diff --git a/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php index fbc08d4ef3..674393dfc7 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php @@ -29,7 +29,7 @@ final class HarbormasterBuildablePHIDType extends PhabricatorPHIDType { array $handles, array $objects) { - $viewer = $this->getViewer(); + $viewer = $query->getViewer(); $target_phids = array(); foreach ($objects as $phid => $object) { diff --git a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php index fc069bd031..b1a643cac7 100644 --- a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php +++ b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php @@ -7,6 +7,7 @@ final class HarbormasterBuildableQuery private $phids; private $buildablePHIDs; private $containerPHIDs; + private $statuses; private $manualBuildables; private $needContainerObjects; @@ -43,6 +44,11 @@ final class HarbormasterBuildableQuery return $this; } + public function withStatuses(array $statuses) { + $this->statuses = $statuses; + return $this; + } + public function needBuilds($need) { $this->needBuilds = $need; return $this; @@ -154,6 +160,13 @@ final class HarbormasterBuildableQuery $this->containerPHIDs); } + if ($this->statuses !== null) { + $where[] = qsprintf( + $conn, + 'buildableStatus in (%Ls)', + $this->statuses); + } + if ($this->manualBuildables !== null) { $where[] = qsprintf( $conn, diff --git a/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php index 937816eb19..cfff27b1aa 100644 --- a/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php +++ b/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php @@ -11,146 +11,87 @@ final class HarbormasterBuildableSearchEngine return 'PhabricatorHarbormasterApplication'; } - public function buildSavedQueryFromRequest(AphrontRequest $request) { - $saved = new PhabricatorSavedQuery(); - - $revisions = $this->readPHIDsFromRequest( - $request, - 'revisions', - array( - DifferentialRevisionPHIDType::TYPECONST, - )); - - $repositories = $this->readPHIDsFromRequest( - $request, - 'repositories', - array( - PhabricatorRepositoryRepositoryPHIDType::TYPECONST, - )); - - $container_phids = array_merge($revisions, $repositories); - $saved->setParameter('containerPHIDs', $container_phids); - - $commits = $this->readPHIDsFromRequest( - $request, - 'commits', - array( - PhabricatorRepositoryCommitPHIDType::TYPECONST, - )); - - $diffs = $this->readListFromRequest($request, 'diffs'); - if ($diffs) { - $diffs = id(new DifferentialDiffQuery()) - ->setViewer($this->requireViewer()) - ->withIDs($diffs) - ->execute(); - $diffs = mpull($diffs, 'getPHID', 'getPHID'); - } - - $buildable_phids = array_merge($commits, $diffs); - $saved->setParameter('buildablePHIDs', $buildable_phids); - - $saved->setParameter( - 'manual', - $this->readBoolFromRequest($request, 'manual')); - - return $saved; + public function newQuery() { + return new HarbormasterBuildableQuery(); } - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { - $query = id(new HarbormasterBuildableQuery()); - - $container_phids = $saved->getParameter('containerPHIDs', array()); - if ($container_phids) { - $query->withContainerPHIDs($container_phids); - } - - $buildable_phids = $saved->getParameter('buildablePHIDs', array()); - - if ($buildable_phids) { - $query->withBuildablePHIDs($buildable_phids); - } - - $manual = $saved->getParameter('manual'); - if ($manual !== null) { - $query->withManualBuildables($manual); - } - - return $query; + protected function buildCustomSearchFields() { + return array( + id(new PhabricatorSearchStringListField()) + ->setKey('objectPHIDs') + ->setAliases(array('objects')) + ->setLabel(pht('Objects')) + ->setPlaceholder(pht('rXabcdef, PHID-DIFF-1234, ...')) + ->setDescription(pht('Search for builds of particular objects.')), + id(new PhabricatorSearchStringListField()) + ->setKey('containerPHIDs') + ->setAliases(array('containers')) + ->setLabel(pht('Containers')) + ->setPlaceholder(pht('rXYZ, R123, D456, ...')) + ->setDescription( + pht('Search for builds by containing revision or repository.')), + id(new PhabricatorSearchCheckboxesField()) + ->setKey('statuses') + ->setLabel(pht('Statuses')) + ->setOptions(HarbormasterBuildable::getBuildStatusMap()) + ->setDescription(pht('Search for builds by buildable status.')), + id(new PhabricatorSearchThreeStateField()) + ->setLabel(pht('Manual')) + ->setKey('manual') + ->setDescription( + pht('Search for only manual or automatic buildables.')) + ->setOptions( + pht('(Show All)'), + pht('Show Only Manual Builds'), + pht('Show Only Automated Builds')), + ); } - public function buildSearchForm( - AphrontFormView $form, - PhabricatorSavedQuery $saved_query) { + private function resolvePHIDs(array $names) { + $viewer = $this->requireViewer(); - $container_phids = $saved_query->getParameter('containerPHIDs', array()); - $buildable_phids = $saved_query->getParameter('buildablePHIDs', array()); + $objects = id(new PhabricatorObjectQuery()) + ->setViewer($viewer) + ->withNames($names) + ->execute(); - $all_phids = array_merge($container_phids, $buildable_phids); + // TODO: Instead of using string lists, we should ideally be using some + // kind of smart field with resolver logic that can help users type the + // right stuff. For now, just return a bogus value here so nothing matches + // but the form doesn't explode. + if (!$objects) { + return array('-'); + } - $revision_names = array(); - $diff_names = array(); - $repository_names = array(); - $commit_names = array(); + return mpull($objects, 'getPHID'); + } - if ($all_phids) { - $objects = id(new PhabricatorObjectQuery()) - ->setViewer($this->requireViewer()) - ->withPHIDs($all_phids) - ->execute(); + protected function buildQueryFromParameters(array $map) { + $query = $this->newQuery(); - foreach ($all_phids as $phid) { - $object = idx($objects, $phid); - if (!$object) { - continue; - } - - if ($object instanceof DifferentialRevision) { - $revision_names[] = 'D'.$object->getID(); - } else if ($object instanceof DifferentialDiff) { - $diff_names[] = $object->getID(); - } else if ($object instanceof PhabricatorRepository) { - $repository_names[] = $object->getMonogram(); - } else if ($object instanceof PhabricatorRepositoryCommit) { - $repository = $object->getRepository(); - $commit_names[] = $repository->formatCommitName( - $object->getCommitIdentifier()); - } + if ($map['objectPHIDs']) { + $phids = $this->resolvePHIDs($map['objectPHIDs']); + if ($phids) { + $query->withBuildablePHIDs($phids); } } - $form - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Differential Revisions')) - ->setName('revisions') - ->setValue(implode(', ', $revision_names))) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Differential Diffs')) - ->setName('diffs') - ->setValue(implode(', ', $diff_names))) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Repositories')) - ->setName('repositories') - ->setValue(implode(', ', $repository_names))) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Commits')) - ->setName('commits') - ->setValue(implode(', ', $commit_names))) - ->appendChild( - id(new AphrontFormSelectControl()) - ->setLabel(pht('Origin')) - ->setName('manual') - ->setValue($this->getBoolFromQuery($saved_query, 'manual')) - ->setOptions( - array( - '' => pht('(All Origins)'), - 'true' => pht('Manual Buildables'), - 'false' => pht('Automatic Buildables'), - ))); + if ($map['containerPHIDs']) { + $phids = $this->resolvePHIDs($map['containerPHIDs']); + if ($phids) { + $query->withContainerPHIDs($phids); + } + } + + if ($map['statuses']) { + $query->withStatuses($map['statuses']); + } + + if ($map['manual'] !== null) { + $query->withManualBuildables($map['manual']); + } + + return $query; } protected function getURI($path) { diff --git a/src/applications/harbormaster/storage/HarbormasterBuildable.php b/src/applications/harbormaster/storage/HarbormasterBuildable.php index f02fff270b..7a7b32618c 100644 --- a/src/applications/harbormaster/storage/HarbormasterBuildable.php +++ b/src/applications/harbormaster/storage/HarbormasterBuildable.php @@ -20,16 +20,16 @@ final class HarbormasterBuildable extends HarbormasterDAO const STATUS_FAILED = 'failed'; public static function getBuildableStatusName($status) { - switch ($status) { - case self::STATUS_BUILDING: - return pht('Building'); - case self::STATUS_PASSED: - return pht('Passed'); - case self::STATUS_FAILED: - return pht('Failed'); - default: - return pht('Unknown'); - } + $map = self::getBuildStatusMap(); + return idx($map, $status, pht('Unknown ("%s")', $status)); + } + + public static function getBuildStatusMap() { + return array( + self::STATUS_BUILDING => pht('Building'), + self::STATUS_PASSED => pht('Passed'), + self::STATUS_FAILED => pht('Failed'), + ); } public static function getBuildableStatusIcon($status) { diff --git a/src/applications/search/field/PhabricatorSearchStringListField.php b/src/applications/search/field/PhabricatorSearchStringListField.php index 415caf7ea2..2dd9517a3e 100644 --- a/src/applications/search/field/PhabricatorSearchStringListField.php +++ b/src/applications/search/field/PhabricatorSearchStringListField.php @@ -3,6 +3,17 @@ final class PhabricatorSearchStringListField extends PhabricatorSearchField { + private $placeholder; + + public function setPlaceholder($placeholder) { + $this->placeholder = $placeholder; + return $this; + } + + public function getPlaceholder() { + return $this->placeholder; + } + protected function getDefaultValue() { return array(); } @@ -12,7 +23,14 @@ final class PhabricatorSearchStringListField } protected function newControl() { - return new AphrontFormTextControl(); + $control = new AphrontFormTextControl(); + + $placeholder = $this->getPlaceholder(); + if ($placeholder !== null) { + $control->setPlaceholder($placeholder); + } + + return $control; } protected function getValueForControl() {