Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2891903
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
9 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/feed/query/PhabricatorFeedTransactionQuery.php b/src/applications/feed/query/PhabricatorFeedTransactionQuery.php
index 00da566532..e7ab4cc55d 100644
--- a/src/applications/feed/query/PhabricatorFeedTransactionQuery.php
+++ b/src/applications/feed/query/PhabricatorFeedTransactionQuery.php
@@ -1,178 +1,189 @@
<?php
final class PhabricatorFeedTransactionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
+ private $authorPHIDs;
private $createdMin;
private $createdMax;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
+ public function withAuthorPHIDs(array $phids) {
+ $this->authorPHIDs = $phids;
+ return $this;
+ }
+
public function withDateCreatedBetween($min, $max) {
$this->createdMin = $min;
$this->createdMax = $max;
return $this;
}
protected function loadPage() {
$queries = $this->newTransactionQueries();
$xactions = array();
if ($this->shouldLimitResults()) {
$limit = $this->getRawResultLimit();
if (!$limit) {
$limit = null;
}
} else {
$limit = null;
}
// We're doing a bit of manual work to get paging working, because this
// query aggregates the results of a large number of subqueries.
// Overall, we're ordering transactions by "<dateCreated, phid>". Ordering
// by PHID is not very meaningful, but we don't need the ordering to be
// especially meaningful, just consistent. Using PHIDs is easy and does
// everything we need it to technically.
// To actually configure paging, if we have an external cursor, we load
// the internal cursor first. Then we pass it to each subquery and the
// subqueries pretend they just loaded a page where it was the last object.
// This configures their queries properly and we can aggregate a cohesive
// set of results by combining all the queries.
$cursor = $this->getExternalCursorString();
if ($cursor !== null) {
$cursor_object = $this->newInternalCursorFromExternalCursor($cursor);
} else {
$cursor_object = null;
}
$is_reversed = $this->getIsQueryOrderReversed();
$created_min = $this->createdMin;
$created_max = $this->createdMax;
$xaction_phids = $this->phids;
+ $author_phids = $this->authorPHIDs;
foreach ($queries as $query) {
$query->withDateCreatedBetween($created_min, $created_max);
if ($xaction_phids !== null) {
$query->withPHIDs($xaction_phids);
}
+ if ($author_phids !== null) {
+ $query->withAuthorPHIDs($author_phids);
+ }
+
if ($limit !== null) {
$query->setLimit($limit);
}
if ($cursor_object !== null) {
$query
->setAggregatePagingCursor($cursor_object)
->setIsQueryOrderReversed($is_reversed);
}
$query->setOrder('global');
$query_xactions = $query->execute();
foreach ($query_xactions as $query_xaction) {
$xactions[] = $query_xaction;
}
$xactions = msortv($xactions, 'newGlobalSortVector');
if ($is_reversed) {
$xactions = array_reverse($xactions);
}
if ($limit !== null) {
$xactions = array_slice($xactions, 0, $limit);
// If we've found enough transactions to fill up the entire requested
// page size, we can narrow the search window: transactions after the
// last transaction we've found so far can't possibly be part of the
// result set.
if (count($xactions) === $limit) {
$last_date = last($xactions)->getDateCreated();
if ($is_reversed) {
if ($created_max === null) {
$created_max = $last_date;
} else {
$created_max = min($created_max, $last_date);
}
} else {
if ($created_min === null) {
$created_min = $last_date;
} else {
$created_min = max($created_min, $last_date);
}
}
}
}
}
return $xactions;
}
public function getQueryApplicationClass() {
return 'PhabricatorFeedApplication';
}
private function newTransactionQueries() {
$viewer = $this->getViewer();
$queries = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorApplicationTransactionQuery')
->execute();
$type_map = array();
// If we're querying for specific transaction PHIDs, we only need to
// consider queries which may load transactions with subtypes present
// in the list.
// For example, if we're loading Maniphest Task transaction PHIDs, we know
// we only have to look at Maniphest Task transactions, since other types
// of objects will never have the right transaction PHIDs.
$xaction_phids = $this->phids;
if ($xaction_phids) {
foreach ($xaction_phids as $xaction_phid) {
$type_map[phid_get_subtype($xaction_phid)] = true;
}
}
$results = array();
foreach ($queries as $query) {
if ($type_map) {
$type = $query->getTemplateApplicationTransaction()
->getApplicationTransactionType();
if (!isset($type_map[$type])) {
continue;
}
}
$results[] = id(clone $query)
->setViewer($viewer)
->setParentQuery($this);
}
return $results;
}
protected function newExternalCursorStringForResult($object) {
return (string)$object->getPHID();
}
protected function applyExternalCursorConstraintsToQuery(
PhabricatorCursorPagedPolicyAwareQuery $subquery,
$cursor) {
$subquery->withPHIDs(array($cursor));
}
}
diff --git a/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php b/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php
index bc0d27c70c..5c73818e4d 100644
--- a/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php
+++ b/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php
@@ -1,113 +1,145 @@
<?php
final class PhabricatorFeedTransactionSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Transactions');
}
public function getApplicationClassName() {
return 'PhabricatorFeedApplication';
}
public function newQuery() {
return new PhabricatorFeedTransactionQuery();
}
protected function buildCustomSearchFields() {
- return array();
+ return array(
+ id(new PhabricatorUsersSearchField())
+ ->setLabel(pht('Authors'))
+ ->setKey('authorPHIDs')
+ ->setAliases(array('author', 'authors')),
+ id(new PhabricatorSearchDateField())
+ ->setLabel(pht('Created After'))
+ ->setKey('createdStart'),
+ id(new PhabricatorSearchDateField())
+ ->setLabel(pht('Created Before'))
+ ->setKey('createdEnd'),
+ );
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
+ if ($map['authorPHIDs']) {
+ $query->withAuthorPHIDs($map['authorPHIDs']);
+ }
+
+ $created_min = $map['createdStart'];
+ $created_max = $map['createdEnd'];
+
+ if ($created_min && $created_max) {
+ if ($created_min > $created_max) {
+ throw new PhabricatorSearchConstraintException(
+ pht(
+ 'The specified "Created Before" date is earlier in time than the '.
+ 'specified "Created After" date, so this query can never match '.
+ 'any results.'));
+ }
+ }
+
+ if ($created_min || $created_max) {
+ $query->withDateCreatedBetween($created_min, $created_max);
+ }
+
return $query;
}
protected function getURI($path) {
return '/feed/transactions/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Transactions'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery()
->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $objects,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($objects, 'PhabricatorApplicationTransaction');
$viewer = $this->requireViewer();
$handle_phids = array();
foreach ($objects as $object) {
$author_phid = $object->getAuthorPHID();
if ($author_phid !== null) {
$handle_phids[] = $author_phid;
}
$object_phid = $object->getObjectPHID();
if ($object_phid !== null) {
$handle_phids[] = $object_phid;
}
}
$handles = $viewer->loadHandles($handle_phids);
$rows = array();
foreach ($objects as $object) {
$author_phid = $object->getAuthorPHID();
$object_phid = $object->getObjectPHID();
try {
$title = $object->getTitle();
} catch (Exception $ex) {
$title = null;
}
$rows[] = array(
$handles[$author_phid]->renderLink(),
$handles[$object_phid]->renderLink(),
AphrontTableView::renderSingleDisplayLine($title),
phabricator_datetime($object->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
- pht('Actor'),
+ pht('Author'),
pht('Object'),
pht('Transaction'),
pht('Date'),
))
->setColumnClasses(
array(
null,
null,
'wide',
'right',
));
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 15:56 (2 w, 6 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126225
Default Alt Text
(9 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment