Page MenuHomePhorge

No OneTemporary

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

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)

Event Timeline