mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 21:02:41 +01:00
Make owners typeahead mostly reasonable
Summary: Ref T8320. Fixes T8427. This is still a little funky because Owners has weird name rules, but should fix the bugs (unselectable packages) in T8427. Test Plan: Browsed Owners typaheads, used various search functions. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T8320, T8427 Differential Revision: https://secure.phabricator.com/D13349
This commit is contained in:
parent
b12f13efd8
commit
1851ca2d71
3 changed files with 110 additions and 92 deletions
|
@ -7,6 +7,7 @@ final class PhabricatorOwnersPackageQuery
|
||||||
private $phids;
|
private $phids;
|
||||||
private $ownerPHIDs;
|
private $ownerPHIDs;
|
||||||
private $repositoryPHIDs;
|
private $repositoryPHIDs;
|
||||||
|
private $namePrefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owners are direct owners, and members of owning projects.
|
* Owners are direct owners, and members of owning projects.
|
||||||
|
@ -31,62 +32,59 @@ final class PhabricatorOwnersPackageQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
public function withNamePrefix($prefix) {
|
||||||
$table = new PhabricatorOwnersPackage();
|
$this->namePrefix = $prefix;
|
||||||
$conn_r = $table->establishConnection('r');
|
return $this;
|
||||||
|
|
||||||
$data = queryfx_all(
|
|
||||||
$conn_r,
|
|
||||||
'SELECT p.* FROM %T p %Q %Q %Q %Q',
|
|
||||||
$table->getTableName(),
|
|
||||||
$this->buildJoinClause($conn_r),
|
|
||||||
$this->buildWhereClause($conn_r),
|
|
||||||
$this->buildOrderClause($conn_r),
|
|
||||||
$this->buildLimitClause($conn_r));
|
|
||||||
|
|
||||||
return $table->loadAllFromArray($data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildJoinClause(AphrontDatabaseConnection $conn_r) {
|
public function newResultObject() {
|
||||||
$joins = array();
|
return new PhabricatorOwnersPackage();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadPage() {
|
||||||
|
return $this->loadStandardPage(new PhabricatorOwnersPackage());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
|
$joins = parent::buildJoinClauseParts($conn);
|
||||||
|
|
||||||
if ($this->ownerPHIDs !== null) {
|
if ($this->ownerPHIDs !== null) {
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'JOIN %T o ON o.packageID = p.id',
|
'JOIN %T o ON o.packageID = p.id',
|
||||||
id(new PhabricatorOwnersOwner())->getTableName());
|
id(new PhabricatorOwnersOwner())->getTableName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->repositoryPHIDs !== null) {
|
if ($this->repositoryPHIDs !== null) {
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'JOIN %T rpath ON rpath.packageID = p.id',
|
'JOIN %T rpath ON rpath.packageID = p.id',
|
||||||
id(new PhabricatorOwnersPath())->getTableName());
|
id(new PhabricatorOwnersPath())->getTableName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(' ', $joins);
|
return $joins;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
$where = array();
|
$where = parent::buildWhereClauseParts($conn);
|
||||||
|
|
||||||
if ($this->phids !== null) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'p.phid IN (%Ls)',
|
'p.phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->ids !== null) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'p.id IN (%Ld)',
|
'p.id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->repositoryPHIDs !== null) {
|
if ($this->repositoryPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'rpath.repositoryPHID IN (%Ls)',
|
'rpath.repositoryPHID IN (%Ls)',
|
||||||
$this->repositoryPHIDs);
|
$this->repositoryPHIDs);
|
||||||
}
|
}
|
||||||
|
@ -94,26 +92,79 @@ final class PhabricatorOwnersPackageQuery
|
||||||
if ($this->ownerPHIDs !== null) {
|
if ($this->ownerPHIDs !== null) {
|
||||||
$base_phids = $this->ownerPHIDs;
|
$base_phids = $this->ownerPHIDs;
|
||||||
|
|
||||||
$query = new PhabricatorProjectQuery();
|
$projects = id(new PhabricatorProjectQuery())
|
||||||
$query->setViewer($this->getViewer());
|
->setViewer($this->getViewer())
|
||||||
$query->withMemberPHIDs($base_phids);
|
->withMemberPHIDs($base_phids)
|
||||||
$projects = $query->execute();
|
->execute();
|
||||||
$project_phids = mpull($projects, 'getPHID');
|
$project_phids = mpull($projects, 'getPHID');
|
||||||
|
|
||||||
$all_phids = array_merge($base_phids, $project_phids);
|
$all_phids = array_merge($base_phids, $project_phids);
|
||||||
|
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'o.userPHID IN (%Ls)',
|
'o.userPHID IN (%Ls)',
|
||||||
$all_phids);
|
$all_phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
$where[] = $this->buildPagingClause($conn_r);
|
if (strlen($this->namePrefix)) {
|
||||||
return $this->formatWhereClause($where);
|
// NOTE: This is a hacky mess, but this column is currently case
|
||||||
|
// sensitive and unique.
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'LOWER(p.name) LIKE %>',
|
||||||
|
phutil_utf8_strtolower($this->namePrefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $where;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function shouldGroupQueryResultRows() {
|
||||||
|
if ($this->repositoryPHIDs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->ownerPHIDs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::shouldGroupQueryResultRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuiltinOrders() {
|
||||||
|
return array(
|
||||||
|
'name' => array(
|
||||||
|
'vector' => array('name'),
|
||||||
|
'name' => pht('Name'),
|
||||||
|
),
|
||||||
|
) + parent::getBuiltinOrders();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOrderableColumns() {
|
||||||
|
return parent::getOrderableColumns() + array(
|
||||||
|
'name' => array(
|
||||||
|
'table' => $this->getPrimaryTableAlias(),
|
||||||
|
'column' => 'name',
|
||||||
|
'type' => 'string',
|
||||||
|
'unique' => true,
|
||||||
|
'reverse' => true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPagingValueMap($cursor, array $keys) {
|
||||||
|
$package = $this->loadCursorObject($cursor);
|
||||||
|
return array(
|
||||||
|
'id' => $package->getID(),
|
||||||
|
'name' => $package->getName(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getQueryApplicationClass() {
|
public function getQueryApplicationClass() {
|
||||||
return 'PhabricatorOwnersApplication';
|
return 'PhabricatorOwnersApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getPrimaryTableAlias() {
|
||||||
|
return 'p';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,68 +11,39 @@ final class PhabricatorOwnersPackageSearchEngine
|
||||||
return 'PhabricatorOwnersApplication';
|
return 'PhabricatorOwnersApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
public function newQuery() {
|
||||||
$saved = new PhabricatorSavedQuery();
|
return new PhabricatorOwnersPackageQuery();
|
||||||
|
|
||||||
$saved->setParameter(
|
|
||||||
'ownerPHIDs',
|
|
||||||
$this->readUsersFromRequest(
|
|
||||||
$request,
|
|
||||||
'owners',
|
|
||||||
array(
|
|
||||||
PhabricatorProjectProjectPHIDType::TYPECONST,
|
|
||||||
)));
|
|
||||||
|
|
||||||
$saved->setParameter(
|
|
||||||
'repositoryPHIDs',
|
|
||||||
$this->readPHIDsFromRequest(
|
|
||||||
$request,
|
|
||||||
'repositories',
|
|
||||||
array(
|
|
||||||
PhabricatorRepositoryRepositoryPHIDType::TYPECONST,
|
|
||||||
)));
|
|
||||||
|
|
||||||
return $saved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
protected function buildCustomSearchFields() {
|
||||||
$query = id(new PhabricatorOwnersPackageQuery());
|
return array(
|
||||||
|
id(new PhabricatorSearchDatasourceField())
|
||||||
|
->setLabel(pht('Owners'))
|
||||||
|
->setKey('ownerPHIDs')
|
||||||
|
->setAliases(array('owner', 'owners'))
|
||||||
|
->setDatasource(new PhabricatorProjectOrUserDatasource()),
|
||||||
|
id(new PhabricatorSearchDatasourceField())
|
||||||
|
->setLabel(pht('Repositories'))
|
||||||
|
->setKey('repositoryPHIDs')
|
||||||
|
->setAliases(array('repository', 'repositories'))
|
||||||
|
->setDatasource(new DiffusionRepositoryDatasource()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$owner_phids = $saved->getParameter('ownerPHIDs', array());
|
protected function buildQueryFromParameters(array $map) {
|
||||||
if ($owner_phids) {
|
$query = $this->newQuery();
|
||||||
$query->withOwnerPHIDs($owner_phids);
|
|
||||||
|
if ($map['ownerPHIDs']) {
|
||||||
|
$query->withOwnerPHIDs($map['ownerPHIDs']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$repository_phids = $saved->getParameter('repositoryPHIDs', array());
|
if ($map['repositoryPHIDs']) {
|
||||||
if ($repository_phids) {
|
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
|
||||||
$query->withRepositoryPHIDs($repository_phids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSearchForm(
|
|
||||||
AphrontFormView $form,
|
|
||||||
PhabricatorSavedQuery $saved) {
|
|
||||||
|
|
||||||
$owner_phids = $saved->getParameter('ownerPHIDs', array());
|
|
||||||
$repository_phids = $saved->getParameter('repositoryPHIDs', array());
|
|
||||||
|
|
||||||
$form
|
|
||||||
->appendControl(
|
|
||||||
id(new AphrontFormTokenizerControl())
|
|
||||||
->setDatasource(new PhabricatorProjectOrUserDatasource())
|
|
||||||
->setName('owners')
|
|
||||||
->setLabel(pht('Owners'))
|
|
||||||
->setValue($owner_phids))
|
|
||||||
->appendControl(
|
|
||||||
id(new AphrontFormTokenizerControl())
|
|
||||||
->setDatasource(new DiffusionRepositoryDatasource())
|
|
||||||
->setName('repositories')
|
|
||||||
->setLabel(pht('Repositories'))
|
|
||||||
->setValue($repository_phids));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getURI($path) {
|
protected function getURI($path) {
|
||||||
return '/owners/'.$path;
|
return '/owners/'.$path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,6 @@
|
||||||
final class PhabricatorOwnersPackageDatasource
|
final class PhabricatorOwnersPackageDatasource
|
||||||
extends PhabricatorTypeaheadDatasource {
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
public function isBrowsable() {
|
|
||||||
// TODO: Make this browsable.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBrowseTitle() {
|
public function getBrowseTitle() {
|
||||||
return pht('Browse Packages');
|
return pht('Browse Packages');
|
||||||
}
|
}
|
||||||
|
@ -26,10 +21,11 @@ final class PhabricatorOwnersPackageDatasource
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
|
|
||||||
$packages = id(new PhabricatorOwnersPackageQuery())
|
$query = id(new PhabricatorOwnersPackageQuery())
|
||||||
->setViewer($viewer)
|
->withNamePrefix($raw_query)
|
||||||
->execute();
|
->setOrder('name');
|
||||||
|
|
||||||
|
$packages = $this->executeQuery($query);
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
$results[] = id(new PhabricatorTypeaheadResult())
|
$results[] = id(new PhabricatorTypeaheadResult())
|
||||||
->setName($package->getName())
|
->setName($package->getName())
|
||||||
|
@ -37,7 +33,7 @@ final class PhabricatorOwnersPackageDatasource
|
||||||
->setPHID($package->getPHID());
|
->setPHID($package->getPHID());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $this->filterResultsAgainstTokens($results);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue