From dfef3251bea752a91dbd57c1e9fd58405cf6755a Mon Sep 17 00:00:00 2001
From: epriestley <git@epriestley.com>
Date: Sun, 30 Sep 2012 20:09:51 -0700
Subject: [PATCH] Restore pager to Your Questions and All Questions

Summary: Restore the pager, using `executeWithOffsetPager()` to handle slicing, etc. Simplify and generalize `PonderQuestionQuery`.

Test Plan:
Set page size to 1, used pager to page.

{F19531}

Reviewers: pieter, starruler

Reviewed By: pieter

CC: aran

Maniphest Tasks: T1644

Differential Revision: https://secure.phabricator.com/D3513
---
 .../controller/PonderFeedController.php       |  32 +++--
 .../ponder/query/PonderQuestionQuery.php      | 119 ++++++------------
 2 files changed, 54 insertions(+), 97 deletions(-)

diff --git a/src/applications/ponder/controller/PonderFeedController.php b/src/applications/ponder/controller/PonderFeedController.php
index 40f73ffb35..67a744a47b 100644
--- a/src/applications/ponder/controller/PonderFeedController.php
+++ b/src/applications/ponder/controller/PonderFeedController.php
@@ -18,12 +18,8 @@
 
 final class PonderFeedController extends PonderController {
   private $page;
-  private $feedOffset;
-  private $questionOffset;
   private $answerOffset;
 
-  const FEED_PAGE_SIZE = 20;
-  const PROFILE_QUESTION_PAGE_SIZE = 10;
   const PROFILE_ANSWER_PAGE_SIZE = 10;
 
   public function willProcessRequest(array $data) {
@@ -34,8 +30,6 @@ final class PonderFeedController extends PonderController {
   public function processRequest() {
     $request = $this->getRequest();
     $user = $request->getUser();
-    $this->feedOffset = $request->getInt('off');
-    $this->questionOffset = $request->getInt('qoff');
     $this->answerOffset = $request->getInt('aoff');
 
     $pages = array(
@@ -53,24 +47,28 @@ final class PonderFeedController extends PonderController {
     switch ($this->page) {
       case 'feed':
       case 'questions':
+        $pager = new AphrontPagerView();
+        $pager->setOffset($request->getStr('offset'));
+        $pager->setURI($request->getRequestURI(), 'offset');
+
+        $query = new PonderQuestionQuery();
 
         if ($this->page == 'feed') {
-          $questions = PonderQuestionQuery::loadHottest(
-            $user,
-            $this->feedOffset,
-            self::FEED_PAGE_SIZE + 1);
+          $query
+            ->setOrder(PonderQuestionQuery::ORDER_HOTTEST);
         } else {
-          $questions = PonderQuestionQuery::loadByAuthor(
-            $user,
-            $user->getPHID(),
-            $this->questionOffset,
-            self::PROFILE_QUESTION_PAGE_SIZE + 1
-          );
+          $query
+            ->setOrder(PonderQuestionQuery::ORDER_CREATED)
+            ->withAuthorPHIDs(array($user->getPHID()));
         }
 
+        $questions = $query->executeWithOffsetPager($pager);
+
         $this->loadHandles(mpull($questions, 'getAuthorPHID'));
 
         $view = $this->buildQuestionListView($questions);
+        $view->setPager($pager);
+
         $side_nav->appendChild(
           id(new PhabricatorHeaderView())->setHeader($title));
         $side_nav->appendChild($view);
@@ -92,7 +90,7 @@ final class PonderFeedController extends PonderController {
           ->setAnswers($answers)
           ->setHandles($handles)
           ->setAnswerOffset($this->answerOffset)
-          ->setPageSize(self::PROFILE_QUESTION_PAGE_SIZE)
+          ->setPageSize(self::PROFILE_ANSWER_PAGE_SIZE)
           ->setURI(new PhutilURI("/ponder/profile/"), "aoff")
         );
         break;
diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php
index c93bf69c0e..36869bf087 100644
--- a/src/applications/ponder/query/PonderQuestionQuery.php
+++ b/src/applications/ponder/query/PonderQuestionQuery.php
@@ -18,76 +18,42 @@
 
 final class PonderQuestionQuery extends PhabricatorOffsetPagedQuery {
 
-  private $id;
+  const ORDER_CREATED = 'order-created';
+  const ORDER_HOTTEST = 'order-hottest';
+
+  private $ids;
   private $phids;
-  private $authorPHID;
-  private $orderHottest;
-  private $orderNewest;
+  private $authorPHIDs;
+  private $order = self::ORDER_CREATED;
 
-  public function withID($qid) {
-    $this->id = $qid;
+  public function withIDs(array $ids) {
+    $this->ids = $ids;
     return $this;
   }
 
-  public function withPHID($phid) {
-    $this->phids = array($phid);
-    return $this;
-  }
-
-  public function withPHIDs($phids) {
+  public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
-  public function withAuthorPHID($phid) {
-    $this->authorPHID = $phid;
+  public function withAuthorPHIDs(array $phids) {
+    $this->authorPHIDs = $phids;
     return $this;
   }
 
-  public function orderByHottest($usethis) {
-    $this->orderHottest = $usethis;
+  public function setOrder($order) {
+    $this->order = $order;
     return $this;
   }
 
-  public function orderByNewest($usethis) {
-    $this->orderNewest = $usethis;
-    return $this;
-  }
-
-  public static function loadHottest($viewer, $offset, $count) {
-    if (!$viewer) {
-      throw new Exception("Must set viewer when calling loadHottest");
-    }
-
-    return id(new PonderQuestionQuery())
-      ->setOffset($offset)
-      ->setLimit($count)
-      ->orderByHottest(true)
-      ->orderByNewest(true)
-      ->execute();
-  }
-
-  public static function loadByAuthor($viewer, $author_phid, $offset, $count) {
-    if (!$viewer) {
-      throw new Exception("Must set viewer when calling loadByAuthor");
-    }
-
-    return id(new PonderQuestionQuery())
-      ->withAuthorPHID($author_phid)
-      ->setOffset($offset)
-      ->setLimit($count)
-      ->orderByNewest(true)
-      ->execute();
-  }
-
   public static function loadSingle($viewer, $id) {
     if (!$viewer) {
       throw new Exception("Must set viewer when calling loadSingle");
     }
 
     return idx(id(new PonderQuestionQuery())
-               ->withID($id)
-               ->execute(), $id);
+      ->withIDs(array($id))
+      ->execute(), $id);
   }
 
   public static function loadSingleByPHID($viewer, $phid) {
@@ -96,50 +62,43 @@ final class PonderQuestionQuery extends PhabricatorOffsetPagedQuery {
     }
 
     return array_shift(id(new PonderQuestionQuery())
-      ->withPHID($phid)
+      ->withPHIDs(array($phid))
       ->execute());
   }
 
-  private function buildWhereClause($conn_r) {
+  private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
     $where = array();
-    if ($this->id) {
-      $where[] = qsprintf($conn_r, '(id = %d)', $this->id);
-    }
-    if ($this->phids) {
-      $where[] = qsprintf($conn_r, '(phid in (%Ls))', $this->phids);
-    }
-    if ($this->authorPHID) {
-      $where[] = qsprintf($conn_r, '(authorPHID = %s)', $this->authorPHID);
+
+    if ($this->ids) {
+      $where[] = qsprintf($conn_r, 'q.id IN (%Ld)', $this->ids);
     }
 
-    return ($where ? 'WHERE ' . implode(' AND ', $where) : '');
+    if ($this->phids) {
+      $where[] = qsprintf($conn_r, 'q.phid IN (%Ls)', $this->phids);
+    }
+
+    if ($this->authorPHIDs) {
+      $where[] = qsprintf($conn_r, 'q.authorPHID IN (%Ls)', $this->authorPHIDs);
+    }
+
+    return $this->formatWhereClause($where);
   }
 
-  private function buildOrderByClause($conn_r) {
-    $order = array();
-    if ($this->orderHottest) {
-      $order[] = qsprintf($conn_r, 'heat DESC');
+  private function buildOrderByClause(AphrontDatabaseConnection $conn_r) {
+    switch ($this->order) {
+      case self::ORDER_HOTTEST:
+        return qsprintf($conn_r, 'ORDER BY q.heat DESC, q.id DESC');
+      case self::ORDER_CREATED:
+        return qsprintf($conn_r, 'ORDER BY q.id DESC');
+      default:
+        throw new Exception("Unknown order '{$this->order}'!");
     }
-    if ($this->orderNewest) {
-      $order[] = qsprintf($conn_r, 'id DESC');
-    }
-
-    if (count($order) == 0) {
-      $order[] = qsprintf($conn_r, 'id ASC');
-    }
-
-    return ($order ? 'ORDER BY ' . implode(', ', $order) : '');
   }
 
   public function execute() {
     $question = new PonderQuestion();
     $conn_r = $question->establishConnection('r');
 
-    $select = qsprintf(
-      $conn_r,
-      'SELECT r.* FROM %T r',
-      $question->getTableName());
-
     $where = $this->buildWhereClause($conn_r);
     $order_by = $this->buildOrderByClause($conn_r);
     $limit = $this->buildLimitClause($conn_r);
@@ -147,8 +106,8 @@ final class PonderQuestionQuery extends PhabricatorOffsetPagedQuery {
     return $question->loadAllFromArray(
       queryfx_all(
         $conn_r,
-        '%Q %Q %Q %Q',
-        $select,
+        'SELECT q.* FROM %T q %Q %Q %Q',
+        $question->getTableName(),
         $where,
         $order_by,
         $limit));