diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php index 389852c000..2a0ae4a8e9 100644 --- a/src/applications/repository/query/PhabricatorRepositoryQuery.php +++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php @@ -27,6 +27,7 @@ final class PhabricatorRepositoryQuery const ORDER_COMMITTED = 'order-committed'; const ORDER_CALLSIGN = 'order-callsign'; const ORDER_NAME = 'order-name'; + const ORDER_SIZE = 'order-size'; private $order = self::ORDER_CREATED; const HOSTED_PHABRICATOR = 'hosted-phab'; @@ -151,7 +152,7 @@ final class PhabricatorRepositoryQuery $table->getTableName(), $this->buildJoinsClause($conn_r), $this->buildWhereClause($conn_r), - $this->buildOrderClause($conn_r), + $this->buildCustomOrderClause($conn_r), $this->buildLimitClause($conn_r)); $repositories = $table->loadAllFromArray($data); @@ -294,29 +295,44 @@ final class PhabricatorRepositoryQuery return $repositories; } - protected function getReversePaging() { - switch ($this->order) { - case self::ORDER_CALLSIGN: - case self::ORDER_NAME: - return true; - } - return false; - } + protected function buildCustomOrderClause(AphrontDatabaseConnection $conn) { + $parts = array(); - protected function getPagingColumn() { $order = $this->order; switch ($order) { case self::ORDER_CREATED: - return 'r.id'; + break; case self::ORDER_COMMITTED: - return 's.epoch'; + $parts[] = array( + 'name' => 's.epoch', + ); + break; case self::ORDER_CALLSIGN: - return 'r.callsign'; + $parts[] = array( + 'name' => 'r.callsign', + 'reverse' => true, + ); + break; case self::ORDER_NAME: - return 'r.name'; + $parts[] = array( + 'name' => 'r.name', + 'reverse' => true, + ); + break; + case self::ORDER_SIZE: + $parts[] = array( + 'name' => 's.size', + ); + break; default: throw new Exception("Unknown order '{$order}!'"); } + + $parts[] = array( + 'name' => 'r.id', + ); + + return $this->formatOrderClause($conn, $parts); } private function loadCursorObject($id) { @@ -328,6 +344,10 @@ final class PhabricatorRepositoryQuery $query->needMostRecentCommits(true); } + if ($this->order == self::ORDER_SIZE) { + $query->needCommitCounts(true); + } + $results = $query->execute(); return head($results); } @@ -394,6 +414,14 @@ final class PhabricatorRepositoryQuery ); $columns[] = $id_column; break; + case self::ORDER_SIZE: + $columns[] = array( + 'name' => 's.size', + 'type' => 'int', + 'value' => $cursor->getCommitCount(), + ); + $columns[] = $id_column; + break; default: throw new Exception("Unknown order '{$order}'!"); } @@ -402,9 +430,7 @@ final class PhabricatorRepositoryQuery $conn_r, $columns, array( - // TODO: Clean up the column ordering stuff and then make this - // depend on getReversePaging(). - 'reversed' => (bool)($before_id), + 'reversed' => ($this->getReversePaging() xor (bool)($before_id)), )); } @@ -413,7 +439,8 @@ final class PhabricatorRepositoryQuery $join_summary_table = $this->needCommitCounts || $this->needMostRecentCommits || - ($this->order == self::ORDER_COMMITTED); + ($this->order == self::ORDER_COMMITTED) || + ($this->order == self::ORDER_SIZE); if ($join_summary_table) { $joins[] = qsprintf( diff --git a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php index 6a2a2458f2..fe7736fea2 100644 --- a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php +++ b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php @@ -195,6 +195,7 @@ final class PhabricatorRepositorySearchEngine 'name' => pht('Name'), 'callsign' => pht('Callsign'), 'created' => pht('Date Created'), + 'size' => pht('Commit Count'), ); } @@ -204,6 +205,7 @@ final class PhabricatorRepositorySearchEngine 'name' => PhabricatorRepositoryQuery::ORDER_NAME, 'callsign' => PhabricatorRepositoryQuery::ORDER_CALLSIGN, 'created' => PhabricatorRepositoryQuery::ORDER_CREATED, + 'size' => PhabricatorRepositoryQuery::ORDER_SIZE, ); } diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php index b314a01bce..18526123a3 100644 --- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php @@ -284,6 +284,44 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery return '('.implode(') OR (', $clauses).')'; } + protected function formatOrderClause( + AphrontDatabaseConnection $conn, + array $parts) { + + $is_query_reversed = false; + if ($this->getReversePaging()) { + $is_query_reversed = !$is_query_reversed; + } + + if ($this->getBeforeID()) { + $is_query_reversed = !$is_query_reversed; + } + + $sql = array(); + foreach ($parts as $key => $part) { + $is_column_reversed = !empty($part['reverse']); + + $descending = true; + if ($is_query_reversed) { + $descending = !$descending; + } + + if ($is_column_reversed) { + $descending = !$descending; + } + + $name = $part['name']; + + if ($descending) { + $sql[] = qsprintf($conn, '%Q DESC', $name); + } else { + $sql[] = qsprintf($conn, '%Q ASC', $name); + } + } + + return qsprintf($conn, 'ORDER BY %Q', implode(', ', $sql)); + } + /* -( Application Search )------------------------------------------------- */