@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+130 -43
+7
resources/sql/autopatches/20160221.almanac.1.devicen.sql
··· 1 + CREATE TABLE {$NAMESPACE}_almanac.almanac_devicename_ngrams ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + objectID INT UNSIGNED NOT NULL, 4 + ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, 5 + KEY `key_object` (objectID), 6 + KEY `key_ngram` (ngram, objectID) 7 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+11
resources/sql/autopatches/20160221.almanac.2.devicei.php
··· 1 + <?php 2 + 3 + $table = new AlmanacDevice(); 4 + 5 + foreach (new LiskMigrationIterator($table) as $device) { 6 + PhabricatorSearchWorker::queueDocumentForIndexing( 7 + $device->getPHID(), 8 + array( 9 + 'force' => true, 10 + )); 11 + }
+3
src/__phutil_library_map__.php
··· 38 38 'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php', 39 39 'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php', 40 40 'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php', 41 + 'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php', 41 42 'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php', 42 43 'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php', 43 44 'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php', ··· 4011 4012 'PhabricatorSSHPublicKeyInterface', 4012 4013 'AlmanacPropertyInterface', 4013 4014 'PhabricatorDestructibleInterface', 4015 + 'PhabricatorNgramsInterface', 4014 4016 ), 4015 4017 'AlmanacDeviceController' => 'AlmanacController', 4016 4018 'AlmanacDeviceEditController' => 'AlmanacDeviceController', 4017 4019 'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor', 4018 4020 'AlmanacDeviceListController' => 'AlmanacDeviceController', 4021 + 'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams', 4019 4022 'AlmanacDevicePHIDType' => 'PhabricatorPHIDType', 4020 4023 'AlmanacDeviceQuery' => 'AlmanacQuery', 4021 4024 'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
+3
src/applications/almanac/customfield/AlmanacCoreCustomField.php
··· 17 17 } 18 18 19 19 public function createFields($object) { 20 + if (!$object->getID()) { 21 + return array(); 22 + } 20 23 21 24 $specs = $object->getAlmanacPropertyFieldSpecifications(); 22 25
+4 -2
src/applications/almanac/editor/AlmanacDeviceEditor.php
··· 11 11 return pht('Almanac Device'); 12 12 } 13 13 14 + protected function supportsSearch() { 15 + return true; 16 + } 17 + 14 18 public function getTransactionTypes() { 15 19 $types = parent::getTransactionTypes(); 16 20 ··· 302 306 303 307 return $errors; 304 308 } 305 - 306 - 307 309 308 310 }
+55 -25
src/applications/almanac/query/AlmanacDeviceQuery.php
··· 34 34 return $this; 35 35 } 36 36 37 - protected function loadPage() { 38 - $table = new AlmanacDevice(); 39 - $conn_r = $table->establishConnection('r'); 37 + public function withNameNgrams($ngrams) { 38 + return $this->withNgramsConstraint( 39 + new AlmanacDeviceNameNgrams(), 40 + $ngrams); 41 + } 40 42 41 - $data = queryfx_all( 42 - $conn_r, 43 - 'SELECT * FROM %T %Q %Q %Q', 44 - $table->getTableName(), 45 - $this->buildWhereClause($conn_r), 46 - $this->buildOrderClause($conn_r), 47 - $this->buildLimitClause($conn_r)); 43 + public function newResultObject() { 44 + return new AlmanacDevice(); 45 + } 48 46 49 - return $table->loadAllFromArray($data); 47 + protected function loadPage() { 48 + return $this->loadStandardPage($this->newResultObject()); 50 49 } 51 50 52 - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 53 - $where = array(); 51 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 52 + $where = parent::buildWhereClauseParts($conn); 54 53 55 54 if ($this->ids !== null) { 56 55 $where[] = qsprintf( 57 - $conn_r, 58 - 'id IN (%Ld)', 56 + $conn, 57 + 'device.id IN (%Ld)', 59 58 $this->ids); 60 59 } 61 60 62 61 if ($this->phids !== null) { 63 62 $where[] = qsprintf( 64 - $conn_r, 65 - 'phid IN (%Ls)', 63 + $conn, 64 + 'device.phid IN (%Ls)', 66 65 $this->phids); 67 66 } 68 67 ··· 72 71 $hashes[] = PhabricatorHash::digestForIndex($name); 73 72 } 74 73 $where[] = qsprintf( 75 - $conn_r, 76 - 'nameIndex IN (%Ls)', 74 + $conn, 75 + 'device.nameIndex IN (%Ls)', 77 76 $hashes); 78 77 } 79 78 80 79 if ($this->namePrefix !== null) { 81 80 $where[] = qsprintf( 82 - $conn_r, 83 - 'name LIKE %>', 81 + $conn, 82 + 'device.name LIKE %>', 84 83 $this->namePrefix); 85 84 } 86 85 87 86 if ($this->nameSuffix !== null) { 88 87 $where[] = qsprintf( 89 - $conn_r, 90 - 'name LIKE %<', 88 + $conn, 89 + 'device.name LIKE %<', 91 90 $this->nameSuffix); 92 91 } 93 92 94 - $where[] = $this->buildPagingClause($conn_r); 93 + return $where; 94 + } 95 95 96 - return $this->formatWhereClause($where); 96 + protected function getPrimaryTableAlias() { 97 + return 'device'; 98 + } 99 + 100 + public function getOrderableColumns() { 101 + return parent::getOrderableColumns() + array( 102 + 'name' => array( 103 + 'table' => $this->getPrimaryTableAlias(), 104 + 'column' => 'name', 105 + 'type' => 'string', 106 + 'unique' => true, 107 + 'reverse' => true, 108 + ), 109 + ); 110 + } 111 + 112 + protected function getPagingValueMap($cursor, array $keys) { 113 + $device = $this->loadCursorObject($cursor); 114 + return array( 115 + 'id' => $device->getID(), 116 + 'name' => $device->getName(), 117 + ); 118 + } 119 + 120 + public function getBuiltinOrders() { 121 + return array( 122 + 'name' => array( 123 + 'vector' => array('name'), 124 + 'name' => pht('Device Name'), 125 + ), 126 + ) + parent::getBuiltinOrders(); 97 127 } 98 128 99 129 public function getQueryApplicationClass() {
+16 -15
src/applications/almanac/query/AlmanacDeviceSearchEngine.php
··· 11 11 return 'PhabricatorAlmanacApplication'; 12 12 } 13 13 14 - public function buildSavedQueryFromRequest(AphrontRequest $request) { 15 - $saved = new PhabricatorSavedQuery(); 14 + public function newQuery() { 15 + return new AlmanacDeviceQuery(); 16 + } 16 17 17 - return $saved; 18 + protected function buildCustomSearchFields() { 19 + return array( 20 + id(new PhabricatorSearchTextField()) 21 + ->setLabel(pht('Name Contains')) 22 + ->setKey('match') 23 + ->setDescription(pht('Search for devices by name substring.')), 24 + ); 18 25 } 19 26 20 - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 21 - $query = id(new AlmanacDeviceQuery()); 27 + protected function buildQueryFromParameters(array $map) { 28 + $query = $this->newQuery(); 29 + 30 + if ($map['match'] !== null) { 31 + $query->withNameNgrams($map['match']); 32 + } 22 33 23 34 return $query; 24 35 } 25 - 26 - public function buildSearchForm( 27 - AphrontFormView $form, 28 - PhabricatorSavedQuery $saved_query) {} 29 36 30 37 protected function getURI($path) { 31 38 return '/almanac/device/'.$path; ··· 50 57 } 51 58 52 59 return parent::buildSavedQueryFromBuiltin($query_key); 53 - } 54 - 55 - protected function getRequiredHandlePHIDsForResultList( 56 - array $devices, 57 - PhabricatorSavedQuery $query) { 58 - return array(); 59 60 } 60 61 61 62 protected function renderResultList(
+13 -1
src/applications/almanac/storage/AlmanacDevice.php
··· 9 9 PhabricatorProjectInterface, 10 10 PhabricatorSSHPublicKeyInterface, 11 11 AlmanacPropertyInterface, 12 - PhabricatorDestructibleInterface { 12 + PhabricatorDestructibleInterface, 13 + PhabricatorNgramsInterface { 13 14 14 15 protected $name; 15 16 protected $nameIndex; ··· 248 249 } 249 250 250 251 $this->delete(); 252 + } 253 + 254 + 255 + /* -( PhabricatorNgramInterface )------------------------------------------ */ 256 + 257 + 258 + public function newNgrams() { 259 + return array( 260 + id(new AlmanacDeviceNameNgrams()) 261 + ->setValue($this->getName()), 262 + ); 251 263 } 252 264 253 265 }
+18
src/applications/almanac/storage/AlmanacDeviceNameNgrams.php
··· 1 + <?php 2 + 3 + final class AlmanacDeviceNameNgrams 4 + extends PhabricatorSearchNgrams { 5 + 6 + public function getNgramKey() { 7 + return 'devicename'; 8 + } 9 + 10 + public function getColumnName() { 11 + return 'name'; 12 + } 13 + 14 + public function getApplicationName() { 15 + return 'almanac'; 16 + } 17 + 18 + }