mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 19:40:55 +01:00
Allow Almanac devices to be queried and sorted by name
Summary: Ref T10205. Ref T10246. This is general modernization, but also supports fixing the interface datasource in T10205. - Update Query. - Update SearchEngine. - Use an ngrams index for searching names efficiently. Test Plan: - Ran migrations. - Searched Almanac devices by name. - Created a new device, searched for it by name. {F1121303} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10205, T10246 Differential Revision: https://secure.phabricator.com/D15319
This commit is contained in:
parent
a4db6f387d
commit
1b6ddae6b2
9 changed files with 133 additions and 46 deletions
7
resources/sql/autopatches/20160221.almanac.1.devicen.sql
Normal file
7
resources/sql/autopatches/20160221.almanac.1.devicen.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_almanac.almanac_devicename_ngrams (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
objectID INT UNSIGNED NOT NULL,
|
||||||
|
ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
KEY `key_object` (objectID),
|
||||||
|
KEY `key_ngram` (ngram, objectID)
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
11
resources/sql/autopatches/20160221.almanac.2.devicei.php
Normal file
11
resources/sql/autopatches/20160221.almanac.2.devicei.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$table = new AlmanacDevice();
|
||||||
|
|
||||||
|
foreach (new LiskMigrationIterator($table) as $device) {
|
||||||
|
PhabricatorSearchWorker::queueDocumentForIndexing(
|
||||||
|
$device->getPHID(),
|
||||||
|
array(
|
||||||
|
'force' => true,
|
||||||
|
));
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ phutil_register_library_map(array(
|
||||||
'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php',
|
'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php',
|
||||||
'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php',
|
'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php',
|
||||||
'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
|
'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
|
||||||
|
'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php',
|
||||||
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
|
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
|
||||||
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
|
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
|
||||||
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
|
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
|
||||||
|
@ -4011,11 +4012,13 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSSHPublicKeyInterface',
|
'PhabricatorSSHPublicKeyInterface',
|
||||||
'AlmanacPropertyInterface',
|
'AlmanacPropertyInterface',
|
||||||
'PhabricatorDestructibleInterface',
|
'PhabricatorDestructibleInterface',
|
||||||
|
'PhabricatorNgramsInterface',
|
||||||
),
|
),
|
||||||
'AlmanacDeviceController' => 'AlmanacController',
|
'AlmanacDeviceController' => 'AlmanacController',
|
||||||
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
|
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
|
||||||
'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor',
|
'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'AlmanacDeviceListController' => 'AlmanacDeviceController',
|
'AlmanacDeviceListController' => 'AlmanacDeviceController',
|
||||||
|
'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams',
|
||||||
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
|
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
|
||||||
'AlmanacDeviceQuery' => 'AlmanacQuery',
|
'AlmanacDeviceQuery' => 'AlmanacQuery',
|
||||||
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
|
|
@ -17,6 +17,9 @@ final class AlmanacCoreCustomField
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createFields($object) {
|
public function createFields($object) {
|
||||||
|
if (!$object->getID()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
$specs = $object->getAlmanacPropertyFieldSpecifications();
|
$specs = $object->getAlmanacPropertyFieldSpecifications();
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ final class AlmanacDeviceEditor
|
||||||
return pht('Almanac Device');
|
return pht('Almanac Device');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function supportsSearch() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTransactionTypes() {
|
public function getTransactionTypes() {
|
||||||
$types = parent::getTransactionTypes();
|
$types = parent::getTransactionTypes();
|
||||||
|
|
||||||
|
@ -303,6 +307,4 @@ final class AlmanacDeviceEditor
|
||||||
return $errors;
|
return $errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,35 +34,34 @@ final class AlmanacDeviceQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
public function withNameNgrams($ngrams) {
|
||||||
$table = new AlmanacDevice();
|
return $this->withNgramsConstraint(
|
||||||
$conn_r = $table->establishConnection('r');
|
new AlmanacDeviceNameNgrams(),
|
||||||
|
$ngrams);
|
||||||
$data = queryfx_all(
|
|
||||||
$conn_r,
|
|
||||||
'SELECT * FROM %T %Q %Q %Q',
|
|
||||||
$table->getTableName(),
|
|
||||||
$this->buildWhereClause($conn_r),
|
|
||||||
$this->buildOrderClause($conn_r),
|
|
||||||
$this->buildLimitClause($conn_r));
|
|
||||||
|
|
||||||
return $table->loadAllFromArray($data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
public function newResultObject() {
|
||||||
$where = array();
|
return new AlmanacDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadPage() {
|
||||||
|
return $this->loadStandardPage($this->newResultObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
|
$where = parent::buildWhereClauseParts($conn);
|
||||||
|
|
||||||
if ($this->ids !== null) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'id IN (%Ld)',
|
'device.id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids !== null) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'phid IN (%Ls)',
|
'device.phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,28 +71,59 @@ final class AlmanacDeviceQuery
|
||||||
$hashes[] = PhabricatorHash::digestForIndex($name);
|
$hashes[] = PhabricatorHash::digestForIndex($name);
|
||||||
}
|
}
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'nameIndex IN (%Ls)',
|
'device.nameIndex IN (%Ls)',
|
||||||
$hashes);
|
$hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->namePrefix !== null) {
|
if ($this->namePrefix !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'name LIKE %>',
|
'device.name LIKE %>',
|
||||||
$this->namePrefix);
|
$this->namePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->nameSuffix !== null) {
|
if ($this->nameSuffix !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'name LIKE %<',
|
'device.name LIKE %<',
|
||||||
$this->nameSuffix);
|
$this->nameSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
$where[] = $this->buildPagingClause($conn_r);
|
return $where;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
protected function getPrimaryTableAlias() {
|
||||||
|
return 'device';
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
$device = $this->loadCursorObject($cursor);
|
||||||
|
return array(
|
||||||
|
'id' => $device->getID(),
|
||||||
|
'name' => $device->getName(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuiltinOrders() {
|
||||||
|
return array(
|
||||||
|
'name' => array(
|
||||||
|
'vector' => array('name'),
|
||||||
|
'name' => pht('Device Name'),
|
||||||
|
),
|
||||||
|
) + parent::getBuiltinOrders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getQueryApplicationClass() {
|
public function getQueryApplicationClass() {
|
||||||
|
|
|
@ -11,22 +11,29 @@ final class AlmanacDeviceSearchEngine
|
||||||
return 'PhabricatorAlmanacApplication';
|
return 'PhabricatorAlmanacApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
public function newQuery() {
|
||||||
$saved = new PhabricatorSavedQuery();
|
return new AlmanacDeviceQuery();
|
||||||
|
|
||||||
return $saved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
protected function buildCustomSearchFields() {
|
||||||
$query = id(new AlmanacDeviceQuery());
|
return array(
|
||||||
|
id(new PhabricatorSearchTextField())
|
||||||
|
->setLabel(pht('Name Contains'))
|
||||||
|
->setKey('match')
|
||||||
|
->setDescription(pht('Search for devices by name substring.')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildQueryFromParameters(array $map) {
|
||||||
|
$query = $this->newQuery();
|
||||||
|
|
||||||
|
if ($map['match'] !== null) {
|
||||||
|
$query->withNameNgrams($map['match']);
|
||||||
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSearchForm(
|
|
||||||
AphrontFormView $form,
|
|
||||||
PhabricatorSavedQuery $saved_query) {}
|
|
||||||
|
|
||||||
protected function getURI($path) {
|
protected function getURI($path) {
|
||||||
return '/almanac/device/'.$path;
|
return '/almanac/device/'.$path;
|
||||||
}
|
}
|
||||||
|
@ -52,12 +59,6 @@ final class AlmanacDeviceSearchEngine
|
||||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getRequiredHandlePHIDsForResultList(
|
|
||||||
array $devices,
|
|
||||||
PhabricatorSavedQuery $query) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function renderResultList(
|
protected function renderResultList(
|
||||||
array $devices,
|
array $devices,
|
||||||
PhabricatorSavedQuery $query,
|
PhabricatorSavedQuery $query,
|
||||||
|
|
|
@ -9,7 +9,8 @@ final class AlmanacDevice
|
||||||
PhabricatorProjectInterface,
|
PhabricatorProjectInterface,
|
||||||
PhabricatorSSHPublicKeyInterface,
|
PhabricatorSSHPublicKeyInterface,
|
||||||
AlmanacPropertyInterface,
|
AlmanacPropertyInterface,
|
||||||
PhabricatorDestructibleInterface {
|
PhabricatorDestructibleInterface,
|
||||||
|
PhabricatorNgramsInterface {
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $nameIndex;
|
protected $nameIndex;
|
||||||
|
@ -250,4 +251,15 @@ final class AlmanacDevice
|
||||||
$this->delete();
|
$this->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorNgramInterface )------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
public function newNgrams() {
|
||||||
|
return array(
|
||||||
|
id(new AlmanacDeviceNameNgrams())
|
||||||
|
->setValue($this->getName()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
18
src/applications/almanac/storage/AlmanacDeviceNameNgrams.php
Normal file
18
src/applications/almanac/storage/AlmanacDeviceNameNgrams.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceNameNgrams
|
||||||
|
extends PhabricatorSearchNgrams {
|
||||||
|
|
||||||
|
public function getNgramKey() {
|
||||||
|
return 'devicename';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColumnName() {
|
||||||
|
return 'name';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'almanac';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue