@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.

Provide `bin/nuance import` and ngram indexes for sources

Summary:
Ref T10537. More infrastructure:

- Put a `bin/nuance` in place with `bin/nuance import`. This has no useful behavior yet.
- Allow sources to be searched by substring. This supports `bin/nuance import --source whatever` so you don't have to dig up PHIDs.

Test Plan:
- Applied migrations.
- Ran `bin/nuance import --source ...` (no meaningful effect, but works fine).
- Searched for sources by substring in the UI.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10537

Differential Revision: https://secure.phabricator.com/D15436

+241 -17
+1
bin/nuance
··· 1 + ../scripts/setup/manage_nuance.php
+7
resources/sql/autopatches/20160308.nuance.03.sourcen.sql
··· 1 + CREATE TABLE {$NAMESPACE}_nuance.nuance_sourcename_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/20160308.nuance.04.sourcei.php
··· 1 + <?php 2 + 3 + $table = new NuanceSource(); 4 + 5 + foreach (new LiskMigrationIterator($table) as $source) { 6 + PhabricatorSearchWorker::queueDocumentForIndexing( 7 + $source->getPHID(), 8 + array( 9 + 'force' => true, 10 + )); 11 + }
+2
resources/sql/autopatches/20160308.nuance.05.sourcename.sql
··· 1 + ALTER TABLE {$NAMESPACE}_nuance.nuance_source 2 + CHANGE name name VARCHAR(255) NOT NULL COLLATE {$COLLATE_SORT};
+21
scripts/setup/manage_nuance.php
··· 1 + #!/usr/bin/env php 2 + <?php 3 + 4 + $root = dirname(dirname(dirname(__FILE__))); 5 + require_once $root.'/scripts/__init_script__.php'; 6 + 7 + $args = new PhutilArgumentParser($argv); 8 + $args->setTagline(pht('manage Nuance')); 9 + $args->setSynopsis(<<<EOSYNOPSIS 10 + **nuance** __command__ [__options__] 11 + Manage and debug Nuance. 12 + 13 + EOSYNOPSIS 14 + ); 15 + $args->parseStandardArguments(); 16 + 17 + $workflows = id(new PhutilClassMapQuery()) 18 + ->setAncestorClass('NuanceManagementWorkflow') 19 + ->execute(); 20 + $workflows[] = new PhutilHelpArgumentWorkflow(); 21 + $args->parseWorkflows($workflows);
+7
src/__phutil_library_map__.php
··· 1434 1434 'NuanceItemTransactionComment' => 'applications/nuance/storage/NuanceItemTransactionComment.php', 1435 1435 'NuanceItemTransactionQuery' => 'applications/nuance/query/NuanceItemTransactionQuery.php', 1436 1436 'NuanceItemViewController' => 'applications/nuance/controller/NuanceItemViewController.php', 1437 + 'NuanceManagementImportWorkflow' => 'applications/nuance/management/NuanceManagementImportWorkflow.php', 1438 + 'NuanceManagementWorkflow' => 'applications/nuance/management/NuanceManagementWorkflow.php', 1437 1439 'NuancePhabricatorFormSourceDefinition' => 'applications/nuance/source/NuancePhabricatorFormSourceDefinition.php', 1438 1440 'NuanceQuery' => 'applications/nuance/query/NuanceQuery.php', 1439 1441 'NuanceQueue' => 'applications/nuance/storage/NuanceQueue.php', ··· 1473 1475 'NuanceSourceEditor' => 'applications/nuance/editor/NuanceSourceEditor.php', 1474 1476 'NuanceSourceListController' => 'applications/nuance/controller/NuanceSourceListController.php', 1475 1477 'NuanceSourceManageCapability' => 'applications/nuance/capability/NuanceSourceManageCapability.php', 1478 + 'NuanceSourceNameNgrams' => 'applications/nuance/storage/NuanceSourceNameNgrams.php', 1476 1479 'NuanceSourcePHIDType' => 'applications/nuance/phid/NuanceSourcePHIDType.php', 1477 1480 'NuanceSourceQuery' => 'applications/nuance/query/NuanceSourceQuery.php', 1478 1481 'NuanceSourceSearchEngine' => 'applications/nuance/query/NuanceSourceSearchEngine.php', ··· 5682 5685 'NuanceItemTransactionComment' => 'PhabricatorApplicationTransactionComment', 5683 5686 'NuanceItemTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 5684 5687 'NuanceItemViewController' => 'NuanceController', 5688 + 'NuanceManagementImportWorkflow' => 'NuanceManagementWorkflow', 5689 + 'NuanceManagementWorkflow' => 'PhabricatorManagementWorkflow', 5685 5690 'NuancePhabricatorFormSourceDefinition' => 'NuanceSourceDefinition', 5686 5691 'NuanceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 5687 5692 'NuanceQueue' => array( ··· 5721 5726 'NuanceDAO', 5722 5727 'PhabricatorApplicationTransactionInterface', 5723 5728 'PhabricatorPolicyInterface', 5729 + 'PhabricatorNgramsInterface', 5724 5730 ), 5725 5731 'NuanceSourceActionController' => 'NuanceController', 5726 5732 'NuanceSourceController' => 'NuanceController', ··· 5733 5739 'NuanceSourceEditor' => 'PhabricatorApplicationTransactionEditor', 5734 5740 'NuanceSourceListController' => 'NuanceSourceController', 5735 5741 'NuanceSourceManageCapability' => 'PhabricatorPolicyCapability', 5742 + 'NuanceSourceNameNgrams' => 'PhabricatorSearchNgrams', 5736 5743 'NuanceSourcePHIDType' => 'PhabricatorPHIDType', 5737 5744 'NuanceSourceQuery' => 'NuanceQuery', 5738 5745 'NuanceSourceSearchEngine' => 'PhabricatorApplicationSearchEngine',
+1 -1
src/applications/almanac/storage/AlmanacDevice.php
··· 246 246 } 247 247 248 248 249 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 249 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 250 250 251 251 252 252 public function newNgrams() {
+1 -1
src/applications/almanac/storage/AlmanacNamespace.php
··· 210 210 } 211 211 212 212 213 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 213 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 214 214 215 215 216 216 public function newNgrams() {
+1 -1
src/applications/almanac/storage/AlmanacNetwork.php
··· 116 116 } 117 117 118 118 119 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 119 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 120 120 121 121 122 122 public function newNgrams() {
+1 -1
src/applications/almanac/storage/AlmanacService.php
··· 251 251 } 252 252 253 253 254 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 254 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 255 255 256 256 257 257 public function newNgrams() {
+1 -1
src/applications/drydock/storage/DrydockBlueprint.php
··· 350 350 } 351 351 352 352 353 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 353 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 354 354 355 355 356 356 public function newNgrams() {
+1 -1
src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php
··· 197 197 } 198 198 199 199 200 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 200 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 201 201 202 202 203 203 public function newNgrams() {
+4
src/applications/nuance/editor/NuanceSourceEditor.php
··· 11 11 return pht('Nuance Sources'); 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
+50
src/applications/nuance/management/NuanceManagementImportWorkflow.php
··· 1 + <?php 2 + 3 + final class NuanceManagementImportWorkflow 4 + extends NuanceManagementWorkflow { 5 + 6 + protected function didConstruct() { 7 + $this 8 + ->setName('import') 9 + ->setExamples('**import** [__options__]') 10 + ->setSynopsis(pht('Import data from a source.')) 11 + ->setArguments( 12 + array( 13 + array( 14 + 'name' => 'source', 15 + 'param' => 'source', 16 + 'help' => pht('Choose which source to import.'), 17 + ), 18 + )); 19 + } 20 + 21 + public function execute(PhutilArgumentParser $args) { 22 + $source = $this->loadSource($args, 'source'); 23 + 24 + $definition = $source->getDefinition() 25 + ->setViewer($this->getViewer()) 26 + ->setSource($source); 27 + 28 + if (!$definition->hasImportCursors()) { 29 + throw new PhutilArgumentUsageException( 30 + pht( 31 + 'This source ("%s") does not expose import cursors.', 32 + $source->getName())); 33 + } 34 + 35 + $cursors = $definition->getImportCursors(); 36 + if (!$cursors) { 37 + throw new PhutilArgumentUsageException( 38 + pht( 39 + 'This source ("%s") does not have any import cursors.', 40 + $source->getName())); 41 + } 42 + 43 + echo tsprintf( 44 + "%s\n", 45 + pht('OK, but actual importing is not implemented yet.')); 46 + 47 + return 0; 48 + } 49 + 50 + }
+67
src/applications/nuance/management/NuanceManagementWorkflow.php
··· 1 + <?php 2 + 3 + abstract class NuanceManagementWorkflow 4 + extends PhabricatorManagementWorkflow { 5 + 6 + protected function loadSource(PhutilArgumentParser $argv, $key) { 7 + $source = $argv->getArg($key); 8 + if (!strlen($source)) { 9 + throw new PhutilArgumentUsageException( 10 + pht( 11 + 'Specify a source with %s.', 12 + '--'.$key)); 13 + } 14 + 15 + $query = id(new NuanceSourceQuery()) 16 + ->setViewer($this->getViewer()) 17 + ->setRaisePolicyExceptions(true); 18 + 19 + $type_unknown = PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN; 20 + 21 + if (ctype_digit($source)) { 22 + $kind = 'id'; 23 + $query->withIDs(array($source)); 24 + } else if (phid_get_type($source) !== $type_unknown) { 25 + $kind = 'phid'; 26 + $query->withPHIDs($source); 27 + } else { 28 + $kind = 'name'; 29 + $query->withNameNgrams($source); 30 + } 31 + 32 + $sources = $query->execute(); 33 + 34 + if (!$sources) { 35 + switch ($kind) { 36 + case 'id': 37 + $message = pht( 38 + 'No source exists with ID "%s".', 39 + $source); 40 + break; 41 + case 'phid': 42 + $message = pht( 43 + 'No source exists with PHID "%s".', 44 + $source); 45 + break; 46 + default: 47 + $message = pht( 48 + 'No source exists with a name matching "%s".', 49 + $source); 50 + break; 51 + } 52 + 53 + throw new PhutilArgumentUsageException($message); 54 + } else if (count($sources) > 1) { 55 + $message = pht( 56 + 'More than one source matches "%s". Choose a narrower query, or '. 57 + 'use an ID or PHID to select a source. Matching sources: %s.', 58 + $source, 59 + implode(', ', mpull($sources, 'getName'))); 60 + 61 + throw new PhutilArgumentUsageException($message); 62 + } 63 + 64 + return head($sources); 65 + } 66 + 67 + }
+16 -6
src/applications/nuance/query/NuanceSourceQuery.php
··· 34 34 return $this; 35 35 } 36 36 37 + public function withNameNgrams($ngrams) { 38 + return $this->withNgramsConstraint( 39 + new NuanceSourceNameNgrams(), 40 + $ngrams); 41 + } 42 + 37 43 public function newResultObject() { 38 44 return new NuanceSource(); 45 + } 46 + 47 + protected function getPrimaryTableAlias() { 48 + return 'source'; 39 49 } 40 50 41 51 protected function loadPage() { ··· 65 75 if ($this->types !== null) { 66 76 $where[] = qsprintf( 67 77 $conn, 68 - 'type IN (%Ls)', 78 + 'source.type IN (%Ls)', 69 79 $this->types); 70 80 } 71 81 72 82 if ($this->ids !== null) { 73 83 $where[] = qsprintf( 74 84 $conn, 75 - 'id IN (%Ld)', 85 + 'source.id IN (%Ld)', 76 86 $this->ids); 77 87 } 78 88 79 89 if ($this->phids !== null) { 80 90 $where[] = qsprintf( 81 91 $conn, 82 - 'phid IN (%Ls)', 92 + 'source.phid IN (%Ls)', 83 93 $this->phids); 84 94 } 85 95 86 96 if ($this->isDisabled !== null) { 87 97 $where[] = qsprintf( 88 98 $conn, 89 - 'isDisabled = %d', 99 + 'source.isDisabled = %d', 90 100 (int)$this->isDisabled); 91 101 } 92 102 ··· 106 116 } else { 107 117 $where[] = qsprintf( 108 118 $conn, 109 - 'type IN (%Ls)', 119 + 'source.type IN (%Ls)', 110 120 $cursor_types); 111 121 } 112 122 } else { ··· 115 125 } else { 116 126 $where[] = qsprintf( 117 127 $conn, 118 - 'type NOT IN (%Ls)', 128 + 'source.type NOT IN (%Ls)', 119 129 $cursor_types); 120 130 } 121 131 }
+10 -1
src/applications/nuance/query/NuanceSourceSearchEngine.php
··· 18 18 protected function buildQueryFromParameters(array $map) { 19 19 $query = $this->newQuery(); 20 20 21 + if ($map['match'] !== null) { 22 + $query->withNameNgrams($map['match']); 23 + } 24 + 21 25 return $query; 22 26 } 23 27 24 28 protected function buildCustomSearchFields() { 25 - return array(); 29 + return array( 30 + id(new PhabricatorSearchTextField()) 31 + ->setLabel(pht('Name Contains')) 32 + ->setKey('match') 33 + ->setDescription(pht('Search for sources by name substring.')), 34 + ); 26 35 } 27 36 28 37 protected function getURI($path) {
+14 -2
src/applications/nuance/storage/NuanceSource.php
··· 3 3 final class NuanceSource extends NuanceDAO 4 4 implements 5 5 PhabricatorApplicationTransactionInterface, 6 - PhabricatorPolicyInterface { 6 + PhabricatorPolicyInterface, 7 + PhabricatorNgramsInterface { 7 8 8 9 protected $name; 9 10 protected $type; ··· 23 24 'data' => self::SERIALIZATION_JSON, 24 25 ), 25 26 self::CONFIG_COLUMN_SCHEMA => array( 26 - 'name' => 'text255?', 27 + 'name' => 'sort255', 27 28 'type' => 'text32', 28 29 'mailKey' => 'bytes20', 29 30 'isDisabled' => 'bool', ··· 130 131 131 132 public function describeAutomaticCapability($capability) { 132 133 return null; 134 + } 135 + 136 + 137 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 138 + 139 + 140 + public function newNgrams() { 141 + return array( 142 + id(new NuanceSourceNameNgrams()) 143 + ->setValue($this->getName()), 144 + ); 133 145 } 134 146 135 147 }
+18
src/applications/nuance/storage/NuanceSourceNameNgrams.php
··· 1 + <?php 2 + 3 + final class NuanceSourceNameNgrams 4 + extends PhabricatorSearchNgrams { 5 + 6 + public function getNgramKey() { 7 + return 'sourcename'; 8 + } 9 + 10 + public function getColumnName() { 11 + return 'name'; 12 + } 13 + 14 + public function getApplicationName() { 15 + return 'nuance'; 16 + } 17 + 18 + }
+1 -1
src/applications/owners/storage/PhabricatorOwnersPackage.php
··· 451 451 } 452 452 453 453 454 - /* -( PhabricatorNgramInterface )------------------------------------------ */ 454 + /* -( PhabricatorNgramsInterface )----------------------------------------- */ 455 455 456 456 457 457 public function newNgrams() {
+6 -1
src/infrastructure/daemon/workers/PhabricatorTriggerDaemon.php
··· 430 430 // cursors. 431 431 if (!$this->nuanceCursors) { 432 432 $source = array_pop($this->nuanceSources); 433 - $cursors = $source->getImportCursors(); 433 + 434 + $definition = $source->getDefinition() 435 + ->setViewer($this->getViewer()) 436 + ->setSource($source); 437 + 438 + $cursors = $definition->getImportCursors(); 434 439 $this->nuanceCursors = array_reverse($cursors); 435 440 } 436 441