Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14760320
D20537.id48968.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D20537.id48968.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -538,6 +538,7 @@
'DifferentialMailEngineExtension' => 'applications/differential/engineextension/DifferentialMailEngineExtension.php',
'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php',
'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php',
+ 'DifferentialNoReviewersDatasource' => 'applications/differential/typeahead/DifferentialNoReviewersDatasource.php',
'DifferentialParseCacheGarbageCollector' => 'applications/differential/garbagecollector/DifferentialParseCacheGarbageCollector.php',
'DifferentialParseCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php',
'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php',
@@ -561,6 +562,7 @@
'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php',
'DifferentialReviewerDatasource' => 'applications/differential/typeahead/DifferentialReviewerDatasource.php',
'DifferentialReviewerForRevisionEdgeType' => 'applications/differential/edge/DifferentialReviewerForRevisionEdgeType.php',
+ 'DifferentialReviewerFunctionDatasource' => 'applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php',
'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php',
'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php',
'DifferentialReviewersAddBlockingSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php',
@@ -6193,6 +6195,7 @@
'DifferentialMailEngineExtension' => 'PhabricatorMailEngineExtension',
'DifferentialMailView' => 'Phobject',
'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField',
+ 'DifferentialNoReviewersDatasource' => 'PhabricatorTypeaheadDatasource',
'DifferentialParseCacheGarbageCollector' => 'PhabricatorGarbageCollector',
'DifferentialParseCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod',
'DifferentialParseRenderTestCase' => 'PhabricatorTestCase',
@@ -6216,6 +6219,7 @@
'DifferentialReviewer' => 'DifferentialDAO',
'DifferentialReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialReviewerForRevisionEdgeType' => 'PhabricatorEdgeType',
+ 'DifferentialReviewerFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialReviewerStatus' => 'Phobject',
'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'DifferentialReviewersHeraldAction',
'DifferentialReviewersAddBlockingSelfHeraldAction' => 'DifferentialReviewersHeraldAction',
diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php
--- a/src/applications/differential/query/DifferentialRevisionQuery.php
+++ b/src/applications/differential/query/DifferentialRevisionQuery.php
@@ -26,6 +26,7 @@
private $isOpen;
private $createdEpochMin;
private $createdEpochMax;
+ private $noReviewers;
const ORDER_MODIFIED = 'order-modified';
const ORDER_CREATED = 'order-created';
@@ -98,7 +99,31 @@
* @task config
*/
public function withReviewers(array $reviewer_phids) {
- $this->reviewers = $reviewer_phids;
+ if ($reviewer_phids === array()) {
+ throw new Exception(
+ pht(
+ 'Empty "withReviewers()" constraint is invalid. Provide one or '.
+ 'more values, or remove the constraint.'));
+ }
+
+ $with_none = false;
+
+ foreach ($reviewer_phids as $key => $phid) {
+ switch ($phid) {
+ case DifferentialNoReviewersDatasource::FUNCTION_TOKEN:
+ $with_none = true;
+ unset($reviewer_phids[$key]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ $this->noReviewers = $with_none;
+ if ($reviewer_phids) {
+ $this->reviewers = array_values($reviewer_phids);
+ }
+
return $this;
}
@@ -572,7 +597,7 @@
if ($this->reviewers) {
$joins[] = qsprintf(
$conn,
- 'JOIN %T reviewer ON reviewer.revisionPHID = r.phid
+ 'LEFT JOIN %T reviewer ON reviewer.revisionPHID = r.phid
AND reviewer.reviewerStatus != %s
AND reviewer.reviewerPHID in (%Ls)',
id(new DifferentialReviewer())->getTableName(),
@@ -580,6 +605,15 @@
$this->reviewers);
}
+ if ($this->noReviewers) {
+ $joins[] = qsprintf(
+ $conn,
+ 'LEFT JOIN %T no_reviewer ON no_reviewer.revisionPHID = r.phid
+ AND no_reviewer.reviewerStatus != %s',
+ id(new DifferentialReviewer())->getTableName(),
+ DifferentialReviewerStatus::STATUS_RESIGNED);
+ }
+
if ($this->draftAuthors) {
$joins[] = qsprintf(
$conn,
@@ -715,6 +749,24 @@
$statuses);
}
+ $reviewer_subclauses = array();
+
+ if ($this->noReviewers) {
+ $reviewer_subclauses[] = qsprintf(
+ $conn,
+ 'no_reviewer.reviewerPHID IS NULL');
+ }
+
+ if ($this->reviewers) {
+ $reviewer_subclauses[] = qsprintf(
+ $conn,
+ 'reviewer.reviewerPHID IS NOT NULL');
+ }
+
+ if ($reviewer_subclauses) {
+ $where[] = qsprintf($conn, '%LO', $reviewer_subclauses);
+ }
+
$where[] = $this->buildWhereClauseParts($conn);
return $this->formatWhereClause($conn, $where);
@@ -735,6 +787,10 @@
return true;
}
+ if ($this->noReviewers) {
+ return true;
+ }
+
return parent::shouldGroupQueryResultRows();
}
diff --git a/src/applications/differential/query/DifferentialRevisionSearchEngine.php b/src/applications/differential/query/DifferentialRevisionSearchEngine.php
--- a/src/applications/differential/query/DifferentialRevisionSearchEngine.php
+++ b/src/applications/differential/query/DifferentialRevisionSearchEngine.php
@@ -73,7 +73,7 @@
->setLabel(pht('Reviewers'))
->setKey('reviewerPHIDs')
->setAliases(array('reviewer', 'reviewers', 'reviewerPHID'))
- ->setDatasource(new DiffusionAuditorFunctionDatasource())
+ ->setDatasource(new DifferentialReviewerFunctionDatasource())
->setDescription(
pht('Find revisions with specific reviewers.')),
id(new PhabricatorSearchDatasourceField())
diff --git a/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php b/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php
@@ -0,0 +1,78 @@
+<?php
+
+final class DifferentialNoReviewersDatasource
+ extends PhabricatorTypeaheadDatasource {
+
+ const FUNCTION_TOKEN = 'none()';
+
+ public function getBrowseTitle() {
+ return pht('Browse No Reviewers');
+ }
+
+ public function getPlaceholderText() {
+ return pht('Type "none"...');
+ }
+
+ public function getDatasourceApplicationClass() {
+ return 'PhabricatorDifferentialApplication';
+ }
+
+ public function getDatasourceFunctions() {
+ return array(
+ 'none' => array(
+ 'name' => pht('No Reviewers'),
+ 'summary' => pht('Find results which have no reviewers.'),
+ 'description' => pht(
+ "This function includes results which have no reviewers. Use a ".
+ "query like this to find results with no reviewers:\n\n%s\n\n".
+ "If you combine this function with other functions, the query will ".
+ "return results which match the other selectors //or// have no ".
+ "reviewers. For example, this query will find results which have ".
+ "`alincoln` as a reviewer, and will also find results which have ".
+ "no reviewers:".
+ "\n\n%s",
+ '> none()',
+ '> alincoln, none()'),
+ ),
+ );
+ }
+
+ public function loadResults() {
+ $results = array(
+ $this->buildNoReviewersResult(),
+ );
+ return $this->filterResultsAgainstTokens($results);
+ }
+
+ protected function evaluateFunction($function, array $argv_list) {
+ $results = array();
+
+ foreach ($argv_list as $argv) {
+ $results[] = self::FUNCTION_TOKEN;
+ }
+
+ return $results;
+ }
+
+ public function renderFunctionTokens($function, array $argv_list) {
+ $results = array();
+ foreach ($argv_list as $argv) {
+ $results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
+ $this->buildNoReviewersResult());
+ }
+ return $results;
+ }
+
+ private function buildNoReviewersResult() {
+ $name = pht('No Reviewers');
+
+ return $this->newFunctionResult()
+ ->setName($name.' none')
+ ->setDisplayName($name)
+ ->setIcon('fa-ban')
+ ->setPHID('none()')
+ ->setUnique(true)
+ ->addAttribute(pht('Select results with no reviewers.'));
+ }
+
+}
diff --git a/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php b/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php
@@ -0,0 +1,26 @@
+<?php
+
+final class DifferentialReviewerFunctionDatasource
+ extends PhabricatorTypeaheadCompositeDatasource {
+
+ public function getBrowseTitle() {
+ return pht('Browse Reviewers');
+ }
+
+ public function getPlaceholderText() {
+ return pht('Type a user, project, package name or function...');
+ }
+
+ public function getDatasourceApplicationClass() {
+ return 'PhabricatorDifferentialApplication';
+ }
+
+ public function getComponentDatasources() {
+ return array(
+ new PhabricatorProjectOrUserFunctionDatasource(),
+ new PhabricatorOwnersPackageFunctionDatasource(),
+ new DifferentialNoReviewersDatasource(),
+ );
+ }
+
+}
diff --git a/src/applications/differential/view/DifferentialRevisionListView.php b/src/applications/differential/view/DifferentialRevisionListView.php
--- a/src/applications/differential/view/DifferentialRevisionListView.php
+++ b/src/applications/differential/view/DifferentialRevisionListView.php
@@ -60,6 +60,16 @@
$handle_phids = array();
foreach ($this->revisions as $key => $revision) {
$reviewers = $revision->getReviewers();
+
+ // Don't show reviewers who have resigned. The "Reviewers" constraint
+ // does not respect these reviewers and they largely don't count as
+ // reviewers.
+ foreach ($reviewers as $reviewer_key => $reviewer) {
+ if ($reviewer->isResigned()) {
+ unset($reviewers[$reviewer_key]);
+ }
+ }
+
if (count($reviewers) > $reviewer_limit) {
$reviewers = array_slice($reviewers, 0, $reviewer_limit);
$reviewer_more[$key] = true;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 23, 5:40 PM (2 h, 11 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7037576
Default Alt Text
D20537.id48968.diff (10 KB)
Attached To
Mode
D20537: Support "none()" in Differential to find revisions with no (un-resigned) reviewers
Attached
Detach File
Event Timeline
Log In to Comment