mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 12:00:55 +01:00
Cheat my way through the rest of the typeahead datasources
Summary: Ref T5750. These are a pain to modernize and most don't matter, so cheat: - Mark a bunch nonbrowsable, including some that probably should be browsable but which I don't want to deal with for now. - For static datasources, add an easy server-side filter (this isn't really cheating, and is appropriate for the status/priority/application datasources). - Make composite sources browsable if their components are browsable. Test Plan: - Tried to browse an unbrowsable source, got a 404. - Browsed a composite source. - Browsed static sources (priority/status/applications). - Browsed normal sources (people/projects). Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5750 Differential Revision: https://secure.phabricator.com/D12438
This commit is contained in:
parent
5eb496bb3e
commit
7db362a4b6
16 changed files with 162 additions and 17 deletions
|
@ -3,6 +3,12 @@
|
|||
final class AlmanacInterfaceDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: We should make this browsable, but need to make the result set
|
||||
// orderable by device name.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type an interface name...');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
final class DiffusionArcanistProjectDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: We should probably make this browsable, or maybe remove it.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type an arcanist project name...');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
final class DiffusionSymbolDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// This is slightly involved to make browsable, and browsing symbols
|
||||
// does not seem likely to be very useful in any real software project.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a symbol name...');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
final class HarbormasterBuildDependencyDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: This should be browsable, but fixing it is involved.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type another build step name...');
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
final class LegalpadDocumentDatasource extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: This should be made browsable.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a document name...');
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
final class PhabricatorMacroDatasource extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: This should be made browsable.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a macro name...');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
final class PhabricatorMailingListDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: Make this browsable if we don't delete it before then.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a mailing list name...');
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ final class ManiphestTaskPriorityDatasource
|
|||
->setName($name);
|
||||
}
|
||||
|
||||
return $results;
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,6 @@ final class ManiphestTaskStatusDatasource
|
|||
->setName($name);
|
||||
}
|
||||
|
||||
return $results;
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ final class PhabricatorApplicationDatasource
|
|||
->setImageSprite('phabricator-search-icon '.$img);
|
||||
}
|
||||
|
||||
return $results;
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
final class PhabricatorMetaMTAApplicationEmailDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: Make this browsable.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type an application email address...');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
final class PhabricatorOwnersPackageDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// TODO: Make this browsable.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a package name...');
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ final class PhabricatorTypeaheadModularDatasourceController
|
|||
if (isset($sources[$class])) {
|
||||
$source = $sources[$class];
|
||||
$source->setParameters($request->getRequestData());
|
||||
$source->setViewer($viewer);
|
||||
|
||||
// NOTE: Wrapping the source in a Composite datasource ensures we perform
|
||||
// application visibility checks for the viewer, so we do not need to do
|
||||
|
@ -40,6 +41,10 @@ final class PhabricatorTypeaheadModularDatasourceController
|
|||
$hard_limit = 1000;
|
||||
|
||||
if ($is_browse) {
|
||||
if (!$composite->isBrowsable()) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$limit = 10;
|
||||
$offset = $request->getInt('offset');
|
||||
|
||||
|
|
|
@ -3,8 +3,20 @@
|
|||
abstract class PhabricatorTypeaheadCompositeDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
private $usable;
|
||||
|
||||
abstract public function getComponentDatasources();
|
||||
|
||||
public function isBrowsable() {
|
||||
foreach ($this->getUsableDatasources() as $datasource) {
|
||||
if (!$datasource->isBrowsable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::isBrowsable();
|
||||
}
|
||||
|
||||
public function getDatasourceApplicationClass() {
|
||||
return null;
|
||||
}
|
||||
|
@ -43,6 +55,7 @@ abstract class PhabricatorTypeaheadCompositeDatasource
|
|||
}
|
||||
|
||||
private function getUsableDatasources() {
|
||||
if ($this->usable === null) {
|
||||
$sources = $this->getComponentDatasources();
|
||||
|
||||
$usable = array();
|
||||
|
@ -61,8 +74,10 @@ abstract class PhabricatorTypeaheadCompositeDatasource
|
|||
|
||||
$usable[] = $source;
|
||||
}
|
||||
$this->usable = $usable;
|
||||
}
|
||||
|
||||
return $usable;
|
||||
return $this->usable;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -102,4 +102,75 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
|||
->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Can the user browse through results from this datasource?
|
||||
*
|
||||
* Browsable datasources allow the user to switch from typeahead mode to
|
||||
* a browse mode where they can scroll through all results.
|
||||
*
|
||||
* By default, datasources are browsable, but some datasources can not
|
||||
* generate a meaningful result set or can't filter results on the server.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBrowsable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter a list of results, removing items which don't match the query
|
||||
* tokens.
|
||||
*
|
||||
* This is useful for datasources which return a static list of hard-coded
|
||||
* or configured results and can't easily do query filtering in a real
|
||||
* query class. Instead, they can just build the entire result set and use
|
||||
* this method to filter it.
|
||||
*
|
||||
* For datasources backed by database objects, this is often much less
|
||||
* efficient than filtering at the query level.
|
||||
*
|
||||
* @param list<PhabricatorTypeaheadResult> List of typeahead results.
|
||||
* @return list<PhabricatorTypeaheadResult> Filtered results.
|
||||
*/
|
||||
protected function filterResultsAgainstTokens(array $results) {
|
||||
$tokens = $this->getTokens();
|
||||
if (!$tokens) {
|
||||
return $results;
|
||||
}
|
||||
|
||||
$map = array();
|
||||
foreach ($tokens as $token) {
|
||||
$map[$token] = strlen($token);
|
||||
}
|
||||
|
||||
foreach ($results as $key => $result) {
|
||||
$rtokens = self::tokenizeString($result->getName());
|
||||
|
||||
// For each token in the query, we need to find a match somewhere
|
||||
// in the result name.
|
||||
foreach ($map as $token => $length) {
|
||||
// Look for a match.
|
||||
$match = false;
|
||||
foreach ($rtokens as $rtoken) {
|
||||
if (!strncmp($rtoken, $token, $length)) {
|
||||
// This part of the result name has the query token as a prefix.
|
||||
$match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$match) {
|
||||
// We didn't find a match for this query token, so throw the result
|
||||
// away. Try with the next result.
|
||||
unset($results[$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
final class PhabricatorTypeaheadMonogramDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function isBrowsable() {
|
||||
// This source isn't meaningfully browsable. Although it's technically
|
||||
// possible to let users browse through every object on an install, there
|
||||
// is no use case for it and it doesn't seem worth building.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type an object name...');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue