diff --git a/src/applications/differential/phid/DifferentialPHIDTypeRevision.php b/src/applications/differential/phid/DifferentialPHIDTypeRevision.php index f576e0e062..9a815e150d 100644 --- a/src/applications/differential/phid/DifferentialPHIDTypeRevision.php +++ b/src/applications/differential/phid/DifferentialPHIDTypeRevision.php @@ -1,78 +1,78 @@ withPHIDs($phids); } public function loadHandles( PhabricatorHandleQuery $query, array $handles, array $objects) { foreach ($handles as $phid => $handle) { $revision = $objects[$phid]; $title = $revision->getTitle(); $id = $revision->getID(); $status = $revision->getStatus(); $handle->setName("D{$id}"); $handle->setURI("/D{$id}"); $handle->setFullName("D{$id}: {$title}"); if ($revision->isClosed()) { $handle->setStatus(PhabricatorObjectHandleStatus::STATUS_CLOSED); } } } public function canLoadNamedObject($name) { return preg_match('/^D\d*[1-9]\d*$/i', $name); } public function loadNamedObjects( PhabricatorObjectQuery $query, array $names) { $id_map = array(); foreach ($names as $name) { $id = (int)substr($name, 1); $id_map[$id][] = $name; } $objects = id(new DifferentialRevisionQuery()) ->setViewer($query->getViewer()) ->withIDs(array_keys($id_map)) ->execute(); $results = array(); foreach ($objects as $id => $object) { foreach (idx($id_map, $id, array()) as $name) { $results[$name] = $object; } } return $results; } } diff --git a/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php b/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php index c84607994f..9afc7c7fa4 100644 --- a/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php +++ b/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php @@ -1,85 +1,85 @@ withPHIDs($phids) ->needProfileImage(true) ->needStatus(true); } public function loadHandles( PhabricatorHandleQuery $query, array $handles, array $objects) { foreach ($handles as $phid => $handle) { $user = $objects[$phid]; $handle->setName($user->getUsername()); $handle->setURI('/p/'.$user->getUsername().'/'); $handle->setFullName( $user->getUsername().' ('.$user->getRealName().')'); $handle->setImageURI($user->loadProfileImageURI()); $handle->setDisabled(!$user->isUserActivated()); if ($user->hasStatus()) { $status = $user->getStatus(); $handle->setStatus($status->getTextStatus()); $handle->setTitle($status->getTerseSummary($query->getViewer())); } } } public function canLoadNamedObject($name) { return preg_match('/^@.+/', $name); } public function loadNamedObjects( PhabricatorObjectQuery $query, array $names) { $id_map = array(); foreach ($names as $name) { $id = substr($name, 1); $id_map[$id][] = $name; } $objects = id(new PhabricatorPeopleQuery()) ->setViewer($query->getViewer()) ->withUsernames(array_keys($id_map)) ->execute(); $results = array(); foreach ($objects as $id => $object) { $username = $object->getUsername(); foreach (idx($id_map, $username, array()) as $name) { $results[$name] = $object; } } return $results; } } diff --git a/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php b/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php index d9a32f7e7a..d68558e6a0 100644 --- a/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php +++ b/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php @@ -1,223 +1,230 @@ setParameter('query', $request->getStr('query')); $saved->setParameter( 'statuses', $this->readListFromRequest($request, 'statuses')); $saved->setParameter( 'types', $this->readListFromRequest($request, 'types')); $saved->setParameter( 'authorPHIDs', $this->readUsersFromRequest($request, 'authorPHIDs')); $saved->setParameter( 'ownerPHIDs', $this->readUsersFromRequest($request, 'ownerPHIDs')); $saved->setParameter( 'withUnowned', $this->readBoolFromRequest($request, 'withUnowned')); $saved->setParameter( 'subscriberPHIDs', $this->readPHIDsFromRequest($request, 'subscriberPHIDs')); $saved->setParameter( 'projectPHIDs', $this->readPHIDsFromRequest($request, 'projectPHIDs')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhabricatorSearchDocumentQuery()) ->withSavedQuery($saved); return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved) { $options = array(); $author_value = null; $owner_value = null; $subscribers_value = null; $project_value = null; $author_phids = $saved->getParameter('authorPHIDs', array()); $owner_phids = $saved->getParameter('ownerPHIDs', array()); $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); $project_phids = $saved->getParameter('projectPHIDs', array()); $all_phids = array_merge( $author_phids, $owner_phids, $subscriber_phids, $project_phids); $all_handles = id(new PhabricatorHandleQuery()) ->setViewer($this->requireViewer()) ->withPHIDs($all_phids) ->execute(); $author_handles = array_select_keys($all_handles, $author_phids); $owner_handles = array_select_keys($all_handles, $owner_phids); $subscriber_handles = array_select_keys($all_handles, $subscriber_phids); $project_handles = array_select_keys($all_handles, $project_phids); $with_unowned = $saved->getParameter('withUnowned', array()); $status_values = $saved->getParameter('statuses', array()); $status_values = array_fuse($status_values); $statuses = array( PhabricatorSearchRelationship::RELATIONSHIP_OPEN => pht('Open'), PhabricatorSearchRelationship::RELATIONSHIP_CLOSED => pht('Closed'), ); $status_control = id(new AphrontFormCheckboxControl()) ->setLabel(pht('Document Status')); foreach ($statuses as $status => $name) { $status_control->addCheckbox( 'statuses[]', $status, $name, isset($status_values[$status])); } $type_values = $saved->getParameter('types', array()); $type_values = array_fuse($type_values); $types = self::getIndexableDocumentTypes(); $types_control = id(new AphrontFormCheckboxControl()) ->setLabel(pht('Document Types')); foreach ($types as $type => $name) { $types_control->addCheckbox( 'types[]', $type, $name, isset($type_values[$type])); } $form ->appendChild( phutil_tag( 'input', array( 'type' => 'hidden', 'name' => 'jump', 'value' => 'no', ))) ->appendChild( id(new AphrontFormTextControl()) ->setLabel('Query') ->setName('query') ->setValue($saved->getParameter('query'))) ->appendChild($status_control) ->appendChild($types_control) ->appendChild( id(new AphrontFormTokenizerControl()) ->setName('authorPHIDs') ->setLabel('Authors') ->setDatasource('/typeahead/common/users/') ->setValue($author_handles)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setName('ownerPHIDs') ->setLabel('Owners') ->setDatasource('/typeahead/common/searchowner/') ->setValue($owner_handles)) ->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'withUnowned', 1, pht('Show only unowned documents.'), $with_unowned)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setName('subscriberPHIDs') ->setLabel('Subscribers') ->setDatasource('/typeahead/common/users/') ->setValue($subscriber_handles)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setName('projectPHIDs') ->setLabel('In Any Project') ->setDatasource('/typeahead/common/projects/') ->setValue($project_handles)); } protected function getURI($path) { return '/search/'.$path; } public function getBuiltinQueryNames() { $names = array( 'all' => pht('All Documents'), 'open' => pht('Open Documents'), 'open-tasks' => pht('Open Tasks'), ); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query; case 'open': return $query->setParameter('statuses', array('open')); case 'open-tasks': return $query ->setParameter('statuses', array('open')) ->setParameter('types', array(ManiphestPHIDTypeTask::TYPECONST)); } return parent::buildSavedQueryFromBuiltin($query_key); } public static function getIndexableDocumentTypes() { // TODO: This is inelegant and not very efficient, but gets us reasonable // results. It would be nice to do this more elegantly. // TODO: We should hide types associated with applications the user can // not access. There's no reasonable way to do this right now. $indexers = id(new PhutilSymbolLoader()) ->setAncestorClass('PhabricatorSearchDocumentIndexer') ->loadObjects(); $types = PhabricatorPHIDType::getAllTypes(); $results = array(); foreach ($types as $type) { $typeconst = $type->getTypeConstant(); foreach ($indexers as $indexer) { $fake_phid = 'PHID-'.$typeconst.'-fake'; if ($indexer->shouldIndexDocumentByPHID($fake_phid)) { $results[$typeconst] = $type->getTypeName(); } } } asort($results); + // Put tasks first, see T4606. + $results = array_select_keys( + $results, + array( + ManiphestPHIDTypeTask::TYPECONST, + )) + $results; + return $results; } }