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

Update Buildable search in Harbormaster

Summary:
Fixes T10011.

- Modernize searching for buildables.
- Prepare for `harbormaster.buildable.search`.
- Allow users to query by status (see T10011).
- Collapse the four weird "commit / diff / revision / repository" fields into two slightly less weird fields with more UI hinting?

Test Plan: {F1131918}

Reviewers: chad

Reviewed By: chad

Subscribers: Luke081515.2

Maniphest Tasks: T10011

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

+107 -135
+1 -1
src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php
··· 29 29 array $handles, 30 30 array $objects) { 31 31 32 - $viewer = $this->getViewer(); 32 + $viewer = $query->getViewer(); 33 33 34 34 $target_phids = array(); 35 35 foreach ($objects as $phid => $object) {
+13
src/applications/harbormaster/query/HarbormasterBuildableQuery.php
··· 7 7 private $phids; 8 8 private $buildablePHIDs; 9 9 private $containerPHIDs; 10 + private $statuses; 10 11 private $manualBuildables; 11 12 12 13 private $needContainerObjects; ··· 40 41 41 42 public function needContainerObjects($need) { 42 43 $this->needContainerObjects = $need; 44 + return $this; 45 + } 46 + 47 + public function withStatuses(array $statuses) { 48 + $this->statuses = $statuses; 43 49 return $this; 44 50 } 45 51 ··· 152 158 $conn, 153 159 'containerPHID in (%Ls)', 154 160 $this->containerPHIDs); 161 + } 162 + 163 + if ($this->statuses !== null) { 164 + $where[] = qsprintf( 165 + $conn, 166 + 'buildableStatus in (%Ls)', 167 + $this->statuses); 155 168 } 156 169 157 170 if ($this->manualBuildables !== null) {
+64 -123
src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php
··· 11 11 return 'PhabricatorHarbormasterApplication'; 12 12 } 13 13 14 - public function buildSavedQueryFromRequest(AphrontRequest $request) { 15 - $saved = new PhabricatorSavedQuery(); 14 + public function newQuery() { 15 + return new HarbormasterBuildableQuery(); 16 + } 16 17 17 - $revisions = $this->readPHIDsFromRequest( 18 - $request, 19 - 'revisions', 20 - array( 21 - DifferentialRevisionPHIDType::TYPECONST, 22 - )); 23 - 24 - $repositories = $this->readPHIDsFromRequest( 25 - $request, 26 - 'repositories', 27 - array( 28 - PhabricatorRepositoryRepositoryPHIDType::TYPECONST, 29 - )); 18 + protected function buildCustomSearchFields() { 19 + return array( 20 + id(new PhabricatorSearchStringListField()) 21 + ->setKey('objectPHIDs') 22 + ->setAliases(array('objects')) 23 + ->setLabel(pht('Objects')) 24 + ->setPlaceholder(pht('rXabcdef, PHID-DIFF-1234, ...')) 25 + ->setDescription(pht('Search for builds of particular objects.')), 26 + id(new PhabricatorSearchStringListField()) 27 + ->setKey('containerPHIDs') 28 + ->setAliases(array('containers')) 29 + ->setLabel(pht('Containers')) 30 + ->setPlaceholder(pht('rXYZ, R123, D456, ...')) 31 + ->setDescription( 32 + pht('Search for builds by containing revision or repository.')), 33 + id(new PhabricatorSearchCheckboxesField()) 34 + ->setKey('statuses') 35 + ->setLabel(pht('Statuses')) 36 + ->setOptions(HarbormasterBuildable::getBuildStatusMap()) 37 + ->setDescription(pht('Search for builds by buildable status.')), 38 + id(new PhabricatorSearchThreeStateField()) 39 + ->setLabel(pht('Manual')) 40 + ->setKey('manual') 41 + ->setDescription( 42 + pht('Search for only manual or automatic buildables.')) 43 + ->setOptions( 44 + pht('(Show All)'), 45 + pht('Show Only Manual Builds'), 46 + pht('Show Only Automated Builds')), 47 + ); 48 + } 30 49 31 - $container_phids = array_merge($revisions, $repositories); 32 - $saved->setParameter('containerPHIDs', $container_phids); 50 + private function resolvePHIDs(array $names) { 51 + $viewer = $this->requireViewer(); 33 52 34 - $commits = $this->readPHIDsFromRequest( 35 - $request, 36 - 'commits', 37 - array( 38 - PhabricatorRepositoryCommitPHIDType::TYPECONST, 39 - )); 53 + $objects = id(new PhabricatorObjectQuery()) 54 + ->setViewer($viewer) 55 + ->withNames($names) 56 + ->execute(); 40 57 41 - $diffs = $this->readListFromRequest($request, 'diffs'); 42 - if ($diffs) { 43 - $diffs = id(new DifferentialDiffQuery()) 44 - ->setViewer($this->requireViewer()) 45 - ->withIDs($diffs) 46 - ->execute(); 47 - $diffs = mpull($diffs, 'getPHID', 'getPHID'); 58 + // TODO: Instead of using string lists, we should ideally be using some 59 + // kind of smart field with resolver logic that can help users type the 60 + // right stuff. For now, just return a bogus value here so nothing matches 61 + // but the form doesn't explode. 62 + if (!$objects) { 63 + return array('-'); 48 64 } 49 65 50 - $buildable_phids = array_merge($commits, $diffs); 51 - $saved->setParameter('buildablePHIDs', $buildable_phids); 52 - 53 - $saved->setParameter( 54 - 'manual', 55 - $this->readBoolFromRequest($request, 'manual')); 56 - 57 - return $saved; 66 + return mpull($objects, 'getPHID'); 58 67 } 59 68 60 - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 61 - $query = id(new HarbormasterBuildableQuery()); 69 + protected function buildQueryFromParameters(array $map) { 70 + $query = $this->newQuery(); 62 71 63 - $container_phids = $saved->getParameter('containerPHIDs', array()); 64 - if ($container_phids) { 65 - $query->withContainerPHIDs($container_phids); 72 + if ($map['objectPHIDs']) { 73 + $phids = $this->resolvePHIDs($map['objectPHIDs']); 74 + if ($phids) { 75 + $query->withBuildablePHIDs($phids); 76 + } 66 77 } 67 78 68 - $buildable_phids = $saved->getParameter('buildablePHIDs', array()); 79 + if ($map['containerPHIDs']) { 80 + $phids = $this->resolvePHIDs($map['containerPHIDs']); 81 + if ($phids) { 82 + $query->withContainerPHIDs($phids); 83 + } 84 + } 69 85 70 - if ($buildable_phids) { 71 - $query->withBuildablePHIDs($buildable_phids); 86 + if ($map['statuses']) { 87 + $query->withStatuses($map['statuses']); 72 88 } 73 89 74 - $manual = $saved->getParameter('manual'); 75 - if ($manual !== null) { 76 - $query->withManualBuildables($manual); 90 + if ($map['manual'] !== null) { 91 + $query->withManualBuildables($map['manual']); 77 92 } 78 93 79 94 return $query; 80 - } 81 - 82 - public function buildSearchForm( 83 - AphrontFormView $form, 84 - PhabricatorSavedQuery $saved_query) { 85 - 86 - $container_phids = $saved_query->getParameter('containerPHIDs', array()); 87 - $buildable_phids = $saved_query->getParameter('buildablePHIDs', array()); 88 - 89 - $all_phids = array_merge($container_phids, $buildable_phids); 90 - 91 - $revision_names = array(); 92 - $diff_names = array(); 93 - $repository_names = array(); 94 - $commit_names = array(); 95 - 96 - if ($all_phids) { 97 - $objects = id(new PhabricatorObjectQuery()) 98 - ->setViewer($this->requireViewer()) 99 - ->withPHIDs($all_phids) 100 - ->execute(); 101 - 102 - foreach ($all_phids as $phid) { 103 - $object = idx($objects, $phid); 104 - if (!$object) { 105 - continue; 106 - } 107 - 108 - if ($object instanceof DifferentialRevision) { 109 - $revision_names[] = 'D'.$object->getID(); 110 - } else if ($object instanceof DifferentialDiff) { 111 - $diff_names[] = $object->getID(); 112 - } else if ($object instanceof PhabricatorRepository) { 113 - $repository_names[] = $object->getMonogram(); 114 - } else if ($object instanceof PhabricatorRepositoryCommit) { 115 - $repository = $object->getRepository(); 116 - $commit_names[] = $repository->formatCommitName( 117 - $object->getCommitIdentifier()); 118 - } 119 - } 120 - } 121 - 122 - $form 123 - ->appendChild( 124 - id(new AphrontFormTextControl()) 125 - ->setLabel(pht('Differential Revisions')) 126 - ->setName('revisions') 127 - ->setValue(implode(', ', $revision_names))) 128 - ->appendChild( 129 - id(new AphrontFormTextControl()) 130 - ->setLabel(pht('Differential Diffs')) 131 - ->setName('diffs') 132 - ->setValue(implode(', ', $diff_names))) 133 - ->appendChild( 134 - id(new AphrontFormTextControl()) 135 - ->setLabel(pht('Repositories')) 136 - ->setName('repositories') 137 - ->setValue(implode(', ', $repository_names))) 138 - ->appendChild( 139 - id(new AphrontFormTextControl()) 140 - ->setLabel(pht('Commits')) 141 - ->setName('commits') 142 - ->setValue(implode(', ', $commit_names))) 143 - ->appendChild( 144 - id(new AphrontFormSelectControl()) 145 - ->setLabel(pht('Origin')) 146 - ->setName('manual') 147 - ->setValue($this->getBoolFromQuery($saved_query, 'manual')) 148 - ->setOptions( 149 - array( 150 - '' => pht('(All Origins)'), 151 - 'true' => pht('Manual Buildables'), 152 - 'false' => pht('Automatic Buildables'), 153 - ))); 154 95 } 155 96 156 97 protected function getURI($path) {
+10 -10
src/applications/harbormaster/storage/HarbormasterBuildable.php
··· 20 20 const STATUS_FAILED = 'failed'; 21 21 22 22 public static function getBuildableStatusName($status) { 23 - switch ($status) { 24 - case self::STATUS_BUILDING: 25 - return pht('Building'); 26 - case self::STATUS_PASSED: 27 - return pht('Passed'); 28 - case self::STATUS_FAILED: 29 - return pht('Failed'); 30 - default: 31 - return pht('Unknown'); 32 - } 23 + $map = self::getBuildStatusMap(); 24 + return idx($map, $status, pht('Unknown ("%s")', $status)); 25 + } 26 + 27 + public static function getBuildStatusMap() { 28 + return array( 29 + self::STATUS_BUILDING => pht('Building'), 30 + self::STATUS_PASSED => pht('Passed'), 31 + self::STATUS_FAILED => pht('Failed'), 32 + ); 33 33 } 34 34 35 35 public static function getBuildableStatusIcon($status) {
+19 -1
src/applications/search/field/PhabricatorSearchStringListField.php
··· 3 3 final class PhabricatorSearchStringListField 4 4 extends PhabricatorSearchField { 5 5 6 + private $placeholder; 7 + 8 + public function setPlaceholder($placeholder) { 9 + $this->placeholder = $placeholder; 10 + return $this; 11 + } 12 + 13 + public function getPlaceholder() { 14 + return $this->placeholder; 15 + } 16 + 6 17 protected function getDefaultValue() { 7 18 return array(); 8 19 } ··· 12 23 } 13 24 14 25 protected function newControl() { 15 - return new AphrontFormTextControl(); 26 + $control = new AphrontFormTextControl(); 27 + 28 + $placeholder = $this->getPlaceholder(); 29 + if ($placeholder !== null) { 30 + $control->setPlaceholder($placeholder); 31 + } 32 + 33 + return $control; 16 34 } 17 35 18 36 protected function getValueForControl() {