diff --git a/src/applications/phriction/query/PhrictionDocumentQuery.php b/src/applications/phriction/query/PhrictionDocumentQuery.php --- a/src/applications/phriction/query/PhrictionDocumentQuery.php +++ b/src/applications/phriction/query/PhrictionDocumentQuery.php @@ -17,7 +17,6 @@ const STATUS_OPEN = 'status-open'; const STATUS_NONSTUB = 'status-nonstub'; - private $order = 'order-created'; const ORDER_CREATED = 'order-created'; const ORDER_UPDATED = 'order-updated'; const ORDER_HIERARCHY = 'order-hierarchy'; @@ -63,7 +62,20 @@ } public function setOrder($order) { - $this->order = $order; + switch ($order) { + case self::ORDER_CREATED: + $this->setOrderVector(array('id')); + break; + case self::ORDER_UPDATED: + $this->setOrderVector(array('updated')); + break; + case self::ORDER_HIERARCHY: + $this->setOrderVector(array('depth', 'title', 'updated')); + break; + default: + throw new Exception(pht('Unknown order "%s".', $order)); + } + return $this; } @@ -71,19 +83,13 @@ $table = new PhrictionDocument(); $conn_r = $table->establishConnection('r'); - if ($this->order == self::ORDER_HIERARCHY) { - $order_clause = $this->buildHierarchicalOrderClause($conn_r); - } else { - $order_clause = $this->buildOrderClause($conn_r); - } - $rows = queryfx_all( $conn_r, 'SELECT d.* FROM %T d %Q %Q %Q %Q', $table->getTableName(), $this->buildJoinClause($conn_r), $this->buildWhereClause($conn_r), - $order_clause, + $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r)); $documents = $table->loadAllFromArray($rows); @@ -186,13 +192,15 @@ private function buildJoinClause(AphrontDatabaseConnection $conn) { $join = ''; - if ($this->order == self::ORDER_HIERARCHY) { + + if ($this->getOrderVector()->containsKey('updated')) { $content_dao = new PhrictionContent(); $join = qsprintf( $conn, 'JOIN %T c ON d.contentID = c.id', $content_dao->getTableName()); } + return $join; } protected function buildWhereClause(AphrontDatabaseConnection $conn) { @@ -271,48 +279,59 @@ return $this->formatWhereClause($where); } - private function buildHierarchicalOrderClause( - AphrontDatabaseConnection $conn_r) { - - if ($this->getBeforeID()) { - return qsprintf( - $conn_r, - 'ORDER BY d.depth, c.title, %Q %Q', - $this->getPagingColumn(), - $this->getReversePaging() ? 'DESC' : 'ASC'); - } else { - return qsprintf( - $conn_r, - 'ORDER BY d.depth, c.title, %Q %Q', - $this->getPagingColumn(), - $this->getReversePaging() ? 'ASC' : 'DESC'); - } + public function getOrderableColumns() { + return parent::getOrderableColumns() + array( + 'depth' => array( + 'table' => 'd', + 'column' => 'depth', + 'reverse' => true, + 'type' => 'int', + ), + 'title' => array( + 'table' => 'c', + 'column' => 'title', + 'reverse' => true, + 'type' => 'string', + ), + 'updated' => array( + 'table' => 'd', + 'column' => 'contentID', + 'type' => 'int', + 'unique' => true, + ), + ); } - protected function getPagingColumn() { - switch ($this->order) { - case self::ORDER_CREATED: - case self::ORDER_HIERARCHY: - return 'd.id'; - case self::ORDER_UPDATED: - return 'd.contentID'; - default: - throw new Exception("Unknown order '{$this->order}'!"); + protected function getPagingValueMap($cursor, array $keys) { + $document = $this->loadCursorObject($cursor); + + $map = array( + 'id' => $document->getID(), + 'depth' => $document->getDepth(), + 'updated' => $document->getContentID(), + ); + + foreach ($keys as $key) { + switch ($key) { + case 'title': + $map[$key] = $document->getContent()->getTitle(); + break; + } } + + return $map; } - protected function getPagingValue($result) { - switch ($this->order) { - case self::ORDER_CREATED: - case self::ORDER_HIERARCHY: - return $result->getID(); - case self::ORDER_UPDATED: - return $result->getContentID(); - default: - throw new Exception("Unknown order '{$this->order}'!"); + protected function willExecuteCursorQuery( + PhabricatorCursorPagedPolicyAwareQuery $query) { + $vector = $this->getOrderVector(); + + if ($vector->containsKey('title')) { + $query->needContent(true); } } + public function getQueryApplicationClass() { return 'PhabricatorPhrictionApplication'; } diff --git a/src/applications/phriction/query/PhrictionSearchEngine.php b/src/applications/phriction/query/PhrictionSearchEngine.php --- a/src/applications/phriction/query/PhrictionSearchEngine.php +++ b/src/applications/phriction/query/PhrictionSearchEngine.php @@ -14,8 +14,8 @@ public function buildSavedQueryFromRequest(AphrontRequest $request) { $saved = new PhabricatorSavedQuery(); - $saved->setParameter('status', $request->getArr('status')); - $saved->setParameter('order', $request->getArr('order')); + $saved->setParameter('status', $request->getStr('status')); + $saved->setParameter('order', $request->getStr('order')); return $saved; } diff --git a/src/infrastructure/query/order/PhabricatorQueryOrderVector.php b/src/infrastructure/query/order/PhabricatorQueryOrderVector.php --- a/src/infrastructure/query/order/PhabricatorQueryOrderVector.php +++ b/src/infrastructure/query/order/PhabricatorQueryOrderVector.php @@ -92,6 +92,10 @@ return implode(', ', $scalars); } + public function containsKey($key) { + return isset($this->items[$key]); + } + /* -( Iterator Interface )------------------------------------------------- */ diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php --- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php @@ -249,6 +249,8 @@ ->setViewer($this->getPagingViewer()) ->withIDs(array((int)$cursor)); + $this->willExecuteCursorQuery($query); + $object = $query->executeOne(); if (!$object) { throw new Exception( @@ -260,6 +262,11 @@ return $object; } + protected function willExecuteCursorQuery( + PhabricatorCursorPagedPolicyAwareQuery $query) { + return; + } + /** * Simplifies the task of constructing a paging clause across multiple @@ -446,7 +453,7 @@ /** * @task order */ - private function getOrderVector() { + protected function getOrderVector() { if (!$this->orderVector) { $vector = $this->getDefaultOrderVector(); $vector = PhabricatorQueryOrderVector::newFromVector($vector);