diff --git a/src/applications/almanac/query/AlmanacBindingQuery.php b/src/applications/almanac/query/AlmanacBindingQuery.php
index 574967f7bb..c3c7940525 100644
--- a/src/applications/almanac/query/AlmanacBindingQuery.php
+++ b/src/applications/almanac/query/AlmanacBindingQuery.php
@@ -1,179 +1,175 @@
 <?php
 
 final class AlmanacBindingQuery
   extends AlmanacQuery {
 
   private $ids;
   private $phids;
   private $servicePHIDs;
   private $devicePHIDs;
   private $interfacePHIDs;
   private $isActive;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withServicePHIDs(array $phids) {
     $this->servicePHIDs = $phids;
     return $this;
   }
 
   public function withDevicePHIDs(array $phids) {
     $this->devicePHIDs = $phids;
     return $this;
   }
 
   public function withInterfacePHIDs(array $phids) {
     $this->interfacePHIDs = $phids;
     return $this;
   }
 
   public function withIsActive($active) {
     $this->isActive = $active;
     return $this;
   }
 
   public function newResultObject() {
     return new AlmanacBinding();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $bindings) {
     $service_phids = mpull($bindings, 'getServicePHID');
     $device_phids = mpull($bindings, 'getDevicePHID');
     $interface_phids = mpull($bindings, 'getInterfacePHID');
 
     $services = id(new AlmanacServiceQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($service_phids)
       ->needProperties($this->getNeedProperties())
       ->execute();
     $services = mpull($services, null, 'getPHID');
 
     $devices = id(new AlmanacDeviceQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($device_phids)
       ->needProperties($this->getNeedProperties())
       ->execute();
     $devices = mpull($devices, null, 'getPHID');
 
     $interfaces = id(new AlmanacInterfaceQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($interface_phids)
       ->needProperties($this->getNeedProperties())
       ->execute();
     $interfaces = mpull($interfaces, null, 'getPHID');
 
     foreach ($bindings as $key => $binding) {
       $service = idx($services, $binding->getServicePHID());
       $device = idx($devices, $binding->getDevicePHID());
       $interface = idx($interfaces, $binding->getInterfacePHID());
       if (!$service || !$device || !$interface) {
         $this->didRejectResult($binding);
         unset($bindings[$key]);
         continue;
       }
 
       $binding->attachService($service);
       $binding->attachDevice($device);
       $binding->attachInterface($interface);
     }
 
     return $bindings;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'binding.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'binding.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->servicePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'binding.servicePHID IN (%Ls)',
         $this->servicePHIDs);
     }
 
     if ($this->devicePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'binding.devicePHID IN (%Ls)',
         $this->devicePHIDs);
     }
 
     if ($this->interfacePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'binding.interfacePHID IN (%Ls)',
         $this->interfacePHIDs);
     }
 
     if ($this->isActive !== null) {
       if ($this->isActive) {
         $where[] = qsprintf(
           $conn,
           '(binding.isDisabled = 0) AND (device.status IN (%Ls))',
           AlmanacDeviceStatus::getActiveStatusList());
       } else {
         $where[] = qsprintf(
           $conn,
           '(binding.isDisabled = 1) OR (device.status IN (%Ls))',
           AlmanacDeviceStatus::getDisabledStatusList());
       }
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinDeviceTable()) {
       $device_table = new AlmanacDevice();
       $joins[] = qsprintf(
         $conn,
         'JOIN %R device ON binding.devicePHID = device.phid',
         $device_table);
     }
 
     return $joins;
   }
 
   private function shouldJoinDeviceTable() {
     if ($this->isActive !== null) {
       return true;
     }
 
     return false;
   }
 
   protected function getPrimaryTableAlias() {
     return 'binding';
   }
 
 }
diff --git a/src/applications/almanac/query/AlmanacDeviceQuery.php b/src/applications/almanac/query/AlmanacDeviceQuery.php
index 7fcf219571..42796c4839 100644
--- a/src/applications/almanac/query/AlmanacDeviceQuery.php
+++ b/src/applications/almanac/query/AlmanacDeviceQuery.php
@@ -1,158 +1,154 @@
 <?php
 
 final class AlmanacDeviceQuery
   extends AlmanacQuery {
 
   private $ids;
   private $phids;
   private $names;
   private $namePrefix;
   private $nameSuffix;
   private $isClusterDevice;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNamePrefix($prefix) {
     $this->namePrefix = $prefix;
     return $this;
   }
 
   public function withNameSuffix($suffix) {
     $this->nameSuffix = $suffix;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new AlmanacDeviceNameNgrams(),
       $ngrams);
   }
 
   public function withIsClusterDevice($is_cluster_device) {
     $this->isClusterDevice = $is_cluster_device;
     return $this;
   }
 
   public function newResultObject() {
     return new AlmanacDevice();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'device.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'device.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->names !== null) {
       $hashes = array();
       foreach ($this->names as $name) {
         $hashes[] = PhabricatorHash::digestForIndex($name);
       }
       $where[] = qsprintf(
         $conn,
         'device.nameIndex IN (%Ls)',
         $hashes);
     }
 
     if ($this->namePrefix !== null) {
       $where[] = qsprintf(
         $conn,
         'device.name LIKE %>',
         $this->namePrefix);
     }
 
     if ($this->nameSuffix !== null) {
       $where[] = qsprintf(
         $conn,
         'device.name LIKE %<',
         $this->nameSuffix);
     }
 
     if ($this->isClusterDevice !== null) {
       $where[] = qsprintf(
         $conn,
         'device.isBoundToClusterService = %d',
         (int)$this->isClusterDevice);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'device.status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'device';
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'name',
         'type' => 'string',
         'unique' => true,
         'reverse' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
     );
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name'),
         'name' => pht('Device Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAlmanacApplication';
   }
 
 }
diff --git a/src/applications/almanac/query/AlmanacInterfaceQuery.php b/src/applications/almanac/query/AlmanacInterfaceQuery.php
index 5738108ffc..dbbc0cd53e 100644
--- a/src/applications/almanac/query/AlmanacInterfaceQuery.php
+++ b/src/applications/almanac/query/AlmanacInterfaceQuery.php
@@ -1,211 +1,207 @@
 <?php
 
 final class AlmanacInterfaceQuery
   extends AlmanacQuery {
 
   private $ids;
   private $phids;
   private $networkPHIDs;
   private $devicePHIDs;
   private $addresses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withNetworkPHIDs(array $phids) {
     $this->networkPHIDs = $phids;
     return $this;
   }
 
   public function withDevicePHIDs(array $phids) {
     $this->devicePHIDs = $phids;
     return $this;
   }
 
   public function withAddresses(array $addresses) {
     $this->addresses = $addresses;
     return $this;
   }
 
   public function newResultObject() {
     return new AlmanacInterface();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $interfaces) {
     $network_phids = mpull($interfaces, 'getNetworkPHID');
     $device_phids = mpull($interfaces, 'getDevicePHID');
 
     $networks = id(new AlmanacNetworkQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($network_phids)
       ->needProperties($this->getNeedProperties())
       ->execute();
     $networks = mpull($networks, null, 'getPHID');
 
     $devices = id(new AlmanacDeviceQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($device_phids)
       ->needProperties($this->getNeedProperties())
       ->execute();
     $devices = mpull($devices, null, 'getPHID');
 
     foreach ($interfaces as $key => $interface) {
       $network = idx($networks, $interface->getNetworkPHID());
       $device = idx($devices, $interface->getDevicePHID());
       if (!$network || !$device) {
         $this->didRejectResult($interface);
         unset($interfaces[$key]);
         continue;
       }
 
       $interface->attachNetwork($network);
       $interface->attachDevice($device);
     }
 
     return $interfaces;
   }
 
   protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) {
     $select = parent::buildSelectClauseParts($conn);
 
     if ($this->shouldJoinDeviceTable()) {
       $select[] = qsprintf($conn, 'device.name');
     }
 
     return $select;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'interface.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'interface.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->networkPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'interface.networkPHID IN (%Ls)',
         $this->networkPHIDs);
     }
 
     if ($this->devicePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'interface.devicePHID IN (%Ls)',
         $this->devicePHIDs);
     }
 
     if ($this->addresses !== null) {
       $parts = array();
       foreach ($this->addresses as $address) {
         $parts[] = qsprintf(
           $conn,
           '(interface.networkPHID = %s '.
             'AND interface.address = %s '.
             'AND interface.port = %d)',
           $address->getNetworkPHID(),
           $address->getAddress(),
           $address->getPort());
       }
       $where[] = qsprintf($conn, '%LO', $parts);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinDeviceTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T device ON device.phid = interface.devicePHID',
         id(new AlmanacDevice())->getTableName());
     }
 
     return $joins;
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->shouldJoinDeviceTable()) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   private function shouldJoinDeviceTable() {
     $vector = $this->getOrderVector();
 
     if ($vector->containsKey('name')) {
       return true;
     }
 
     return false;
   }
 
   protected function getPrimaryTableAlias() {
     return 'interface';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAlmanacApplication';
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name', 'id'),
         'name' => pht('Device Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => 'device',
         'column' => 'name',
         'type' => 'string',
         'reverse' => true,
       ),
     );
   }
 
   protected function newPagingMapFromCursorObject(
     PhabricatorQueryCursor $cursor,
     array $keys) {
 
     $interface = $cursor->getObject();
 
     return array(
       'id' => (int)$interface->getID(),
       'name' => $cursor->getRawRowProperty('device.name'),
     );
   }
 
 }
diff --git a/src/applications/almanac/query/AlmanacNamespaceQuery.php b/src/applications/almanac/query/AlmanacNamespaceQuery.php
index d4378e17c7..e6c99bf6ea 100644
--- a/src/applications/almanac/query/AlmanacNamespaceQuery.php
+++ b/src/applications/almanac/query/AlmanacNamespaceQuery.php
@@ -1,102 +1,98 @@
 <?php
 
 final class AlmanacNamespaceQuery
   extends AlmanacQuery {
 
   private $ids;
   private $phids;
   private $names;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new AlmanacNamespaceNameNgrams(),
       $ngrams);
   }
 
   public function newResultObject() {
     return new AlmanacNamespace();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'namespace.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'namespace.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->names !== null) {
       $where[] = qsprintf(
         $conn,
         'namespace.name IN (%Ls)',
         $this->names);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'namespace';
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'name',
         'type' => 'string',
         'unique' => true,
         'reverse' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
     );
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name'),
         'name' => pht('Namespace Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAlmanacApplication';
   }
 
 }
diff --git a/src/applications/almanac/query/AlmanacNetworkQuery.php b/src/applications/almanac/query/AlmanacNetworkQuery.php
index 13176f7de1..7af9db8585 100644
--- a/src/applications/almanac/query/AlmanacNetworkQuery.php
+++ b/src/applications/almanac/query/AlmanacNetworkQuery.php
@@ -1,74 +1,70 @@
 <?php
 
 final class AlmanacNetworkQuery
   extends AlmanacQuery {
 
   private $ids;
   private $phids;
   private $names;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new AlmanacNetwork();
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new AlmanacNetworkNameNgrams(),
       $ngrams);
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'network.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'network.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->names !== null) {
       $where[] = qsprintf(
         $conn,
         'network.name IN (%Ls)',
         $this->names);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'network';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAlmanacApplication';
   }
 
 }
diff --git a/src/applications/almanac/query/AlmanacPropertyQuery.php b/src/applications/almanac/query/AlmanacPropertyQuery.php
index 17f1e87c07..4261c70fec 100644
--- a/src/applications/almanac/query/AlmanacPropertyQuery.php
+++ b/src/applications/almanac/query/AlmanacPropertyQuery.php
@@ -1,109 +1,105 @@
 <?php
 
 final class AlmanacPropertyQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $objectPHIDs;
   private $objects;
   private $names;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withObjectPHIDs(array $phids) {
     $this->objectPHIDs = $phids;
     return $this;
   }
 
   public function withObjects(array $objects) {
     $this->objects = mpull($objects, null, 'getPHID');
     $this->objectPHIDs = array_keys($this->objects);
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function newResultObject() {
     return new AlmanacProperty();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $properties) {
     $object_phids = mpull($properties, 'getObjectPHID');
 
     $object_phids = array_fuse($object_phids);
 
     if ($this->objects !== null) {
       $object_phids = array_diff_key($object_phids, $this->objects);
     }
 
     if ($object_phids) {
       $objects = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($object_phids)
         ->execute();
       $objects = mpull($objects, null, 'getPHID');
     } else {
       $objects = array();
     }
 
     $objects += $this->objects;
 
     foreach ($properties as $key => $property) {
       $object = idx($objects, $property->getObjectPHID());
       if (!$object) {
         unset($properties[$key]);
         continue;
       }
       $property->attachObject($object);
     }
 
     return $properties;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->names !== null) {
       $hashes = array();
       foreach ($this->names as $name) {
         $hashes[] = PhabricatorHash::digestForIndex($name);
       }
       $where[] = qsprintf(
         $conn,
         'fieldIndex IN (%Ls)',
         $hashes);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAlmanacApplication';
   }
 
 }
diff --git a/src/applications/almanac/query/AlmanacServiceQuery.php b/src/applications/almanac/query/AlmanacServiceQuery.php
index 4e374ec90c..eaca9d4a76 100644
--- a/src/applications/almanac/query/AlmanacServiceQuery.php
+++ b/src/applications/almanac/query/AlmanacServiceQuery.php
@@ -1,248 +1,244 @@
 <?php
 
 final class AlmanacServiceQuery
   extends AlmanacQuery {
 
   private $ids;
   private $phids;
   private $names;
   private $serviceTypes;
   private $devicePHIDs;
   private $namePrefix;
   private $nameSuffix;
 
   private $needBindings;
   private $needActiveBindings;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withServiceTypes(array $types) {
     $this->serviceTypes = $types;
     return $this;
   }
 
   public function withDevicePHIDs(array $phids) {
     $this->devicePHIDs = $phids;
     return $this;
   }
 
   public function withNamePrefix($prefix) {
     $this->namePrefix = $prefix;
     return $this;
   }
 
   public function withNameSuffix($suffix) {
     $this->nameSuffix = $suffix;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new AlmanacServiceNameNgrams(),
       $ngrams);
   }
 
   public function needBindings($need_bindings) {
     $this->needBindings = $need_bindings;
     return $this;
   }
 
   public function needActiveBindings($need_active) {
     $this->needActiveBindings = $need_active;
     return $this;
   }
 
   public function newResultObject() {
     return new AlmanacService();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinBindingTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T binding ON service.phid = binding.servicePHID',
         id(new AlmanacBinding())->getTableName());
     }
 
     return $joins;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'service.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'service.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->names !== null) {
       $hashes = array();
       foreach ($this->names as $name) {
         $hashes[] = PhabricatorHash::digestForIndex($name);
       }
 
       $where[] = qsprintf(
         $conn,
         'service.nameIndex IN (%Ls)',
         $hashes);
     }
 
     if ($this->serviceTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'service.serviceType IN (%Ls)',
         $this->serviceTypes);
     }
 
     if ($this->devicePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'binding.devicePHID IN (%Ls)',
         $this->devicePHIDs);
     }
 
     if ($this->namePrefix !== null) {
       $where[] = qsprintf(
         $conn,
         'service.name LIKE %>',
         $this->namePrefix);
     }
 
     if ($this->nameSuffix !== null) {
       $where[] = qsprintf(
         $conn,
         'service.name LIKE %<',
         $this->nameSuffix);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $services) {
     $service_map = AlmanacServiceType::getAllServiceTypes();
 
     foreach ($services as $key => $service) {
       $implementation = idx($service_map, $service->getServiceType());
 
       if (!$implementation) {
         $this->didRejectResult($service);
         unset($services[$key]);
         continue;
       }
 
       $implementation = clone $implementation;
       $service->attachServiceImplementation($implementation);
     }
 
     return $services;
   }
 
   protected function didFilterPage(array $services) {
     $need_all = $this->needBindings;
     $need_active = $this->needActiveBindings;
 
     $need_any = ($need_all || $need_active);
     $only_active = ($need_active && !$need_all);
 
     if ($need_any) {
       $service_phids = mpull($services, 'getPHID');
 
       $bindings_query = id(new AlmanacBindingQuery())
         ->setViewer($this->getViewer())
         ->withServicePHIDs($service_phids)
         ->needProperties($this->getNeedProperties());
 
       if ($only_active) {
         $bindings_query->withIsActive(true);
       }
 
       $bindings = $bindings_query->execute();
       $bindings = mgroup($bindings, 'getServicePHID');
 
       foreach ($services as $service) {
         $service_bindings = idx($bindings, $service->getPHID(), array());
 
         if ($only_active) {
           $service->attachActiveBindings($service_bindings);
         } else {
           $service->attachBindings($service_bindings);
         }
       }
     }
 
     return parent::didFilterPage($services);
   }
 
   private function shouldJoinBindingTable() {
     return ($this->devicePHIDs !== null);
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->shouldJoinBindingTable()) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   protected function getPrimaryTableAlias() {
     return 'service';
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'name',
         'type' => 'string',
         'unique' => true,
         'reverse' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
     );
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name'),
         'name' => pht('Service Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthChallengeQuery.php b/src/applications/auth/query/PhabricatorAuthChallengeQuery.php
index 195abe0884..c6abead11f 100644
--- a/src/applications/auth/query/PhabricatorAuthChallengeQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthChallengeQuery.php
@@ -1,99 +1,95 @@
 <?php
 
 final class PhabricatorAuthChallengeQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $userPHIDs;
   private $factorPHIDs;
   private $challengeTTLMin;
   private $challengeTTLMax;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withUserPHIDs(array $user_phids) {
     $this->userPHIDs = $user_phids;
     return $this;
   }
 
   public function withFactorPHIDs(array $factor_phids) {
     $this->factorPHIDs = $factor_phids;
     return $this;
   }
 
   public function withChallengeTTLBetween($challenge_min, $challenge_max) {
     $this->challengeTTLMin = $challenge_min;
     $this->challengeTTLMax = $challenge_max;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthChallenge();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     if ($this->factorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'factorPHID IN (%Ls)',
         $this->factorPHIDs);
     }
 
     if ($this->challengeTTLMin !== null) {
       $where[] = qsprintf(
         $conn,
         'challengeTTL >= %d',
         $this->challengeTTLMin);
     }
 
     if ($this->challengeTTLMax !== null) {
       $where[] = qsprintf(
         $conn,
         'challengeTTL <= %d',
         $this->challengeTTLMax);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php b/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php
index 77b3b559dd..ba507c757b 100644
--- a/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php
@@ -1,103 +1,99 @@
 <?php
 
 final class PhabricatorAuthContactNumberQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $objectPHIDs;
   private $statuses;
   private $uniqueKeys;
   private $isPrimary;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withUniqueKeys(array $unique_keys) {
     $this->uniqueKeys = $unique_keys;
     return $this;
   }
 
   public function withIsPrimary($is_primary) {
     $this->isPrimary = $is_primary;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthContactNumber();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->uniqueKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'uniqueKey IN (%Ls)',
         $this->uniqueKeys);
     }
 
     if ($this->isPrimary !== null) {
       $where[] = qsprintf(
         $conn,
         'isPrimary = %d',
         (int)$this->isPrimary);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php b/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php
index 5f838f66ba..dd73d0b081 100644
--- a/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php
@@ -1,131 +1,127 @@
 <?php
 
 final class PhabricatorAuthFactorConfigQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $userPHIDs;
   private $factorProviderPHIDs;
   private $factorProviderStatuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withUserPHIDs(array $user_phids) {
     $this->userPHIDs = $user_phids;
     return $this;
   }
 
   public function withFactorProviderPHIDs(array $provider_phids) {
     $this->factorProviderPHIDs = $provider_phids;
     return $this;
   }
 
   public function withFactorProviderStatuses(array $statuses) {
     $this->factorProviderStatuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthFactorConfig();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'config.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'config.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'config.userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     if ($this->factorProviderPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'config.factorProviderPHID IN (%Ls)',
         $this->factorProviderPHIDs);
     }
 
     if ($this->factorProviderStatuses !== null) {
       $where[] = qsprintf(
         $conn,
         'provider.status IN (%Ls)',
         $this->factorProviderStatuses);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->factorProviderStatuses !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %R provider ON config.factorProviderPHID = provider.phid',
         new PhabricatorAuthFactorProvider());
     }
 
     return $joins;
   }
 
   protected function willFilterPage(array $configs) {
     $provider_phids = mpull($configs, 'getFactorProviderPHID');
 
     $providers = id(new PhabricatorAuthFactorProviderQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs($provider_phids)
       ->execute();
     $providers = mpull($providers, null, 'getPHID');
 
     foreach ($configs as $key => $config) {
       $provider = idx($providers, $config->getFactorProviderPHID());
 
       if (!$provider) {
         unset($configs[$key]);
         $this->didRejectResult($config);
         continue;
       }
 
       $config->attachFactorProvider($provider);
     }
 
     return $configs;
   }
 
   protected function getPrimaryTableAlias() {
     return 'config';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php b/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php
index 57b554885c..7083545e3e 100644
--- a/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php
@@ -1,94 +1,90 @@
 <?php
 
 final class PhabricatorAuthFactorProviderQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $statuses;
   private $providerFactorKeys;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withProviderFactorKeys(array $keys) {
     $this->providerFactorKeys = $keys;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthFactorProvider();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->providerFactorKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'providerFactorKey IN (%Ls)',
         $this->providerFactorKeys);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $providers) {
     $map = PhabricatorAuthFactor::getAllFactors();
     foreach ($providers as $key => $provider) {
       $factor_key = $provider->getProviderFactorKey();
       $factor = idx($map, $factor_key);
 
       if (!$factor) {
         unset($providers[$key]);
         continue;
       }
 
       $provider->attachFactor($factor);
     }
 
     return $providers;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthMessageQuery.php b/src/applications/auth/query/PhabricatorAuthMessageQuery.php
index 384c8de23b..7158d03a00 100644
--- a/src/applications/auth/query/PhabricatorAuthMessageQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthMessageQuery.php
@@ -1,83 +1,79 @@
 <?php
 
 final class PhabricatorAuthMessageQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $messageKeys;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withMessageKeys(array $keys) {
     $this->messageKeys = $keys;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthMessage();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->messageKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'messageKey IN (%Ls)',
         $this->messageKeys);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $messages) {
     $message_types = PhabricatorAuthMessageType::getAllMessageTypes();
 
     foreach ($messages as $key => $message) {
       $message_key = $message->getMessageKey();
 
       $message_type = idx($message_types, $message_key);
       if (!$message_type) {
         unset($messages[$key]);
         $this->didRejectResult($message);
         continue;
       }
 
       $message->attachMessageType($message_type);
     }
 
     return $messages;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthPasswordQuery.php b/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
index 483936fb30..a77fd54b13 100644
--- a/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
@@ -1,114 +1,110 @@
 <?php
 
 final class PhabricatorAuthPasswordQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $objectPHIDs;
   private $passwordTypes;
   private $isRevoked;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withPasswordTypes(array $types) {
     $this->passwordTypes = $types;
     return $this;
   }
 
   public function withIsRevoked($is_revoked) {
     $this->isRevoked = $is_revoked;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthPassword();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->passwordTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'passwordType IN (%Ls)',
         $this->passwordTypes);
     }
 
     if ($this->isRevoked !== null) {
       $where[] = qsprintf(
         $conn,
         'isRevoked = %d',
         (int)$this->isRevoked);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $passwords) {
     $object_phids = mpull($passwords, 'getObjectPHID');
 
     $objects = id(new PhabricatorObjectQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($object_phids)
       ->execute();
     $objects = mpull($objects, null, 'getPHID');
 
     foreach ($passwords as $key => $password) {
       $object = idx($objects, $password->getObjectPHID());
       if (!$object) {
         unset($passwords[$key]);
         $this->didRejectResult($password);
         continue;
       }
 
       $password->attachObject($object);
     }
 
     return $passwords;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php b/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
index ee073e3ac1..30e5dad113 100644
--- a/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
@@ -1,90 +1,86 @@
 <?php
 
 final class PhabricatorAuthProviderConfigQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $providerClasses;
   private $isEnabled;
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withProviderClasses(array $classes) {
     $this->providerClasses = $classes;
     return $this;
   }
 
   public function withIsEnabled($is_enabled) {
     $this->isEnabled = $is_enabled;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthProviderConfig();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->providerClasses !== null) {
       $where[] = qsprintf(
         $conn,
         'providerClass IN (%Ls)',
         $this->providerClasses);
     }
 
     if ($this->isEnabled !== null) {
       $where[] = qsprintf(
         $conn,
         'isEnabled = %d',
         (int)$this->isEnabled);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $configs) {
 
     foreach ($configs as $key => $config) {
       $provider = $config->getProvider();
       if (!$provider) {
         unset($configs[$key]);
         continue;
       }
     }
 
     return $configs;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php b/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php
index 3a310ed173..7d4aac4a01 100644
--- a/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php
@@ -1,138 +1,134 @@
 <?php
 
 final class PhabricatorAuthSSHKeyQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   const AUTHSTRUCT_CACHEKEY = 'ssh.authstruct';
 
   private $ids;
   private $phids;
   private $objectPHIDs;
   private $keys;
   private $isActive;
 
   public static function deleteSSHKeyCache() {
     $cache = PhabricatorCaches::getMutableCache();
     $authfile_key = self::AUTHSTRUCT_CACHEKEY;
     $cache->deleteKey($authfile_key);
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withKeys(array $keys) {
     assert_instances_of($keys, 'PhabricatorAuthSSHPublicKey');
     $this->keys = $keys;
     return $this;
   }
 
   public function withIsActive($active) {
     $this->isActive = $active;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthSSHKey();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $keys) {
     $object_phids = mpull($keys, 'getObjectPHID');
 
     $objects = id(new PhabricatorObjectQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($object_phids)
       ->execute();
     $objects = mpull($objects, null, 'getPHID');
 
     foreach ($keys as $key => $ssh_key) {
       $object = idx($objects, $ssh_key->getObjectPHID());
 
       // We must have an object, and that object must be a valid object for
       // SSH keys.
       if (!$object || !($object instanceof PhabricatorSSHPublicKeyInterface)) {
         $this->didRejectResult($ssh_key);
         unset($keys[$key]);
         continue;
       }
 
       $ssh_key->attachObject($object);
     }
 
     return $keys;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->keys !== null) {
       $sql = array();
       foreach ($this->keys as $key) {
         $sql[] = qsprintf(
           $conn,
           '(keyType = %s AND keyIndex = %s)',
           $key->getType(),
           $key->getHash());
       }
       $where[] = qsprintf($conn, '%LO', $sql);
     }
 
     if ($this->isActive !== null) {
       if ($this->isActive) {
         $where[] = qsprintf(
           $conn,
           'isActive = %d',
           1);
       } else {
         $where[] = qsprintf(
           $conn,
           'isActive IS NULL');
       }
     }
 
     return $where;
 
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthSessionQuery.php b/src/applications/auth/query/PhabricatorAuthSessionQuery.php
index 00a663e964..4bc7eba73f 100644
--- a/src/applications/auth/query/PhabricatorAuthSessionQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthSessionQuery.php
@@ -1,117 +1,113 @@
 <?php
 
 final class PhabricatorAuthSessionQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $identityPHIDs;
   private $sessionKeys;
   private $sessionTypes;
 
   public function withIdentityPHIDs(array $identity_phids) {
     $this->identityPHIDs = $identity_phids;
     return $this;
   }
 
   public function withSessionKeys(array $keys) {
     $this->sessionKeys = $keys;
     return $this;
   }
 
   public function withSessionTypes(array $types) {
     $this->sessionTypes = $types;
     return $this;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthSession();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $sessions) {
     $identity_phids = mpull($sessions, 'getUserPHID');
 
     $identity_objects = id(new PhabricatorObjectQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($identity_phids)
       ->execute();
     $identity_objects = mpull($identity_objects, null, 'getPHID');
 
     foreach ($sessions as $key => $session) {
       $identity_object = idx($identity_objects, $session->getUserPHID());
       if (!$identity_object) {
         unset($sessions[$key]);
       } else {
         $session->attachIdentityObject($identity_object);
       }
     }
 
     return $sessions;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->identityPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'userPHID IN (%Ls)',
         $this->identityPHIDs);
     }
 
     if ($this->sessionKeys !== null) {
       $hashes = array();
       foreach ($this->sessionKeys as $session_key) {
         $hashes[] = PhabricatorAuthSession::newSessionDigest(
           new PhutilOpaqueEnvelope($session_key));
       }
       $where[] = qsprintf(
         $conn,
         'sessionKey IN (%Ls)',
         $hashes);
     }
 
     if ($this->sessionTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'type IN (%Ls)',
         $this->sessionTypes);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php b/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php
index 72141f75f0..c5cb39096c 100644
--- a/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php
@@ -1,110 +1,106 @@
 <?php
 
 final class PhabricatorAuthTemporaryTokenQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $tokenResources;
   private $tokenTypes;
   private $userPHIDs;
   private $expired;
   private $tokenCodes;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withTokenResources(array $resources) {
     $this->tokenResources = $resources;
     return $this;
   }
 
   public function withTokenTypes(array $types) {
     $this->tokenTypes = $types;
     return $this;
   }
 
   public function withExpired($expired) {
     $this->expired = $expired;
     return $this;
   }
 
   public function withTokenCodes(array $codes) {
     $this->tokenCodes = $codes;
     return $this;
   }
 
   public function withUserPHIDs(array $phids) {
     $this->userPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorAuthTemporaryToken();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->tokenResources !== null) {
       $where[] = qsprintf(
         $conn,
         'tokenResource IN (%Ls)',
         $this->tokenResources);
     }
 
     if ($this->tokenTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'tokenType IN (%Ls)',
         $this->tokenTypes);
     }
 
     if ($this->expired !== null) {
       if ($this->expired) {
         $where[] = qsprintf(
           $conn,
           'tokenExpires <= %d',
           time());
       } else {
         $where[] = qsprintf(
           $conn,
           'tokenExpires > %d',
           time());
       }
     }
 
     if ($this->tokenCodes !== null) {
       $where[] = qsprintf(
         $conn,
         'tokenCode IN (%Ls)',
         $this->tokenCodes);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorAuthApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php b/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php
index c44e0aed4f..b5c5b6eaa2 100644
--- a/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php
+++ b/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php
@@ -1,94 +1,90 @@
 <?php
 
 final class PhabricatorExternalAccountIdentifierQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $providerConfigPHIDs;
   private $externalAccountPHIDs;
   private $rawIdentifiers;
 
   public function withIDs($ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withProviderConfigPHIDs(array $phids) {
     $this->providerConfigPHIDs = $phids;
     return $this;
   }
 
   public function withExternalAccountPHIDs(array $phids) {
     $this->externalAccountPHIDs = $phids;
     return $this;
   }
 
   public function withRawIdentifiers(array $identifiers) {
     $this->rawIdentifiers = $identifiers;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorExternalAccountIdentifier();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->providerConfigPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'providerConfigPHID IN (%Ls)',
         $this->providerConfigPHIDs);
     }
 
     if ($this->externalAccountPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'externalAccountPHID IN (%Ls)',
         $this->externalAccountPHIDs);
     }
 
     if ($this->rawIdentifiers !== null) {
       $hashes = array();
       foreach ($this->rawIdentifiers as $raw_identifier) {
         $hashes[] = PhabricatorHash::digestForIndex($raw_identifier);
       }
       $where[] = qsprintf(
         $conn,
         'identifierHash IN (%Ls)',
         $hashes);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPeopleApplication';
   }
 
 }
diff --git a/src/applications/auth/query/PhabricatorExternalAccountQuery.php b/src/applications/auth/query/PhabricatorExternalAccountQuery.php
index bdc030f20c..f44821d7a9 100644
--- a/src/applications/auth/query/PhabricatorExternalAccountQuery.php
+++ b/src/applications/auth/query/PhabricatorExternalAccountQuery.php
@@ -1,251 +1,247 @@
 <?php
 
 /**
  * NOTE: When loading ExternalAccounts for use in an authentication context
  * (that is, you're going to act as the account or link identities or anything
  * like that) you should require CAN_EDIT capability even if you aren't actually
  * editing the ExternalAccount.
  *
  * ExternalAccounts have a permissive CAN_VIEW policy (like users) because they
  * interact directly with objects and can leave comments, sign documents, etc.
  * However, CAN_EDIT is restricted to users who own the accounts.
  */
 final class PhabricatorExternalAccountQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $userPHIDs;
   private $needImages;
   private $accountSecrets;
   private $providerConfigPHIDs;
   private $needAccountIdentifiers;
   private $rawAccountIdentifiers;
 
   public function withUserPHIDs(array $user_phids) {
     $this->userPHIDs = $user_phids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withIDs($ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withAccountSecrets(array $secrets) {
     $this->accountSecrets = $secrets;
     return $this;
   }
 
   public function needImages($need) {
     $this->needImages = $need;
     return $this;
   }
 
   public function needAccountIdentifiers($need) {
     $this->needAccountIdentifiers = $need;
     return $this;
   }
 
   public function withProviderConfigPHIDs(array $phids) {
     $this->providerConfigPHIDs = $phids;
     return $this;
   }
 
   public function withRawAccountIdentifiers(array $identifiers) {
     $this->rawAccountIdentifiers = $identifiers;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorExternalAccount();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $accounts) {
     $viewer = $this->getViewer();
 
     $configs = id(new PhabricatorAuthProviderConfigQuery())
       ->setViewer($viewer)
       ->withPHIDs(mpull($accounts, 'getProviderConfigPHID'))
       ->execute();
     $configs = mpull($configs, null, 'getPHID');
 
     foreach ($accounts as $key => $account) {
       $config_phid = $account->getProviderConfigPHID();
       $config = idx($configs, $config_phid);
 
       if (!$config) {
         unset($accounts[$key]);
         continue;
       }
 
       $account->attachProviderConfig($config);
     }
 
     if ($this->needImages) {
       $file_phids = mpull($accounts, 'getProfileImagePHID');
       $file_phids = array_filter($file_phids);
 
       if ($file_phids) {
         // NOTE: We use the omnipotent viewer here because these files are
         // usually created during registration and can't be associated with
         // the correct policies, since the relevant user account does not exist
         // yet. In effect, if you can see an ExternalAccount, you can see its
         // profile image.
         $files = id(new PhabricatorFileQuery())
           ->setViewer(PhabricatorUser::getOmnipotentUser())
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
       } else {
         $files = array();
       }
 
       $default_file = null;
       foreach ($accounts as $account) {
         $image_phid = $account->getProfileImagePHID();
         if ($image_phid && isset($files[$image_phid])) {
           $account->attachProfileImageFile($files[$image_phid]);
         } else {
           if ($default_file === null) {
             $default_file = PhabricatorFile::loadBuiltin(
               $this->getViewer(),
               'profile.png');
           }
           $account->attachProfileImageFile($default_file);
         }
       }
     }
 
     if ($this->needAccountIdentifiers) {
       $account_phids = mpull($accounts, 'getPHID');
 
       $identifiers = id(new PhabricatorExternalAccountIdentifierQuery())
         ->setViewer($viewer)
         ->setParentQuery($this)
         ->withExternalAccountPHIDs($account_phids)
         ->execute();
 
       $identifiers = mgroup($identifiers, 'getExternalAccountPHID');
       foreach ($accounts as $account) {
         $account_phid = $account->getPHID();
         $account_identifiers = idx($identifiers, $account_phid, array());
         $account->attachAccountIdentifiers($account_identifiers);
       }
     }
 
     return $accounts;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'account.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'account.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'account.userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     if ($this->accountSecrets !== null) {
       $where[] = qsprintf(
         $conn,
         'account.accountSecret IN (%Ls)',
         $this->accountSecrets);
     }
 
     if ($this->providerConfigPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'account.providerConfigPHID IN (%Ls)',
         $this->providerConfigPHIDs);
 
       // If we have a list of ProviderConfig PHIDs and are joining the
       // identifiers table, also include the list as an additional constraint
       // on the identifiers table.
 
       // This does not change the query results (an Account and its
       // Identifiers always have the same ProviderConfig PHID) but it allows
       // us to use keys on the Identifier table more efficiently.
 
       if ($this->shouldJoinIdentifiersTable()) {
         $where[] = qsprintf(
           $conn,
           'identifier.providerConfigPHID IN (%Ls)',
           $this->providerConfigPHIDs);
       }
     }
 
     if ($this->rawAccountIdentifiers !== null) {
       $hashes = array();
 
       foreach ($this->rawAccountIdentifiers as $raw_identifier) {
         $hashes[] = PhabricatorHash::digestForIndex($raw_identifier);
       }
 
       $where[] = qsprintf(
         $conn,
         'identifier.identifierHash IN (%Ls)',
         $hashes);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinIdentifiersTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %R identifier ON account.phid = identifier.externalAccountPHID',
         new PhabricatorExternalAccountIdentifier());
     }
 
     return $joins;
   }
 
   protected function shouldJoinIdentifiersTable() {
     return ($this->rawAccountIdentifiers !== null);
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->shouldJoinIdentifiersTable()) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   protected function getPrimaryTableAlias() {
     return 'account';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPeopleApplication';
   }
 
 }
diff --git a/src/applications/badges/query/PhabricatorBadgesAwardQuery.php b/src/applications/badges/query/PhabricatorBadgesAwardQuery.php
index 347462de4d..57e53a5a30 100644
--- a/src/applications/badges/query/PhabricatorBadgesAwardQuery.php
+++ b/src/applications/badges/query/PhabricatorBadgesAwardQuery.php
@@ -1,125 +1,121 @@
 <?php
 
 final class PhabricatorBadgesAwardQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $badgePHIDs;
   private $recipientPHIDs;
   private $awarderPHIDs;
   private $badgeStatuses = null;
 
   protected function willFilterPage(array $awards) {
     $badge_phids = array();
     foreach ($awards as $key => $award) {
       $badge_phids[] = $award->getBadgePHID();
     }
 
     $badges = id(new PhabricatorBadgesQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs($badge_phids)
       ->execute();
 
     $badges = mpull($badges, null, 'getPHID');
     foreach ($awards as $key => $award) {
       $award_badge = idx($badges, $award->getBadgePHID());
       if (!$award_badge) {
         unset($awards[$key]);
         $this->didRejectResult($award);
         continue;
       }
       $award->attachBadge($award_badge);
     }
 
     return $awards;
   }
 
   public function withBadgePHIDs(array $phids) {
     $this->badgePHIDs = $phids;
     return $this;
   }
 
   public function withRecipientPHIDs(array $phids) {
     $this->recipientPHIDs = $phids;
     return $this;
   }
 
   public function withAwarderPHIDs(array $phids) {
     $this->awarderPHIDs = $phids;
     return $this;
   }
 
   public function withBadgeStatuses(array $statuses) {
     $this->badgeStatuses = $statuses;
     return $this;
   }
 
   private function shouldJoinBadge() {
     return (bool)$this->badgeStatuses;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   public function newResultObject() {
     return new PhabricatorBadgesAward();
   }
 
   protected function getPrimaryTableAlias() {
     return 'badges_award';
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->badgePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'badges_award.badgePHID IN (%Ls)',
         $this->badgePHIDs);
     }
 
     if ($this->recipientPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'badges_award.recipientPHID IN (%Ls)',
         $this->recipientPHIDs);
     }
 
     if ($this->awarderPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'badges_award.awarderPHID IN (%Ls)',
         $this->awarderPHIDs);
     }
 
     if ($this->badgeStatuses !== null) {
       $where[] = qsprintf(
         $conn,
         'badges_badge.status IN (%Ls)',
         $this->badgeStatuses);
     }
 
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $join = parent::buildJoinClauseParts($conn);
     $badges = new PhabricatorBadgesBadge();
 
     if ($this->shouldJoinBadge()) {
       $join[] = qsprintf(
         $conn,
         'JOIN %T badges_badge ON badges_award.badgePHID = badges_badge.phid',
         $badges->getTableName());
     }
 
     return $join;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorBadgesApplication';
   }
 
 }
diff --git a/src/applications/badges/query/PhabricatorBadgesQuery.php b/src/applications/badges/query/PhabricatorBadgesQuery.php
index dcadf881fe..cc59465f67 100644
--- a/src/applications/badges/query/PhabricatorBadgesQuery.php
+++ b/src/applications/badges/query/PhabricatorBadgesQuery.php
@@ -1,119 +1,115 @@
 <?php
 
 final class PhabricatorBadgesQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $qualities;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withQualities(array $qualities) {
     $this->qualities = $qualities;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       id(new PhabricatorBadgesBadgeNameNgrams()),
       $ngrams);
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function getPrimaryTableAlias() {
     return 'badges';
   }
 
   public function newResultObject() {
     return new PhabricatorBadgesBadge();
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'badges.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'badges.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->qualities !== null) {
       $where[] = qsprintf(
         $conn,
         'badges.quality IN (%Ls)',
         $this->qualities);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'badges.status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorBadgesApplication';
   }
 
   public function getBuiltinOrders() {
     return array(
       'quality' => array(
         'vector' => array('quality', 'id'),
         'name' => pht('Rarity (Rarest First)'),
       ),
       'shoddiness' => array(
         'vector' => array('-quality', '-id'),
         'name' => pht('Rarity (Most Common First)'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getOrderableColumns() {
     return array(
       'quality' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'quality',
         'reverse' => true,
         'type' => 'int',
       ),
     ) + parent::getOrderableColumns();
   }
 
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'quality' => $object->getQuality(),
     );
   }
 
 }
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportQuery.php b/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
index c51671c806..7ef970216f 100644
--- a/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
@@ -1,94 +1,90 @@
 <?php
 
 final class PhabricatorCalendarExportQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $secretKeys;
   private $isDisabled;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function withIsDisabled($is_disabled) {
     $this->isDisabled = $is_disabled;
     return $this;
   }
 
   public function withSecretKeys(array $keys) {
     $this->secretKeys = $keys;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorCalendarExport();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'export.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'export.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'export.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->isDisabled !== null) {
       $where[] = qsprintf(
         $conn,
         'export.isDisabled = %d',
         (int)$this->isDisabled);
     }
 
     if ($this->secretKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'export.secretKey IN (%Ls)',
         $this->secretKeys);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'export';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorCalendarApplication';
   }
 
 }
diff --git a/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php b/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php
index ea7200e614..35891cfd28 100644
--- a/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php
@@ -1,68 +1,64 @@
 <?php
 
 final class PhabricatorCalendarExternalInviteeQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $names;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorCalendarExternalInvitee();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->names !== null) {
       $name_indexes = array();
       foreach ($this->names as $name) {
         $name_indexes[] = PhabricatorHash::digestForIndex($name);
       }
       $where[] = qsprintf(
         $conn,
         'nameIndex IN (%Ls)',
         $name_indexes);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorCalendarApplication';
   }
 
 }
diff --git a/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php b/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php
index 81f309bdca..731b1209cc 100644
--- a/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php
@@ -1,111 +1,107 @@
 <?php
 
 final class PhabricatorCalendarImportLogQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $importPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withImportPHIDs(array $phids) {
     $this->importPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorCalendarImportLog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'log.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'log.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->importPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'log.importPHID IN (%Ls)',
         $this->importPHIDs);
     }
 
 
     return $where;
   }
 
   protected function willFilterPage(array $page) {
     $viewer = $this->getViewer();
 
     $type_map = PhabricatorCalendarImportLogType::getAllLogTypes();
     foreach ($page as $log) {
       $type_constant = $log->getParameter('type');
 
       $type_object = idx($type_map, $type_constant);
       if (!$type_object) {
         $type_object = new PhabricatorCalendarImportDefaultLogType();
       }
 
       $type_object = clone $type_object;
       $log->attachLogType($type_object);
     }
 
     $import_phids = mpull($page, 'getImportPHID');
 
     if ($import_phids) {
       $imports = id(new PhabricatorCalendarImportQuery())
         ->setViewer($viewer)
         ->withPHIDs($import_phids)
         ->execute();
       $imports = mpull($imports, null, 'getPHID');
     } else {
       $imports = array();
     }
 
     foreach ($page as $key => $log) {
       $import = idx($imports, $log->getImportPHID());
       if (!$import) {
         $this->didRejectResult($import);
         unset($page[$key]);
         continue;
       }
 
       $log->attachImport($import);
     }
 
     return $page;
   }
 
   protected function getPrimaryTableAlias() {
     return 'log';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorCalendarApplication';
   }
 
 }
diff --git a/src/applications/calendar/query/PhabricatorCalendarImportQuery.php b/src/applications/calendar/query/PhabricatorCalendarImportQuery.php
index 5d44657994..0e3dbbf387 100644
--- a/src/applications/calendar/query/PhabricatorCalendarImportQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarImportQuery.php
@@ -1,99 +1,95 @@
 <?php
 
 final class PhabricatorCalendarImportQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $isDisabled;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function withIsDisabled($is_disabled) {
     $this->isDisabled = $is_disabled;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorCalendarImport();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'import.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'import.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'import.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->isDisabled !== null) {
       $where[] = qsprintf(
         $conn,
         'import.isDisabled = %d',
         (int)$this->isDisabled);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $page) {
     $engines = PhabricatorCalendarImportEngine::getAllImportEngines();
     foreach ($page as $key => $import) {
       $engine_type = $import->getEngineType();
       $engine = idx($engines, $engine_type);
 
       if (!$engine) {
         unset($page[$key]);
         $this->didRejectResult($import);
         continue;
       }
 
       $import->attachEngine(clone $engine);
     }
 
     return $page;
   }
 
   protected function getPrimaryTableAlias() {
     return 'import';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorCalendarApplication';
   }
 
 }
diff --git a/src/applications/conduit/query/PhabricatorConduitLogQuery.php b/src/applications/conduit/query/PhabricatorConduitLogQuery.php
index 23a5b46786..19cb31a812 100644
--- a/src/applications/conduit/query/PhabricatorConduitLogQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitLogQuery.php
@@ -1,117 +1,113 @@
 <?php
 
 final class PhabricatorConduitLogQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $callerPHIDs;
   private $methods;
   private $methodStatuses;
   private $epochMin;
   private $epochMax;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withCallerPHIDs(array $phids) {
     $this->callerPHIDs = $phids;
     return $this;
   }
 
   public function withMethods(array $methods) {
     $this->methods = $methods;
     return $this;
   }
 
   public function withMethodStatuses(array $statuses) {
     $this->methodStatuses = $statuses;
     return $this;
   }
 
   public function withEpochBetween($epoch_min, $epoch_max) {
     $this->epochMin = $epoch_min;
     $this->epochMax = $epoch_max;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorConduitMethodCallLog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->callerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'callerPHID IN (%Ls)',
         $this->callerPHIDs);
     }
 
     if ($this->methods !== null) {
       $where[] = qsprintf(
         $conn,
         'method IN (%Ls)',
         $this->methods);
     }
 
     if ($this->methodStatuses !== null) {
       $statuses = array_fuse($this->methodStatuses);
 
       $methods = id(new PhabricatorConduitMethodQuery())
         ->setViewer($this->getViewer())
         ->execute();
 
       $method_names = array();
       foreach ($methods as $method) {
         $status = $method->getMethodStatus();
         if (isset($statuses[$status])) {
           $method_names[] = $method->getAPIMethodName();
         }
       }
 
       if (!$method_names) {
         throw new PhabricatorEmptyQueryException();
       }
 
       $where[] = qsprintf(
         $conn,
         'method IN (%Ls)',
         $method_names);
     }
 
     if ($this->epochMin !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCreated >= %d',
         $this->epochMin);
     }
 
     if ($this->epochMax !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCreated <= %d',
         $this->epochMax);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorConduitApplication';
   }
 
 }
diff --git a/src/applications/conduit/query/PhabricatorConduitTokenQuery.php b/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
index ef35b006a7..384efccadf 100644
--- a/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
@@ -1,119 +1,115 @@
 <?php
 
 final class PhabricatorConduitTokenQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $objectPHIDs;
   private $expired;
   private $tokens;
   private $tokenTypes;
 
   public function withExpired($expired) {
     $this->expired = $expired;
     return $this;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withObjectPHIDs(array $phids) {
     $this->objectPHIDs = $phids;
     return $this;
   }
 
   public function withTokens(array $tokens) {
     $this->tokens = $tokens;
     return $this;
   }
 
   public function withTokenTypes(array $types) {
     $this->tokenTypes = $types;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorConduitToken();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->tokens !== null) {
       $where[] = qsprintf(
         $conn,
         'token IN (%Ls)',
         $this->tokens);
     }
 
     if ($this->tokenTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'tokenType IN (%Ls)',
         $this->tokenTypes);
     }
 
     if ($this->expired !== null) {
       if ($this->expired) {
         $where[] = qsprintf(
           $conn,
           'expires <= %d',
           PhabricatorTime::getNow());
       } else {
         $where[] = qsprintf(
           $conn,
           'expires IS NULL OR expires > %d',
           PhabricatorTime::getNow());
       }
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $tokens) {
     $object_phids = mpull($tokens, 'getObjectPHID');
     $objects = id(new PhabricatorObjectQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($object_phids)
       ->execute();
     $objects = mpull($objects, null, 'getPHID');
 
     foreach ($tokens as $key => $token) {
       $object = idx($objects, $token->getObjectPHID(), null);
       if (!$object) {
         $this->didRejectResult($token);
         unset($tokens[$key]);
         continue;
       }
       $token->attachObject($object);
     }
 
     return $tokens;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorConduitApplication';
   }
 
 }
diff --git a/src/applications/countdown/query/PhabricatorCountdownQuery.php b/src/applications/countdown/query/PhabricatorCountdownQuery.php
index 67a2f3a9e3..4a6df16e8e 100644
--- a/src/applications/countdown/query/PhabricatorCountdownQuery.php
+++ b/src/applications/countdown/query/PhabricatorCountdownQuery.php
@@ -1,107 +1,103 @@
 <?php
 
 final class PhabricatorCountdownQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $upcoming;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
   public function withUpcoming() {
     $this->upcoming = true;
     return $this;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   public function newResultObject() {
     return new PhabricatorCountdown();
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'authorPHID in (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->upcoming !== null) {
       $where[] = qsprintf(
         $conn,
         'epoch >= %d',
         PhabricatorTime::getNow());
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorCountdownApplication';
   }
 
   public function getBuiltinOrders() {
     return array(
       'ending' => array(
         'vector' => array('-epoch', '-id'),
         'name' => pht('End Date (Past to Future)'),
       ),
       'unending' => array(
         'vector' => array('epoch', 'id'),
         'name' => pht('End Date (Future to Past)'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getOrderableColumns() {
     return array(
       'epoch' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'epoch',
         'type' => 'int',
       ),
     ) + parent::getOrderableColumns();
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'epoch' => (int)$object->getEpoch(),
     );
   }
 
 }
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
index dd32d1c9dc..c67b756262 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
@@ -1,102 +1,98 @@
 <?php
 
 final class PhabricatorDashboardPanelQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $archived;
   private $panelTypes;
   private $authorPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withArchived($archived) {
     $this->archived = $archived;
     return $this;
   }
 
   public function withPanelTypes(array $types) {
     $this->panelTypes = $types;
     return $this;
   }
 
   public function withAuthorPHIDs(array $authors) {
     $this->authorPHIDs = $authors;
     return $this;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   public function newResultObject() {
     // TODO: If we don't do this, SearchEngine explodes when trying to
     // enumerate custom fields. For now, just give the panel a default panel
     // type so custom fields work. In the long run, we may want to find a
     // cleaner or more general approach for this.
     $text_type = id(new PhabricatorDashboardTextPanelType())
       ->getPanelTypeKey();
 
     return id(new PhabricatorDashboardPanel())
       ->setPanelType($text_type);
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'panel.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'panel.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->archived !== null) {
       $where[] = qsprintf(
         $conn,
         'panel.isArchived = %d',
         (int)$this->archived);
     }
 
     if ($this->panelTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'panel.panelType IN (%Ls)',
         $this->panelTypes);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'panel.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDashboardApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'panel';
   }
 
 }
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php
index 857c4dc215..418262c745 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php
@@ -1,68 +1,64 @@
 <?php
 
 final class PhabricatorDashboardPortalQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorDashboardPortal();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'portal.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'portal.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'portal.status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDashboardApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'portal';
   }
 
 }
diff --git a/src/applications/dashboard/query/PhabricatorDashboardQuery.php b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
index 76854bffc1..954a565ac6 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
@@ -1,103 +1,99 @@
 <?php
 
 final class PhabricatorDashboardQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $statuses;
   private $authorPHIDs;
   private $canEdit;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withAuthorPHIDs(array $authors) {
     $this->authorPHIDs = $authors;
     return $this;
   }
 
   public function withCanEdit($can_edit) {
     $this->canEdit = $can_edit;
     return $this;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   public function newResultObject() {
     return new PhabricatorDashboard();
   }
 
   protected function didFilterPage(array $dashboards) {
 
     $phids = mpull($dashboards, 'getPHID');
 
     if ($this->canEdit) {
       $dashboards = id(new PhabricatorPolicyFilter())
         ->setViewer($this->getViewer())
         ->requireCapabilities(array(
           PhabricatorPolicyCapability::CAN_EDIT,
         ))
         ->apply($dashboards);
     }
 
     return $dashboards;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'dashboard.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'dashboard.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'dashboard.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'dashboard.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDashboardApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'dashboard';
   }
 
 }
diff --git a/src/applications/differential/query/DifferentialChangesetQuery.php b/src/applications/differential/query/DifferentialChangesetQuery.php
index e2357f9278..ee29aa1cf8 100644
--- a/src/applications/differential/query/DifferentialChangesetQuery.php
+++ b/src/applications/differential/query/DifferentialChangesetQuery.php
@@ -1,182 +1,178 @@
 <?php
 
 final class DifferentialChangesetQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $diffPHIDs;
 
   private $diffs;
 
   private $needAttachToDiffs;
   private $needHunks;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withDiffs(array $diffs) {
     assert_instances_of($diffs, 'DifferentialDiff');
     $this->diffs = $diffs;
     return $this;
   }
 
   public function withDiffPHIDs(array $phids) {
     $this->diffPHIDs = $phids;
     return $this;
   }
 
   public function needAttachToDiffs($attach) {
     $this->needAttachToDiffs = $attach;
     return $this;
   }
 
   public function needHunks($need) {
     $this->needHunks = $need;
     return $this;
   }
 
   protected function willExecute() {
     // If we fail to load any changesets (which is possible in the case of an
     // empty commit) we'll never call didFilterPage(). Attach empty changeset
     // lists now so that we end up with the right result.
     if ($this->needAttachToDiffs) {
       foreach ($this->diffs as $diff) {
         $diff->attachChangesets(array());
       }
     }
   }
 
   public function newResultObject() {
     return new DifferentialChangeset();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $changesets) {
     // First, attach all the diffs we already have. We can just do this
     // directly without worrying about querying for them. When we don't have
     // a diff, record that we need to load it.
     if ($this->diffs) {
       $have_diffs = mpull($this->diffs, null, 'getID');
     } else {
       $have_diffs = array();
     }
 
     $must_load = array();
     foreach ($changesets as $key => $changeset) {
       $diff_id = $changeset->getDiffID();
       if (isset($have_diffs[$diff_id])) {
         $changeset->attachDiff($have_diffs[$diff_id]);
       } else {
         $must_load[$key] = $changeset;
       }
     }
 
     // Load all the diffs we don't have.
     $need_diff_ids = mpull($must_load, 'getDiffID');
     $more_diffs = array();
     if ($need_diff_ids) {
       $more_diffs = id(new DifferentialDiffQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withIDs($need_diff_ids)
         ->execute();
       $more_diffs = mpull($more_diffs, null, 'getID');
     }
 
     // Attach the diffs we loaded.
     foreach ($must_load as $key => $changeset) {
       $diff_id = $changeset->getDiffID();
       if (isset($more_diffs[$diff_id])) {
         $changeset->attachDiff($more_diffs[$diff_id]);
       } else {
         // We didn't have the diff, and could not load it (it does not exist,
         // or we can't see it), so filter this result out.
         unset($changesets[$key]);
       }
     }
 
     return $changesets;
   }
 
   protected function didFilterPage(array $changesets) {
     if ($this->needAttachToDiffs) {
       $changeset_groups = mgroup($changesets, 'getDiffID');
       foreach ($this->diffs as $diff) {
         $diff_changesets = idx($changeset_groups, $diff->getID(), array());
         $diff->attachChangesets($diff_changesets);
       }
     }
 
     if ($this->needHunks) {
       id(new DifferentialHunkQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withChangesets($changesets)
         ->needAttachToChangesets(true)
         ->execute();
     }
 
     return $changesets;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->diffs !== null) {
       $where[] = qsprintf(
         $conn,
         'diffID IN (%Ld)',
         mpull($this->diffs, 'getID'));
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->diffPHIDs !== null) {
       $diff_ids = queryfx_all(
         $conn,
         'SELECT id FROM %R WHERE phid IN (%Ls)',
         new DifferentialDiff(),
         $this->diffPHIDs);
       $diff_ids = ipull($diff_ids, 'id', null);
 
       if (!$diff_ids) {
         throw new PhabricatorEmptyQueryException();
       }
 
       $where[] = qsprintf(
         $conn,
         'diffID IN (%Ld)',
         $diff_ids);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDifferentialApplication';
   }
 
 }
diff --git a/src/applications/differential/query/DifferentialDiffQuery.php b/src/applications/differential/query/DifferentialDiffQuery.php
index 3b1dd3ae62..04019df1e0 100644
--- a/src/applications/differential/query/DifferentialDiffQuery.php
+++ b/src/applications/differential/query/DifferentialDiffQuery.php
@@ -1,195 +1,191 @@
 <?php
 
 final class DifferentialDiffQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $revisionIDs;
   private $revisionPHIDs;
   private $commitPHIDs;
   private $hasRevision;
 
   private $needChangesets = false;
   private $needProperties;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRevisionIDs(array $revision_ids) {
     $this->revisionIDs = $revision_ids;
     return $this;
   }
 
   public function withRevisionPHIDs(array $revision_phids) {
     $this->revisionPHIDs = $revision_phids;
     return $this;
   }
 
   public function withCommitPHIDs(array $phids) {
     $this->commitPHIDs = $phids;
     return $this;
   }
 
   public function withHasRevision($has_revision) {
     $this->hasRevision = $has_revision;
     return $this;
   }
 
   public function needChangesets($bool) {
     $this->needChangesets = $bool;
     return $this;
   }
 
   public function needProperties($need_properties) {
     $this->needProperties = $need_properties;
     return $this;
   }
 
   public function newResultObject() {
     return new DifferentialDiff();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $diffs) {
     $revision_ids = array_filter(mpull($diffs, 'getRevisionID'));
 
     $revisions = array();
     if ($revision_ids) {
       $revisions = id(new DifferentialRevisionQuery())
         ->setViewer($this->getViewer())
         ->withIDs($revision_ids)
         ->execute();
     }
 
     foreach ($diffs as $key => $diff) {
       if (!$diff->getRevisionID()) {
         continue;
       }
 
       $revision = idx($revisions, $diff->getRevisionID());
       if ($revision) {
         $diff->attachRevision($revision);
         continue;
       }
 
       unset($diffs[$key]);
     }
 
 
     if ($diffs && $this->needChangesets) {
       $diffs = $this->loadChangesets($diffs);
     }
 
     return $diffs;
   }
 
   protected function didFilterPage(array $diffs) {
     if ($this->needProperties) {
       $properties = id(new DifferentialDiffProperty())->loadAllWhere(
         'diffID IN (%Ld)',
         mpull($diffs, 'getID'));
 
       $properties = mgroup($properties, 'getDiffID');
       foreach ($diffs as $diff) {
         $map = idx($properties, $diff->getID(), array());
         $map = mpull($map, 'getData', 'getName');
         $diff->attachDiffProperties($map);
       }
     }
 
     return $diffs;
   }
 
   private function loadChangesets(array $diffs) {
     id(new DifferentialChangesetQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withDiffs($diffs)
       ->needAttachToDiffs(true)
       ->needHunks(true)
       ->execute();
 
     return $diffs;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->revisionIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'revisionID IN (%Ld)',
         $this->revisionIDs);
     }
 
     if ($this->commitPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'commitPHID IN (%Ls)',
         $this->commitPHIDs);
     }
 
     if ($this->hasRevision !== null) {
       if ($this->hasRevision) {
         $where[] = qsprintf(
           $conn,
           'revisionID IS NOT NULL');
       } else {
         $where[] = qsprintf(
           $conn,
           'revisionID IS NULL');
       }
     }
 
     if ($this->revisionPHIDs !== null) {
       $viewer = $this->getViewer();
 
       $revisions = id(new DifferentialRevisionQuery())
         ->setViewer($viewer)
         ->setParentQuery($this)
         ->withPHIDs($this->revisionPHIDs)
         ->execute();
       $revision_ids = mpull($revisions, 'getID');
       if (!$revision_ids) {
         throw new PhabricatorEmptyQueryException();
       }
 
       $where[] = qsprintf(
         $conn,
         'revisionID IN (%Ls)',
         $revision_ids);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDifferentialApplication';
   }
 
 }
diff --git a/src/applications/differential/query/DifferentialHunkQuery.php b/src/applications/differential/query/DifferentialHunkQuery.php
index 981c2b4782..21787f04e5 100644
--- a/src/applications/differential/query/DifferentialHunkQuery.php
+++ b/src/applications/differential/query/DifferentialHunkQuery.php
@@ -1,93 +1,89 @@
 <?php
 
 final class DifferentialHunkQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $changesets;
   private $shouldAttachToChangesets;
 
   public function withChangesets(array $changesets) {
     assert_instances_of($changesets, 'DifferentialChangeset');
     $this->changesets = $changesets;
     return $this;
   }
 
   public function needAttachToChangesets($attach) {
     $this->shouldAttachToChangesets = $attach;
     return $this;
   }
 
   protected function willExecute() {
     // If we fail to load any hunks at all (for example, because all of
     // the requested changesets are directories or empty files and have no
     // hunks) we'll never call didFilterPage(), and thus never have an
     // opportunity to attach hunks. Attach empty hunk lists now so that we
     // end up with the right result.
     if ($this->shouldAttachToChangesets) {
       foreach ($this->changesets as $changeset) {
         $changeset->attachHunks(array());
       }
     }
   }
 
   public function newResultObject() {
     return new DifferentialHunk();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $hunks) {
     $changesets = mpull($this->changesets, null, 'getID');
     foreach ($hunks as $key => $hunk) {
       $changeset = idx($changesets, $hunk->getChangesetID());
       if (!$changeset) {
         unset($hunks[$key]);
       }
       $hunk->attachChangeset($changeset);
     }
 
     return $hunks;
   }
 
   protected function didFilterPage(array $hunks) {
     if ($this->shouldAttachToChangesets) {
       $hunk_groups = mgroup($hunks, 'getChangesetID');
       foreach ($this->changesets as $changeset) {
         $hunks = idx($hunk_groups, $changeset->getID(), array());
         $changeset->attachHunks($hunks);
       }
     }
 
     return $hunks;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if (!$this->changesets) {
       throw new Exception(
         pht(
           'You must load hunks via changesets, with %s!',
           'withChangesets()'));
     }
 
     $where[] = qsprintf(
       $conn,
       'changesetID IN (%Ld)',
       mpull($this->changesets, 'getID'));
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDifferentialApplication';
   }
 
   protected function getDefaultOrderVector() {
     // TODO: Do we need this?
     return array('-id');
   }
 
 }
diff --git a/src/applications/differential/query/DifferentialViewStateQuery.php b/src/applications/differential/query/DifferentialViewStateQuery.php
index 6ef63721e4..604a6de1db 100644
--- a/src/applications/differential/query/DifferentialViewStateQuery.php
+++ b/src/applications/differential/query/DifferentialViewStateQuery.php
@@ -1,64 +1,60 @@
 <?php
 
 final class DifferentialViewStateQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $viewerPHIDs;
   private $objectPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withViewerPHIDs(array $phids) {
     $this->viewerPHIDs = $phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $phids) {
     $this->objectPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new DifferentialViewState();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->viewerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'viewerPHID IN (%Ls)',
         $this->viewerPHIDs);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDifferentialApplication';
   }
 
 }
diff --git a/src/applications/diffusion/query/DiffusionCommitHintQuery.php b/src/applications/diffusion/query/DiffusionCommitHintQuery.php
index bfd8045131..c0794a4387 100644
--- a/src/applications/diffusion/query/DiffusionCommitHintQuery.php
+++ b/src/applications/diffusion/query/DiffusionCommitHintQuery.php
@@ -1,116 +1,112 @@
 <?php
 
 final class DiffusionCommitHintQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $repositoryPHIDs;
   private $oldCommitIdentifiers;
 
   private $commits;
   private $commitMap;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $phids) {
     $this->repositoryPHIDs = $phids;
     return $this;
   }
 
   public function withOldCommitIdentifiers(array $identifiers) {
     $this->oldCommitIdentifiers = $identifiers;
     return $this;
   }
 
   public function withCommits(array $commits) {
     assert_instances_of($commits, 'PhabricatorRepositoryCommit');
 
     $repository_phids = array();
     foreach ($commits as $commit) {
       $repository_phids[] = $commit->getRepository()->getPHID();
     }
 
     $this->repositoryPHIDs = $repository_phids;
     $this->oldCommitIdentifiers = mpull($commits, 'getCommitIdentifier');
     $this->commits = $commits;
 
     return $this;
   }
 
   public function getCommitMap() {
     if ($this->commitMap === null) {
       throw new PhutilInvalidStateException('execute');
     }
 
     return $this->commitMap;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryCommitHint();
   }
 
   protected function willExecute() {
     $this->commitMap = array();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->oldCommitIdentifiers !== null) {
       $where[] = qsprintf(
         $conn,
         'oldCommitIdentifier IN (%Ls)',
         $this->oldCommitIdentifiers);
     }
 
     return $where;
   }
 
   protected function didFilterPage(array $hints) {
     if ($this->commits) {
       $map = array();
       foreach ($this->commits as $commit) {
         $repository_phid = $commit->getRepository()->getPHID();
         $identifier = $commit->getCommitIdentifier();
         $map[$repository_phid][$identifier] = $commit->getPHID();
       }
 
       foreach ($hints as $hint) {
         $repository_phid = $hint->getRepositoryPHID();
         $identifier = $hint->getOldCommitIdentifier();
         if (isset($map[$repository_phid][$identifier])) {
           $commit_phid = $map[$repository_phid][$identifier];
           $this->commitMap[$commit_phid] = $hint;
         }
       }
     }
 
     return $hints;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php b/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
index bc794cc629..2a33206831 100644
--- a/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
+++ b/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
@@ -1,51 +1,47 @@
 <?php
 
 final class DoorkeeperExternalObjectQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   protected $phids;
   protected $objectKeys;
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withObjectKeys(array $keys) {
     $this->objectKeys = $keys;
     return $this;
   }
 
   public function newResultObject() {
     return new DoorkeeperExternalObject();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->objectKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'objectKey IN (%Ls)',
         $this->objectKeys);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDoorkeeperApplication';
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockAuthorizationQuery.php b/src/applications/drydock/query/DrydockAuthorizationQuery.php
index d6436fc93a..8c5c58c853 100644
--- a/src/applications/drydock/query/DrydockAuthorizationQuery.php
+++ b/src/applications/drydock/query/DrydockAuthorizationQuery.php
@@ -1,175 +1,171 @@
 <?php
 
 final class DrydockAuthorizationQuery extends DrydockQuery {
 
   private $ids;
   private $phids;
   private $blueprintPHIDs;
   private $objectPHIDs;
   private $blueprintStates;
   private $objectStates;
 
   public static function isFullyAuthorized(
     $object_phid,
     array $blueprint_phids) {
 
     if (!$blueprint_phids) {
       return true;
     }
 
     $authorizations = id(new self())
       ->setViewer(PhabricatorUser::getOmnipotentUser())
       ->withObjectPHIDs(array($object_phid))
       ->withBlueprintPHIDs($blueprint_phids)
       ->execute();
     $authorizations = mpull($authorizations, null, 'getBlueprintPHID');
 
     foreach ($blueprint_phids as $phid) {
       $authorization = idx($authorizations, $phid);
       if (!$authorization) {
         return false;
       }
 
       if (!$authorization->isAuthorized()) {
         return false;
       }
     }
 
     return true;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBlueprintPHIDs(array $phids) {
     $this->blueprintPHIDs = $phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $phids) {
     $this->objectPHIDs = $phids;
     return $this;
   }
 
   public function withBlueprintStates(array $states) {
     $this->blueprintStates = $states;
     return $this;
   }
 
   public function withObjectStates(array $states) {
     $this->objectStates = $states;
     return $this;
   }
 
   public function newResultObject() {
     return new DrydockAuthorization();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $authorizations) {
     $blueprint_phids = mpull($authorizations, 'getBlueprintPHID');
     if ($blueprint_phids) {
       $blueprints = id(new DrydockBlueprintQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($blueprint_phids)
         ->execute();
       $blueprints = mpull($blueprints, null, 'getPHID');
     } else {
       $blueprints = array();
     }
 
     foreach ($authorizations as $key => $authorization) {
       $blueprint = idx($blueprints, $authorization->getBlueprintPHID());
       if (!$blueprint) {
         $this->didRejectResult($authorization);
         unset($authorizations[$key]);
         continue;
       }
       $authorization->attachBlueprint($blueprint);
     }
 
     $object_phids = mpull($authorizations, 'getObjectPHID');
     if ($object_phids) {
       $objects = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($object_phids)
         ->execute();
       $objects = mpull($objects, null, 'getPHID');
     } else {
       $objects = array();
     }
 
     foreach ($authorizations as $key => $authorization) {
       $object = idx($objects, $authorization->getObjectPHID());
       if (!$object) {
         $this->didRejectResult($authorization);
         unset($authorizations[$key]);
         continue;
       }
       $authorization->attachObject($object);
     }
 
     return $authorizations;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->blueprintPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprintPHID IN (%Ls)',
         $this->blueprintPHIDs);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->blueprintStates !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprintAuthorizationState IN (%Ls)',
         $this->blueprintStates);
     }
 
     if ($this->objectStates !== null) {
       $where[] = qsprintf(
         $conn,
         'objectAuthorizationState IN (%Ls)',
         $this->objectStates);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockBlueprintQuery.php b/src/applications/drydock/query/DrydockBlueprintQuery.php
index a5df734e19..c163103d16 100644
--- a/src/applications/drydock/query/DrydockBlueprintQuery.php
+++ b/src/applications/drydock/query/DrydockBlueprintQuery.php
@@ -1,241 +1,237 @@
 <?php
 
 final class DrydockBlueprintQuery extends DrydockQuery {
 
   private $ids;
   private $phids;
   private $blueprintClasses;
   private $datasourceQuery;
   private $disabled;
   private $authorizedPHIDs;
 
   private $identifiers;
   private $identifierIDs;
   private $identifierPHIDs;
   private $identifierMap;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBlueprintClasses(array $classes) {
     $this->blueprintClasses = $classes;
     return $this;
   }
 
   public function withDatasourceQuery($query) {
     $this->datasourceQuery = $query;
     return $this;
   }
 
   public function withDisabled($disabled) {
     $this->disabled = $disabled;
     return $this;
   }
 
   public function withAuthorizedPHIDs(array $phids) {
     $this->authorizedPHIDs = $phids;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new DrydockBlueprintNameNgrams(),
       $ngrams);
   }
 
   public function withIdentifiers(array $identifiers) {
     if (!$identifiers) {
       throw new Exception(
         pht(
           'Can not issue a query with an empty identifier list.'));
     }
 
     $this->identifiers = $identifiers;
 
     $ids = array();
     $phids = array();
 
     foreach ($identifiers as $identifier) {
       if (ctype_digit($identifier)) {
         $ids[] = $identifier;
       } else {
         $phids[] = $identifier;
       }
     }
 
     $this->identifierIDs = $ids;
     $this->identifierPHIDs = $phids;
 
     return $this;
   }
 
   public function getIdentifierMap() {
     if ($this->identifierMap === null) {
       throw new Exception(
         pht(
           'Execute a query with identifiers before getting the '.
           'identifier map.'));
     }
 
     return $this->identifierMap;
   }
 
   public function newResultObject() {
     return new DrydockBlueprint();
   }
 
   protected function getPrimaryTableAlias() {
     return 'blueprint';
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willExecute() {
     if ($this->identifiers) {
       $this->identifierMap = array();
     } else {
       $this->identifierMap = null;
     }
   }
 
   protected function willFilterPage(array $blueprints) {
     $impls = DrydockBlueprintImplementation::getAllBlueprintImplementations();
     foreach ($blueprints as $key => $blueprint) {
       $impl = idx($impls, $blueprint->getClassName());
       if (!$impl) {
         $this->didRejectResult($blueprint);
         unset($blueprints[$key]);
         continue;
       }
       $impl = clone $impl;
       $blueprint->attachImplementation($impl);
     }
 
     if ($this->identifiers) {
       $id_map = mpull($blueprints, null, 'getID');
       $phid_map = mpull($blueprints, null, 'getPHID');
 
       $map = $this->identifierMap;
 
       foreach ($this->identifierIDs as $id) {
         if (isset($id_map[$id])) {
           $map[$id] = $id_map[$id];
         }
       }
 
       foreach ($this->identifierPHIDs as $phid) {
         if (isset($phid_map[$phid])) {
           $map[$phid] = $phid_map[$phid];
         }
       }
 
       // Just for consistency, reorder the map to match input order.
       $map = array_select_keys($map, $this->identifiers);
 
       $this->identifierMap = $map;
     }
 
     return $blueprints;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprint.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprint.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->datasourceQuery !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprint.blueprintName LIKE %>',
         $this->datasourceQuery);
     }
 
     if ($this->blueprintClasses !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprint.className IN (%Ls)',
         $this->blueprintClasses);
     }
 
     if ($this->disabled !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprint.isDisabled = %d',
         (int)$this->disabled);
     }
 
     if ($this->identifiers !== null) {
       $parts = array();
 
       if ($this->identifierIDs) {
         $parts[] = qsprintf(
           $conn,
           'blueprint.id IN (%Ld)',
           $this->identifierIDs);
       }
 
       if ($this->identifierPHIDs) {
         $parts[] = qsprintf(
           $conn,
           'blueprint.phid IN (%Ls)',
           $this->identifierPHIDs);
       }
 
       $where[] = qsprintf(
         $conn,
         '%LO',
         $parts);
     }
 
     return $where;
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->authorizedPHIDs !== null) {
       return true;
     }
     return parent::shouldGroupQueryResultRows();
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->authorizedPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T authorization
           ON authorization.blueprintPHID = blueprint.phid
           AND authorization.objectPHID IN (%Ls)
           AND authorization.objectAuthorizationState = %s
           AND authorization.blueprintAuthorizationState = %s',
         id(new DrydockAuthorization())->getTableName(),
         $this->authorizedPHIDs,
         DrydockAuthorization::OBJECTAUTH_ACTIVE,
         DrydockAuthorization::BLUEPRINTAUTH_AUTHORIZED);
     }
 
     return $joins;
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockCommandQuery.php b/src/applications/drydock/query/DrydockCommandQuery.php
index 0d71288a85..fef6170ec9 100644
--- a/src/applications/drydock/query/DrydockCommandQuery.php
+++ b/src/applications/drydock/query/DrydockCommandQuery.php
@@ -1,82 +1,78 @@
 <?php
 
 final class DrydockCommandQuery extends DrydockQuery {
 
   private $ids;
   private $targetPHIDs;
   private $consumed;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withTargetPHIDs(array $phids) {
     $this->targetPHIDs = $phids;
     return $this;
   }
 
   public function withConsumed($consumed) {
     $this->consumed = $consumed;
     return $this;
   }
 
   public function newResultObject() {
     return new DrydockCommand();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $commands) {
     $target_phids = mpull($commands, 'getTargetPHID');
 
     $targets = id(new PhabricatorObjectQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($target_phids)
       ->execute();
     $targets = mpull($targets, null, 'getPHID');
 
     foreach ($commands as $key => $command) {
       $target = idx($targets, $command->getTargetPHID());
       if (!$target) {
         $this->didRejectResult($command);
         unset($commands[$key]);
         continue;
       }
       $command->attachCommandTarget($target);
     }
 
     return $commands;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->targetPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'targetPHID IN (%Ls)',
         $this->targetPHIDs);
     }
 
     if ($this->consumed !== null) {
       $where[] = qsprintf(
         $conn,
         'isConsumed = %d',
         (int)$this->consumed);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockLeaseQuery.php b/src/applications/drydock/query/DrydockLeaseQuery.php
index 6bfb8deefe..4950764486 100644
--- a/src/applications/drydock/query/DrydockLeaseQuery.php
+++ b/src/applications/drydock/query/DrydockLeaseQuery.php
@@ -1,174 +1,170 @@
 <?php
 
 final class DrydockLeaseQuery extends DrydockQuery {
 
   private $ids;
   private $phids;
   private $resourcePHIDs;
   private $ownerPHIDs;
   private $statuses;
   private $datasourceQuery;
   private $needUnconsumedCommands;
   private $minModified;
   private $maxModified;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withResourcePHIDs(array $phids) {
     $this->resourcePHIDs = $phids;
     return $this;
   }
 
   public function withOwnerPHIDs(array $phids) {
     $this->ownerPHIDs = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withDatasourceQuery($query) {
     $this->datasourceQuery = $query;
     return $this;
   }
 
   public function withDateModifiedBetween($min_epoch, $max_epoch) {
     $this->minModified = $min_epoch;
     $this->maxModified = $max_epoch;
     return $this;
   }
 
   public function needUnconsumedCommands($need) {
     $this->needUnconsumedCommands = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new DrydockLease();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $leases) {
     $resource_phids = array_filter(mpull($leases, 'getResourcePHID'));
     if ($resource_phids) {
       $resources = id(new DrydockResourceQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs(array_unique($resource_phids))
         ->execute();
       $resources = mpull($resources, null, 'getPHID');
     } else {
       $resources = array();
     }
 
     foreach ($leases as $key => $lease) {
       $resource = null;
       if ($lease->getResourcePHID()) {
         $resource = idx($resources, $lease->getResourcePHID());
         if (!$resource) {
           $this->didRejectResult($lease);
           unset($leases[$key]);
           continue;
         }
       }
       $lease->attachResource($resource);
     }
 
     return $leases;
   }
 
   protected function didFilterPage(array $leases) {
     if ($this->needUnconsumedCommands) {
       $commands = id(new DrydockCommandQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withTargetPHIDs(mpull($leases, 'getPHID'))
         ->withConsumed(false)
         ->execute();
       $commands = mgroup($commands, 'getTargetPHID');
 
       foreach ($leases as $lease) {
         $list = idx($commands, $lease->getPHID(), array());
         $lease->attachUnconsumedCommands($list);
       }
     }
 
     return $leases;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->resourcePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'resourcePHID IN (%Ls)',
         $this->resourcePHIDs);
     }
 
     if ($this->ownerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'ownerPHID IN (%Ls)',
         $this->ownerPHIDs);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->datasourceQuery !== null) {
       $where[] = qsprintf(
         $conn,
         'id = %d',
         (int)$this->datasourceQuery);
     }
 
     if ($this->minModified !== null) {
       $where[] = qsprintf(
         $conn,
         'dateModified >= %d',
         $this->minModified);
     }
 
     if ($this->maxModified !== null) {
       $where[] = qsprintf(
         $conn,
         'dateModified <= %d',
         $this->maxModified);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockLogQuery.php b/src/applications/drydock/query/DrydockLogQuery.php
index 80f47f584f..d7e1f77ae6 100644
--- a/src/applications/drydock/query/DrydockLogQuery.php
+++ b/src/applications/drydock/query/DrydockLogQuery.php
@@ -1,173 +1,169 @@
 <?php
 
 final class DrydockLogQuery extends DrydockQuery {
 
   private $ids;
   private $blueprintPHIDs;
   private $resourcePHIDs;
   private $leasePHIDs;
   private $operationPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withBlueprintPHIDs(array $phids) {
     $this->blueprintPHIDs = $phids;
     return $this;
   }
 
   public function withResourcePHIDs(array $phids) {
     $this->resourcePHIDs = $phids;
     return $this;
   }
 
   public function withLeasePHIDs(array $phids) {
     $this->leasePHIDs = $phids;
     return $this;
   }
 
   public function withOperationPHIDs(array $phids) {
     $this->operationPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new DrydockLog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function didFilterPage(array $logs) {
     $blueprint_phids = array_filter(mpull($logs, 'getBlueprintPHID'));
     if ($blueprint_phids) {
       $blueprints = id(new DrydockBlueprintQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($blueprint_phids)
         ->execute();
       $blueprints = mpull($blueprints, null, 'getPHID');
     } else {
       $blueprints = array();
     }
 
     foreach ($logs as $key => $log) {
       $blueprint = null;
       $blueprint_phid = $log->getBlueprintPHID();
       if ($blueprint_phid) {
         $blueprint = idx($blueprints, $blueprint_phid);
       }
       $log->attachBlueprint($blueprint);
     }
 
     $resource_phids = array_filter(mpull($logs, 'getResourcePHID'));
     if ($resource_phids) {
       $resources = id(new DrydockResourceQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($resource_phids)
         ->execute();
       $resources = mpull($resources, null, 'getPHID');
     } else {
       $resources = array();
     }
 
     foreach ($logs as $key => $log) {
       $resource = null;
       $resource_phid = $log->getResourcePHID();
       if ($resource_phid) {
         $resource = idx($resources, $resource_phid);
       }
       $log->attachResource($resource);
     }
 
     $lease_phids = array_filter(mpull($logs, 'getLeasePHID'));
     if ($lease_phids) {
       $leases = id(new DrydockLeaseQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($lease_phids)
         ->execute();
       $leases = mpull($leases, null, 'getPHID');
     } else {
       $leases = array();
     }
 
     foreach ($logs as $key => $log) {
       $lease = null;
       $lease_phid = $log->getLeasePHID();
       if ($lease_phid) {
         $lease = idx($leases, $lease_phid);
       }
       $log->attachLease($lease);
     }
 
     $operation_phids = array_filter(mpull($logs, 'getOperationPHID'));
     if ($operation_phids) {
       $operations = id(new DrydockRepositoryOperationQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($operation_phids)
         ->execute();
       $operations = mpull($operations, null, 'getPHID');
     } else {
       $operations = array();
     }
 
     foreach ($logs as $key => $log) {
       $operation = null;
       $operation_phid = $log->getOperationPHID();
       if ($operation_phid) {
         $operation = idx($operations, $operation_phid);
       }
       $log->attachOperation($operation);
     }
 
     return $logs;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ls)',
         $this->ids);
     }
 
     if ($this->blueprintPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'blueprintPHID IN (%Ls)',
         $this->blueprintPHIDs);
     }
 
     if ($this->resourcePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'resourcePHID IN (%Ls)',
         $this->resourcePHIDs);
     }
 
     if ($this->leasePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'leasePHID IN (%Ls)',
         $this->leasePHIDs);
     }
 
     if ($this->operationPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'operationPHID IN (%Ls)',
         $this->operationPHIDs);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockRepositoryOperationQuery.php b/src/applications/drydock/query/DrydockRepositoryOperationQuery.php
index a5fbe0acc9..6ef5d1b295 100644
--- a/src/applications/drydock/query/DrydockRepositoryOperationQuery.php
+++ b/src/applications/drydock/query/DrydockRepositoryOperationQuery.php
@@ -1,189 +1,185 @@
 <?php
 
 final class DrydockRepositoryOperationQuery extends DrydockQuery {
 
   private $ids;
   private $phids;
   private $objectPHIDs;
   private $repositoryPHIDs;
   private $operationStates;
   private $operationTypes;
   private $isDismissed;
   private $authorPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $repository_phids) {
     $this->repositoryPHIDs = $repository_phids;
     return $this;
   }
 
   public function withOperationStates(array $states) {
     $this->operationStates = $states;
     return $this;
   }
 
   public function withOperationTypes(array $types) {
     $this->operationTypes = $types;
     return $this;
   }
 
   public function withIsDismissed($dismissed) {
     $this->isDismissed = $dismissed;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new DrydockRepositoryOperation();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $operations) {
     $implementations = DrydockRepositoryOperationType::getAllOperationTypes();
 
     $viewer = $this->getViewer();
 
     foreach ($operations as $key => $operation) {
       $impl = idx($implementations, $operation->getOperationType());
       if (!$impl) {
         $this->didRejectResult($operation);
         unset($operations[$key]);
         continue;
       }
       $impl = id(clone $impl)
         ->setViewer($viewer)
         ->setOperation($operation);
 
       $operation->attachImplementation($impl);
     }
 
     $repository_phids = mpull($operations, 'getRepositoryPHID');
     if ($repository_phids) {
       $repositories = id(new PhabricatorRepositoryQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($repository_phids)
         ->execute();
       $repositories = mpull($repositories, null, 'getPHID');
     } else {
       $repositories = array();
     }
 
     foreach ($operations as $key => $operation) {
       $repository = idx($repositories, $operation->getRepositoryPHID());
       if (!$repository) {
         $this->didRejectResult($operation);
         unset($operations[$key]);
         continue;
       }
       $operation->attachRepository($repository);
     }
 
     return $operations;
   }
 
   protected function didFilterPage(array $operations) {
     $object_phids = mpull($operations, 'getObjectPHID');
     if ($object_phids) {
       $objects = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($object_phids)
         ->execute();
       $objects = mpull($objects, null, 'getPHID');
     } else {
       $objects = array();
     }
 
     foreach ($operations as $key => $operation) {
       $object = idx($objects, $operation->getObjectPHID());
       $operation->attachObject($object);
     }
 
     return $operations;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->operationStates !== null) {
       $where[] = qsprintf(
         $conn,
         'operationState IN (%Ls)',
         $this->operationStates);
     }
 
     if ($this->operationTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'operationType IN (%Ls)',
         $this->operationTypes);
     }
 
     if ($this->isDismissed !== null) {
       $where[] = qsprintf(
         $conn,
         'isDismissed = %d',
         (int)$this->isDismissed);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/drydock/query/DrydockResourceQuery.php b/src/applications/drydock/query/DrydockResourceQuery.php
index bcbff03663..395e758a23 100644
--- a/src/applications/drydock/query/DrydockResourceQuery.php
+++ b/src/applications/drydock/query/DrydockResourceQuery.php
@@ -1,149 +1,145 @@
 <?php
 
 final class DrydockResourceQuery extends DrydockQuery {
 
   private $ids;
   private $phids;
   private $statuses;
   private $types;
   private $blueprintPHIDs;
   private $datasourceQuery;
   private $needUnconsumedCommands;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withTypes(array $types) {
     $this->types = $types;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withBlueprintPHIDs(array $blueprint_phids) {
     $this->blueprintPHIDs = $blueprint_phids;
     return $this;
   }
 
   public function withDatasourceQuery($query) {
     $this->datasourceQuery = $query;
     return $this;
   }
 
   public function needUnconsumedCommands($need) {
     $this->needUnconsumedCommands = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new DrydockResource();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $resources) {
     $blueprint_phids = mpull($resources, 'getBlueprintPHID');
 
     $blueprints = id(new DrydockBlueprintQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs($blueprint_phids)
       ->execute();
     $blueprints = mpull($blueprints, null, 'getPHID');
 
     foreach ($resources as $key => $resource) {
       $blueprint = idx($blueprints, $resource->getBlueprintPHID());
       if (!$blueprint) {
         $this->didRejectResult($resource);
         unset($resources[$key]);
         continue;
       }
       $resource->attachBlueprint($blueprint);
     }
 
     return $resources;
   }
 
   protected function didFilterPage(array $resources) {
     if ($this->needUnconsumedCommands) {
       $commands = id(new DrydockCommandQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withTargetPHIDs(mpull($resources, 'getPHID'))
         ->withConsumed(false)
         ->execute();
       $commands = mgroup($commands, 'getTargetPHID');
 
       foreach ($resources as $resource) {
         $list = idx($commands, $resource->getPHID(), array());
         $resource->attachUnconsumedCommands($list);
       }
     }
 
     return $resources;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'resource.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'resource.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->types !== null) {
       $where[] = qsprintf(
         $conn,
         'resource.type IN (%Ls)',
         $this->types);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'resource.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->blueprintPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'resource.blueprintPHID IN (%Ls)',
         $this->blueprintPHIDs);
     }
 
     if ($this->datasourceQuery !== null) {
       $where[] = qsprintf(
         $conn,
         'resource.name LIKE %>',
         $this->datasourceQuery);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'resource';
   }
 
 }
diff --git a/src/applications/files/query/PhabricatorFileAttachmentQuery.php b/src/applications/files/query/PhabricatorFileAttachmentQuery.php
index 6367fc20f8..5fb37dc32e 100644
--- a/src/applications/files/query/PhabricatorFileAttachmentQuery.php
+++ b/src/applications/files/query/PhabricatorFileAttachmentQuery.php
@@ -1,135 +1,131 @@
 <?php
 
 final class PhabricatorFileAttachmentQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $objectPHIDs;
   private $filePHIDs;
   private $needFiles;
   private $visibleFiles;
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withFilePHIDs(array $file_phids) {
     $this->filePHIDs = $file_phids;
     return $this;
   }
 
   public function withVisibleFiles($visible_files) {
     $this->visibleFiles = $visible_files;
     return $this;
   }
 
   public function needFiles($need) {
     $this->needFiles = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorFileAttachment();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'attachments.objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->filePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'attachments.filePHID IN (%Ls)',
         $this->filePHIDs);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $attachments) {
     $viewer = $this->getViewer();
     $object_phids = array();
 
     foreach ($attachments as $attachment) {
       $object_phid = $attachment->getObjectPHID();
       $object_phids[$object_phid] = $object_phid;
     }
 
     if ($object_phids) {
       $objects = id(new PhabricatorObjectQuery())
         ->setViewer($viewer)
         ->setParentQuery($this)
         ->withPHIDs($object_phids)
         ->execute();
       $objects = mpull($objects, null, 'getPHID');
     } else {
       $objects = array();
     }
 
     foreach ($attachments as $key => $attachment) {
       $object_phid = $attachment->getObjectPHID();
       $object = idx($objects, $object_phid);
 
       if (!$object) {
         $this->didRejectResult($attachment);
         unset($attachments[$key]);
         continue;
       }
 
       $attachment->attachObject($object);
     }
 
     if ($this->needFiles) {
       $file_phids = array();
       foreach ($attachments as $attachment) {
         $file_phid = $attachment->getFilePHID();
         $file_phids[$file_phid] = $file_phid;
       }
 
       if ($file_phids) {
         $files = id(new PhabricatorFileQuery())
           ->setViewer($viewer)
           ->setParentQuery($this)
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
       } else {
         $files = array();
       }
 
       foreach ($attachments as $key => $attachment) {
         $file_phid = $attachment->getFilePHID();
         $file = idx($files, $file_phid);
 
         if ($this->visibleFiles && !$file) {
           $this->didRejectResult($attachment);
           unset($attachments[$key]);
           continue;
         }
 
         $attachment->attachFile($file);
       }
     }
 
     return $attachments;
   }
 
   protected function getPrimaryTableAlias() {
     return 'attachments';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorFilesApplication';
   }
 
 }
diff --git a/src/applications/fund/query/FundInitiativeQuery.php b/src/applications/fund/query/FundInitiativeQuery.php
index bbb4ef2746..4b18597873 100644
--- a/src/applications/fund/query/FundInitiativeQuery.php
+++ b/src/applications/fund/query/FundInitiativeQuery.php
@@ -1,81 +1,77 @@
 <?php
 
 final class FundInitiativeQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $ownerPHIDs;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withOwnerPHIDs(array $phids) {
     $this->ownerPHIDs = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new FundInitiative();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'i.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'i.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->ownerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'i.ownerPHID IN (%Ls)',
         $this->ownerPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'i.status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorFundApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'i';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
index de35c05aa6..59d4c07d2f 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
@@ -1,117 +1,113 @@
 <?php
 
 final class HarbormasterBuildArtifactQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $buildTargetPHIDs;
   private $artifactTypes;
   private $artifactIndexes;
   private $keyBuildPHID;
   private $keyBuildGeneration;
   private $isReleased;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withBuildTargetPHIDs(array $build_target_phids) {
     $this->buildTargetPHIDs = $build_target_phids;
     return $this;
   }
 
   public function withArtifactTypes(array $artifact_types) {
     $this->artifactTypes = $artifact_types;
     return $this;
   }
 
   public function withArtifactIndexes(array $artifact_indexes) {
     $this->artifactIndexes = $artifact_indexes;
     return $this;
   }
 
   public function withIsReleased($released) {
     $this->isReleased = $released;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildArtifact();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $build_targets = array();
 
     $build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
     if ($build_target_phids) {
       $build_targets = id(new HarbormasterBuildTargetQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($build_target_phids)
         ->setParentQuery($this)
         ->execute();
       $build_targets = mpull($build_targets, null, 'getPHID');
     }
 
     foreach ($page as $key => $build_log) {
       $build_target_phid = $build_log->getBuildTargetPHID();
       if (empty($build_targets[$build_target_phid])) {
         unset($page[$key]);
         continue;
       }
       $build_log->attachBuildTarget($build_targets[$build_target_phid]);
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->buildTargetPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'buildTargetPHID IN (%Ls)',
         $this->buildTargetPHIDs);
     }
 
     if ($this->artifactTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'artifactType in (%Ls)',
         $this->artifactTypes);
     }
 
     if ($this->artifactIndexes !== null) {
       $where[] = qsprintf(
         $conn,
         'artifactIndex IN (%Ls)',
         $this->artifactIndexes);
     }
 
     if ($this->isReleased !== null) {
       $where[] = qsprintf(
         $conn,
         'isReleased = %d',
         (int)$this->isReleased);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
index ad27d09582..f62919f989 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
@@ -1,90 +1,86 @@
 <?php
 
 final class HarbormasterBuildLogQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $buildPHIDs;
   private $buildTargetPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBuildTargetPHIDs(array $build_target_phids) {
     $this->buildTargetPHIDs = $build_target_phids;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildLog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $build_targets = array();
 
     $build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
     if ($build_target_phids) {
       $build_targets = id(new HarbormasterBuildTargetQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($build_target_phids)
         ->setParentQuery($this)
         ->execute();
       $build_targets = mpull($build_targets, null, 'getPHID');
     }
 
     foreach ($page as $key => $build_log) {
       $build_target_phid = $build_log->getBuildTargetPHID();
       if (empty($build_targets[$build_target_phid])) {
         unset($page[$key]);
         continue;
       }
       $build_log->attachBuildTarget($build_targets[$build_target_phid]);
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->buildTargetPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'buildTargetPHID IN (%Ls)',
         $this->buildTargetPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php b/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
index 134c68ce04..393ca0a493 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
@@ -1,92 +1,88 @@
 <?php
 
 final class HarbormasterBuildMessageQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $receiverPHIDs;
   private $consumed;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withReceiverPHIDs(array $phids) {
     $this->receiverPHIDs = $phids;
     return $this;
   }
 
   public function withConsumed($consumed) {
     $this->consumed = $consumed;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildMessage();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $receiver_phids = array_filter(mpull($page, 'getReceiverPHID'));
     if ($receiver_phids) {
       $receivers = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($receiver_phids)
         ->setParentQuery($this)
         ->execute();
       $receivers = mpull($receivers, null, 'getPHID');
     } else {
       $receivers = array();
     }
 
     foreach ($page as $key => $message) {
       $receiver_phid = $message->getReceiverPHID();
 
       if (empty($receivers[$receiver_phid])) {
         unset($page[$key]);
         $this->didRejectResult($message);
         continue;
       }
 
       $message->attachReceiver($receivers[$receiver_phid]);
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->receiverPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'receiverPHID IN (%Ls)',
         $this->receiverPHIDs);
     }
 
     if ($this->consumed !== null) {
       $where[] = qsprintf(
         $conn,
         'isConsumed = %d',
         (int)$this->consumed);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php b/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
index 262aa12d7b..c8514b2186 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
@@ -1,152 +1,148 @@
 <?php
 
 final class HarbormasterBuildPlanQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $statuses;
   private $datasourceQuery;
   private $planAutoKeys;
   private $needBuildSteps;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withDatasourceQuery($query) {
     $this->datasourceQuery = $query;
     return $this;
   }
 
   public function withPlanAutoKeys(array $keys) {
     $this->planAutoKeys = $keys;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new HarbormasterBuildPlanNameNgrams(),
       $ngrams);
   }
 
   public function needBuildSteps($need) {
     $this->needBuildSteps = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildPlan();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function didFilterPage(array $page) {
     if ($this->needBuildSteps) {
       $plan_phids = mpull($page, 'getPHID');
 
       $steps = id(new HarbormasterBuildStepQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withBuildPlanPHIDs($plan_phids)
         ->execute();
       $steps = mgroup($steps, 'getBuildPlanPHID');
 
       foreach ($page as $plan) {
         $plan_steps = idx($steps, $plan->getPHID(), array());
         $plan->attachBuildSteps($plan_steps);
       }
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'plan.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'plan.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'plan.planStatus IN (%Ls)',
         $this->statuses);
     }
 
     if (!phutil_nonempty_string($this->datasourceQuery)) {
       $where[] = qsprintf(
         $conn,
         'plan.name LIKE %>',
         $this->datasourceQuery);
     }
 
     if ($this->planAutoKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'plan.planAutoKey IN (%Ls)',
         $this->planAutoKeys);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'plan';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'column' => 'name',
         'type' => 'string',
         'reverse' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
     );
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name', 'id'),
         'name' => pht('Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildQuery.php b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
index 5ff5fe2eb3..a397f5968a 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
@@ -1,233 +1,229 @@
 <?php
 
 final class HarbormasterBuildQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $buildStatuses;
   private $buildablePHIDs;
   private $buildPlanPHIDs;
   private $initiatorPHIDs;
   private $needBuildTargets;
   private $autobuilds;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBuildStatuses(array $build_statuses) {
     $this->buildStatuses = $build_statuses;
     return $this;
   }
 
   public function withBuildablePHIDs(array $buildable_phids) {
     $this->buildablePHIDs = $buildable_phids;
     return $this;
   }
 
   public function withBuildPlanPHIDs(array $build_plan_phids) {
     $this->buildPlanPHIDs = $build_plan_phids;
     return $this;
   }
 
   public function withInitiatorPHIDs(array $initiator_phids) {
     $this->initiatorPHIDs = $initiator_phids;
     return $this;
   }
 
   public function withAutobuilds($with_autobuilds) {
     $this->autobuilds = $with_autobuilds;
     return $this;
   }
 
   public function needBuildTargets($need_targets) {
     $this->needBuildTargets = $need_targets;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuild();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $buildables = array();
 
     $buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
     if ($buildable_phids) {
       $buildables = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($buildable_phids)
         ->setParentQuery($this)
         ->execute();
       $buildables = mpull($buildables, null, 'getPHID');
     }
 
     foreach ($page as $key => $build) {
       $buildable_phid = $build->getBuildablePHID();
       if (empty($buildables[$buildable_phid])) {
         unset($page[$key]);
         continue;
       }
       $build->attachBuildable($buildables[$buildable_phid]);
     }
 
     return $page;
   }
 
   protected function didFilterPage(array $page) {
     $plans = array();
 
     $plan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
     if ($plan_phids) {
       $plans = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($plan_phids)
         ->setParentQuery($this)
         ->execute();
       $plans = mpull($plans, null, 'getPHID');
     }
 
     foreach ($page as $key => $build) {
       $plan_phid = $build->getBuildPlanPHID();
       $build->attachBuildPlan(idx($plans, $plan_phid));
     }
 
     $build_phids = mpull($page, 'getPHID');
     $messages = id(new HarbormasterBuildMessage())->loadAllWhere(
       'receiverPHID IN (%Ls) AND isConsumed = 0 ORDER BY id ASC',
       $build_phids);
     $messages = mgroup($messages, 'getReceiverPHID');
     foreach ($page as $build) {
       $unprocessed_messages = idx($messages, $build->getPHID(), array());
       $build->attachUnprocessedMessages($unprocessed_messages);
     }
 
     if ($this->needBuildTargets) {
       $targets = id(new HarbormasterBuildTargetQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withBuildPHIDs($build_phids)
         ->execute();
 
       // TODO: Some day, when targets have dependencies, we should toposort
       // these. For now, just put them into chronological order.
       $targets = array_reverse($targets);
 
       $targets = mgroup($targets, 'getBuildPHID');
       foreach ($page as $build) {
         $build_targets = idx($targets, $build->getPHID(), array());
 
         foreach ($build_targets as $phid => $target) {
           if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
             unset($build_targets[$phid]);
           }
         }
 
         $build->attachBuildTargets($build_targets);
       }
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'b.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'b.phid in (%Ls)',
         $this->phids);
     }
 
     if ($this->buildStatuses !== null) {
       $where[] = qsprintf(
         $conn,
         'b.buildStatus in (%Ls)',
         $this->buildStatuses);
     }
 
     if ($this->buildablePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'b.buildablePHID IN (%Ls)',
         $this->buildablePHIDs);
     }
 
     if ($this->buildPlanPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'b.buildPlanPHID IN (%Ls)',
         $this->buildPlanPHIDs);
     }
 
     if ($this->initiatorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'b.initiatorPHID IN (%Ls)',
         $this->initiatorPHIDs);
     }
 
     if ($this->autobuilds !== null) {
       if ($this->autobuilds) {
         $where[] = qsprintf(
           $conn,
           'p.planAutoKey IS NOT NULL');
       } else {
         $where[] = qsprintf(
           $conn,
           'p.planAutoKey IS NULL');
       }
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinPlanTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T p ON b.buildPlanPHID = p.phid',
         id(new HarbormasterBuildPlan())->getTableName());
     }
 
     return $joins;
   }
 
   private function shouldJoinPlanTable() {
     if ($this->autobuilds !== null) {
       return true;
     }
 
     return false;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'b';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php b/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
index 992dd4fad1..93010071e2 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
@@ -1,89 +1,85 @@
 <?php
 
 final class HarbormasterBuildStepQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $buildPlanPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBuildPlanPHIDs(array $phids) {
     $this->buildPlanPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildStep();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid in (%Ls)',
         $this->phids);
     }
 
     if ($this->buildPlanPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'buildPlanPHID in (%Ls)',
         $this->buildPlanPHIDs);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $page) {
     $plans = array();
 
     $buildplan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
     if ($buildplan_phids) {
       $plans = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($buildplan_phids)
         ->setParentQuery($this)
         ->execute();
       $plans = mpull($plans, null, 'getPHID');
     }
 
     foreach ($page as $key => $build) {
       $buildable_phid = $build->getBuildPlanPHID();
       if (empty($plans[$buildable_phid])) {
         unset($page[$key]);
         continue;
       }
       $build->attachBuildPlan($plans[$buildable_phid]);
     }
 
     return $page;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
index 54b9c4ee16..a93aff60bd 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
@@ -1,213 +1,209 @@
 <?php
 
 final class HarbormasterBuildTargetQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $buildPHIDs;
   private $buildGenerations;
   private $dateCreatedMin;
   private $dateCreatedMax;
   private $dateStartedMin;
   private $dateStartedMax;
   private $dateCompletedMin;
   private $dateCompletedMax;
   private $statuses;
 
   private $needBuildSteps;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBuildPHIDs(array $build_phids) {
     $this->buildPHIDs = $build_phids;
     return $this;
   }
 
   public function withBuildGenerations(array $build_generations) {
     $this->buildGenerations = $build_generations;
     return $this;
   }
 
   public function withDateCreatedBetween($min, $max) {
     $this->dateCreatedMin = $min;
     $this->dateCreatedMax = $max;
     return $this;
   }
 
   public function withDateStartedBetween($min, $max) {
     $this->dateStartedMin = $min;
     $this->dateStartedMax = $max;
     return $this;
   }
 
   public function withDateCompletedBetween($min, $max) {
     $this->dateCompletedMin = $min;
     $this->dateCompletedMax = $max;
     return $this;
   }
 
   public function withTargetStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function needBuildSteps($need_build_steps) {
     $this->needBuildSteps = $need_build_steps;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildTarget();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid in (%Ls)',
         $this->phids);
     }
 
     if ($this->buildPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'buildPHID in (%Ls)',
         $this->buildPHIDs);
     }
 
     if ($this->buildGenerations !== null) {
       $where[] = qsprintf(
         $conn,
         'buildGeneration in (%Ld)',
         $this->buildGenerations);
     }
 
     if ($this->dateCreatedMin !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCreated >= %d',
         $this->dateCreatedMin);
     }
 
     if ($this->dateCreatedMax !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCreated <= %d',
         $this->dateCreatedMax);
     }
 
     if ($this->dateStartedMin !== null) {
       $where[] = qsprintf(
         $conn,
         'dateStarted >= %d',
         $this->dateStartedMin);
     }
 
     if ($this->dateStartedMax !== null) {
       $where[] = qsprintf(
         $conn,
         'dateStarted <= %d',
         $this->dateStartedMax);
     }
 
     if ($this->dateCompletedMin !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCompleted >= %d',
         $this->dateCompletedMin);
     }
 
     if ($this->dateCompletedMax !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCompleted <= %d',
         $this->dateCompletedMax);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'targetStatus IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   protected function didFilterPage(array $page) {
     if ($this->needBuildSteps) {
       $step_phids = array();
 
       foreach ($page as $target) {
         $step_phids[] = $target->getBuildStepPHID();
       }
 
       $steps = id(new HarbormasterBuildStepQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($step_phids)
         ->execute();
 
       $steps = mpull($steps, null, 'getPHID');
 
       foreach ($page as $target) {
         $target->attachBuildStep(
           idx($steps, $target->getBuildStepPHID()));
       }
     }
 
     return $page;
   }
 
   protected function willFilterPage(array $page) {
     $builds = array();
 
     $build_phids = array_filter(mpull($page, 'getBuildPHID'));
     if ($build_phids) {
       $builds = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($build_phids)
         ->setParentQuery($this)
         ->execute();
       $builds = mpull($builds, null, 'getPHID');
     }
 
     foreach ($page as $key => $build_target) {
       $build_phid = $build_target->getBuildPHID();
       if (empty($builds[$build_phid])) {
         unset($page[$key]);
         continue;
       }
       $build_target->attachBuild($builds[$build_phid]);
     }
 
     return $page;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php b/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
index f73016a29f..edfe102ca2 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
@@ -1,95 +1,91 @@
 <?php
 
 final class HarbormasterBuildUnitMessageQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $targetPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBuildTargetPHIDs(array $target_phids) {
     $this->targetPHIDs = $target_phids;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildUnitMessage();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid in (%Ls)',
         $this->phids);
     }
 
     if ($this->targetPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'buildTargetPHID in (%Ls)',
         $this->targetPHIDs);
     }
 
     return $where;
   }
 
   protected function didFilterPage(array $messages) {
     $indexes = array();
     foreach ($messages as $message) {
       $index = $message->getNameIndex();
       if (strlen($index)) {
         $indexes[$index] = $index;
       }
     }
 
     if ($indexes) {
       $map = HarbormasterString::newIndexMap($indexes);
 
       foreach ($messages as $message) {
         $index = $message->getNameIndex();
 
         if (!strlen($index)) {
           continue;
         }
 
         $name = idx($map, $index);
         if ($name === null) {
           $name = pht('Unknown Unit Message ("%s")', $index);
         }
 
         $message->setName($name);
       }
     }
 
     return $messages;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
index b1a643cac7..cf907a2dc3 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
@@ -1,184 +1,180 @@
 <?php
 
 final class HarbormasterBuildableQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $buildablePHIDs;
   private $containerPHIDs;
   private $statuses;
   private $manualBuildables;
 
   private $needContainerObjects;
   private $needBuilds;
   private $needTargets;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBuildablePHIDs(array $buildable_phids) {
     $this->buildablePHIDs = $buildable_phids;
     return $this;
   }
 
   public function withContainerPHIDs(array $container_phids) {
     $this->containerPHIDs = $container_phids;
     return $this;
   }
 
   public function withManualBuildables($manual) {
     $this->manualBuildables = $manual;
     return $this;
   }
 
   public function needContainerObjects($need) {
     $this->needContainerObjects = $need;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function needBuilds($need) {
     $this->needBuilds = $need;
     return $this;
   }
 
   public function needTargets($need) {
     $this->needTargets = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new HarbormasterBuildable();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $buildables = array();
 
     $buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
     if ($buildable_phids) {
       $buildables = id(new PhabricatorObjectQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($buildable_phids)
         ->setParentQuery($this)
         ->execute();
       $buildables = mpull($buildables, null, 'getPHID');
     }
 
     foreach ($page as $key => $buildable) {
       $buildable_phid = $buildable->getBuildablePHID();
       if (empty($buildables[$buildable_phid])) {
         unset($page[$key]);
         continue;
       }
       $buildable->attachBuildableObject($buildables[$buildable_phid]);
     }
 
     return $page;
   }
 
   protected function didFilterPage(array $page) {
     if ($this->needContainerObjects) {
       $container_phids = array_filter(mpull($page, 'getContainerPHID'));
 
       if ($container_phids) {
         $containers = id(new PhabricatorObjectQuery())
           ->setViewer($this->getViewer())
           ->withPHIDs($container_phids)
           ->setParentQuery($this)
           ->execute();
         $containers = mpull($containers, null, 'getPHID');
       } else {
         $containers = array();
       }
 
       foreach ($page as $key => $buildable) {
         $container_phid = $buildable->getContainerPHID();
         $buildable->attachContainerObject(idx($containers, $container_phid));
       }
     }
 
     if ($this->needBuilds || $this->needTargets) {
       $builds = id(new HarbormasterBuildQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withBuildablePHIDs(mpull($page, 'getPHID'))
         ->needBuildTargets($this->needTargets)
         ->execute();
       $builds = mgroup($builds, 'getBuildablePHID');
       foreach ($page as $key => $buildable) {
         $buildable->attachBuilds(idx($builds, $buildable->getPHID(), array()));
       }
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->buildablePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'buildablePHID IN (%Ls)',
         $this->buildablePHIDs);
     }
 
     if ($this->containerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'containerPHID in (%Ls)',
         $this->containerPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'buildableStatus in (%Ls)',
         $this->statuses);
     }
 
     if ($this->manualBuildables !== null) {
       $where[] = qsprintf(
         $conn,
         'isManualBuildable = %d',
         (int)$this->manualBuildables);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHarbormasterApplication';
   }
 
 }
diff --git a/src/applications/herald/query/HeraldRuleQuery.php b/src/applications/herald/query/HeraldRuleQuery.php
index e346a998d4..e104c44122 100644
--- a/src/applications/herald/query/HeraldRuleQuery.php
+++ b/src/applications/herald/query/HeraldRuleQuery.php
@@ -1,341 +1,337 @@
 <?php
 
 final class HeraldRuleQuery extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $ruleTypes;
   private $contentTypes;
   private $disabled;
   private $active;
   private $datasourceQuery;
   private $triggerObjectPHIDs;
   private $affectedObjectPHIDs;
 
   private $needConditionsAndActions;
   private $needAppliedToPHIDs;
   private $needValidateAuthors;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
   public function withRuleTypes(array $types) {
     $this->ruleTypes = $types;
     return $this;
   }
 
   public function withContentTypes(array $types) {
     $this->contentTypes = $types;
     return $this;
   }
 
   public function withDisabled($disabled) {
     $this->disabled = $disabled;
     return $this;
   }
 
   public function withActive($active) {
     $this->active = $active;
     return $this;
   }
 
   public function withDatasourceQuery($query) {
     $this->datasourceQuery = $query;
     return $this;
   }
 
   public function withTriggerObjectPHIDs(array $phids) {
     $this->triggerObjectPHIDs = $phids;
     return $this;
   }
 
   public function withAffectedObjectPHIDs(array $phids) {
     $this->affectedObjectPHIDs = $phids;
     return $this;
   }
 
   public function needConditionsAndActions($need) {
     $this->needConditionsAndActions = $need;
     return $this;
   }
 
   public function needAppliedToPHIDs(array $phids) {
     $this->needAppliedToPHIDs = $phids;
     return $this;
   }
 
   public function needValidateAuthors($need) {
     $this->needValidateAuthors = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new HeraldRule();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $rules) {
     $rule_ids = mpull($rules, 'getID');
 
     // Filter out any rules that have invalid adapters, or have adapters the
     // viewer isn't permitted to see or use (for example, Differential rules
     // if the user can't use Differential or Differential is not installed).
     $types = HeraldAdapter::getEnabledAdapterMap($this->getViewer());
     foreach ($rules as $key => $rule) {
       if (empty($types[$rule->getContentType()])) {
         $this->didRejectResult($rule);
         unset($rules[$key]);
       }
     }
 
     if ($this->needValidateAuthors || ($this->active !== null)) {
       $this->validateRuleAuthors($rules);
     }
 
     if ($this->active !== null) {
       $need_active = (bool)$this->active;
       foreach ($rules as $key => $rule) {
         if ($rule->getIsDisabled()) {
           $is_active = false;
         } else if (!$rule->hasValidAuthor()) {
           $is_active = false;
         } else {
           $is_active = true;
         }
 
         if ($is_active != $need_active) {
           unset($rules[$key]);
         }
       }
     }
 
     if (!$rules) {
       return array();
     }
 
     if ($this->needConditionsAndActions) {
       $conditions = id(new HeraldCondition())->loadAllWhere(
         'ruleID IN (%Ld)',
         $rule_ids);
       $conditions = mgroup($conditions, 'getRuleID');
 
       $actions = id(new HeraldActionRecord())->loadAllWhere(
         'ruleID IN (%Ld)',
         $rule_ids);
       $actions = mgroup($actions, 'getRuleID');
 
       foreach ($rules as $rule) {
         $rule->attachActions(idx($actions, $rule->getID(), array()));
         $rule->attachConditions(idx($conditions, $rule->getID(), array()));
       }
     }
 
     if ($this->needAppliedToPHIDs) {
       $conn_r = id(new HeraldRule())->establishConnection('r');
       $applied = queryfx_all(
         $conn_r,
         'SELECT * FROM %T WHERE ruleID IN (%Ld) AND phid IN (%Ls)',
         HeraldRule::TABLE_RULE_APPLIED,
         $rule_ids,
         $this->needAppliedToPHIDs);
 
       $map = array();
       foreach ($applied as $row) {
         $map[$row['ruleID']][$row['phid']] = true;
       }
 
       foreach ($rules as $rule) {
         foreach ($this->needAppliedToPHIDs as $phid) {
           $rule->setRuleApplied(
             $phid,
             isset($map[$rule->getID()][$phid]));
         }
       }
     }
 
     $object_phids = array();
     foreach ($rules as $rule) {
       if ($rule->isObjectRule()) {
         $object_phids[] = $rule->getTriggerObjectPHID();
       }
     }
 
     if ($object_phids) {
       $objects = id(new PhabricatorObjectQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($object_phids)
         ->execute();
       $objects = mpull($objects, null, 'getPHID');
     } else {
       $objects = array();
     }
 
     foreach ($rules as $key => $rule) {
       if ($rule->isObjectRule()) {
         $object = idx($objects, $rule->getTriggerObjectPHID());
         if (!$object) {
           unset($rules[$key]);
           continue;
         }
         $rule->attachTriggerObject($object);
       }
     }
 
     return $rules;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->ruleTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.ruleType IN (%Ls)',
         $this->ruleTypes);
     }
 
     if ($this->contentTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.contentType IN (%Ls)',
         $this->contentTypes);
     }
 
     if ($this->disabled !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.isDisabled = %d',
         (int)$this->disabled);
     }
 
     if ($this->active !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.isDisabled = %d',
         (int)(!$this->active));
     }
 
     if ($this->datasourceQuery !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.name LIKE %>',
         $this->datasourceQuery);
     }
 
     if ($this->triggerObjectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'rule.triggerObjectPHID IN (%Ls)',
         $this->triggerObjectPHIDs);
     }
 
     if ($this->affectedObjectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'edge_affects.dst IN (%Ls)',
         $this->affectedObjectPHIDs);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->affectedObjectPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T edge_affects ON rule.phid = edge_affects.src
           AND edge_affects.type = %d',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         HeraldRuleActionAffectsObjectEdgeType::EDGECONST);
     }
 
     return $joins;
   }
 
   private function validateRuleAuthors(array $rules) {
     // "Global" and "Object" rules always have valid authors.
     foreach ($rules as $key => $rule) {
       if ($rule->isGlobalRule() || $rule->isObjectRule()) {
         $rule->attachValidAuthor(true);
         unset($rules[$key]);
         continue;
       }
     }
 
     if (!$rules) {
       return;
     }
 
     // For personal rules, the author needs to exist and not be disabled.
     $user_phids = mpull($rules, 'getAuthorPHID');
     $users = id(new PhabricatorPeopleQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs($user_phids)
       ->execute();
     $users = mpull($users, null, 'getPHID');
 
     foreach ($rules as $key => $rule) {
       $author_phid = $rule->getAuthorPHID();
       if (empty($users[$author_phid])) {
         $rule->attachValidAuthor(false);
         continue;
       }
       if (!$users[$author_phid]->isUserActivated()) {
         $rule->attachValidAuthor(false);
         continue;
       }
 
       $rule->attachValidAuthor(true);
       $rule->attachAuthor($users[$author_phid]);
     }
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHeraldApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'rule';
   }
 
 }
diff --git a/src/applications/herald/query/HeraldWebhookQuery.php b/src/applications/herald/query/HeraldWebhookQuery.php
index ca46880613..77307a71e6 100644
--- a/src/applications/herald/query/HeraldWebhookQuery.php
+++ b/src/applications/herald/query/HeraldWebhookQuery.php
@@ -1,64 +1,60 @@
 <?php
 
 final class HeraldWebhookQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new HeraldWebhook();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHeraldApplication';
   }
 
 }
diff --git a/src/applications/herald/query/HeraldWebhookRequestQuery.php b/src/applications/herald/query/HeraldWebhookRequestQuery.php
index 4c71d48e05..f0a61a2dc5 100644
--- a/src/applications/herald/query/HeraldWebhookRequestQuery.php
+++ b/src/applications/herald/query/HeraldWebhookRequestQuery.php
@@ -1,126 +1,122 @@
 <?php
 
 final class HeraldWebhookRequestQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $webhookPHIDs;
   private $lastRequestEpochMin;
   private $lastRequestEpochMax;
   private $lastRequestResults;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withWebhookPHIDs(array $phids) {
     $this->webhookPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new HeraldWebhookRequest();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   public function withLastRequestEpochBetween($epoch_min, $epoch_max) {
     $this->lastRequestEpochMin = $epoch_min;
     $this->lastRequestEpochMax = $epoch_max;
     return $this;
   }
 
   public function withLastRequestResults(array $results) {
     $this->lastRequestResults = $results;
     return $this;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->webhookPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'webhookPHID IN (%Ls)',
         $this->webhookPHIDs);
     }
 
     if ($this->lastRequestEpochMin !== null) {
       $where[] = qsprintf(
         $conn,
         'lastRequestEpoch >= %d',
         $this->lastRequestEpochMin);
     }
 
     if ($this->lastRequestEpochMax !== null) {
       $where[] = qsprintf(
         $conn,
         'lastRequestEpoch <= %d',
         $this->lastRequestEpochMax);
     }
 
     if ($this->lastRequestResults !== null) {
       $where[] = qsprintf(
         $conn,
         'lastRequestResult IN (%Ls)',
         $this->lastRequestResults);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $requests) {
     $hook_phids = mpull($requests, 'getWebhookPHID');
 
     $hooks = id(new HeraldWebhookQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($hook_phids)
       ->execute();
     $hooks = mpull($hooks, null, 'getPHID');
 
     foreach ($requests as $key => $request) {
       $hook_phid = $request->getWebhookPHID();
       $hook = idx($hooks, $hook_phid);
 
       if (!$hook) {
         unset($requests[$key]);
         $this->didRejectResult($request);
         continue;
       }
 
       $request->attachWebhook($hook);
     }
 
     return $requests;
   }
 
 
   public function getQueryApplicationClass() {
     return 'PhabricatorHeraldApplication';
   }
 
 }
diff --git a/src/applications/legalpad/query/LegalpadDocumentQuery.php b/src/applications/legalpad/query/LegalpadDocumentQuery.php
index 3d79e9f3a1..854a187fab 100644
--- a/src/applications/legalpad/query/LegalpadDocumentQuery.php
+++ b/src/applications/legalpad/query/LegalpadDocumentQuery.php
@@ -1,273 +1,269 @@
 <?php
 
 final class LegalpadDocumentQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $creatorPHIDs;
   private $contributorPHIDs;
   private $signerPHIDs;
   private $dateCreatedAfter;
   private $dateCreatedBefore;
   private $signatureRequired;
 
   private $needDocumentBodies;
   private $needContributors;
   private $needSignatures;
   private $needViewerSignatures;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withCreatorPHIDs(array $phids) {
     $this->creatorPHIDs = $phids;
     return $this;
   }
 
   public function withContributorPHIDs(array $phids) {
     $this->contributorPHIDs = $phids;
     return $this;
   }
 
   public function withSignerPHIDs(array $phids) {
     $this->signerPHIDs = $phids;
     return $this;
   }
 
   public function withSignatureRequired($bool) {
     $this->signatureRequired = $bool;
     return $this;
   }
 
   public function needDocumentBodies($need_bodies) {
     $this->needDocumentBodies = $need_bodies;
     return $this;
   }
 
   public function needContributors($need_contributors) {
     $this->needContributors = $need_contributors;
     return $this;
   }
 
   public function needSignatures($need_signatures) {
     $this->needSignatures = $need_signatures;
     return $this;
   }
 
   public function withDateCreatedBefore($date_created_before) {
     $this->dateCreatedBefore = $date_created_before;
     return $this;
   }
 
   public function withDateCreatedAfter($date_created_after) {
     $this->dateCreatedAfter = $date_created_after;
     return $this;
   }
 
   public function needViewerSignatures($need) {
     $this->needViewerSignatures = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new LegalpadDocument();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $documents) {
     if ($this->needDocumentBodies) {
       $documents = $this->loadDocumentBodies($documents);
     }
 
     if ($this->needContributors) {
       $documents = $this->loadContributors($documents);
     }
 
     if ($this->needSignatures) {
       $documents = $this->loadSignatures($documents);
     }
 
     if ($this->needViewerSignatures) {
       if ($documents) {
         if ($this->getViewer()->getPHID()) {
           $signatures = id(new LegalpadDocumentSignatureQuery())
             ->setViewer($this->getViewer())
             ->withSignerPHIDs(array($this->getViewer()->getPHID()))
             ->withDocumentPHIDs(mpull($documents, 'getPHID'))
             ->execute();
           $signatures = mpull($signatures, null, 'getDocumentPHID');
         } else {
           $signatures = array();
         }
 
         foreach ($documents as $document) {
           $signature = idx($signatures, $document->getPHID());
           $document->attachUserSignature(
             $this->getViewer()->getPHID(),
             $signature);
         }
       }
     }
 
     return $documents;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->contributorPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN edge contributor ON contributor.src = d.phid
           AND contributor.type = %d',
         PhabricatorObjectHasContributorEdgeType::EDGECONST);
     }
 
     if ($this->signerPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T signer ON signer.documentPHID = d.phid
           AND signer.signerPHID IN (%Ls)',
         id(new LegalpadDocumentSignature())->getTableName(),
         $this->signerPHIDs);
     }
 
     return $joins;
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->contributorPHIDs) {
       return true;
     }
 
     if ($this->signerPHIDs) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'd.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'd.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->creatorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'd.creatorPHID IN (%Ls)',
         $this->creatorPHIDs);
     }
 
     if ($this->dateCreatedAfter !== null) {
       $where[] = qsprintf(
         $conn,
         'd.dateCreated >= %d',
         $this->dateCreatedAfter);
     }
 
     if ($this->dateCreatedBefore !== null) {
       $where[] = qsprintf(
         $conn,
         'd.dateCreated <= %d',
         $this->dateCreatedBefore);
     }
 
     if ($this->contributorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'contributor.dst IN (%Ls)',
         $this->contributorPHIDs);
     }
 
     if ($this->signatureRequired !== null) {
       $where[] = qsprintf(
         $conn,
         'd.requireSignature = %d',
         $this->signatureRequired);
     }
 
     return $where;
   }
 
   private function loadDocumentBodies(array $documents) {
     $body_phids = mpull($documents, 'getDocumentBodyPHID');
     $bodies = id(new LegalpadDocumentBody())->loadAllWhere(
       'phid IN (%Ls)',
       $body_phids);
     $bodies = mpull($bodies, null, 'getPHID');
 
     foreach ($documents as $document) {
       $body = idx($bodies, $document->getDocumentBodyPHID());
       $document->attachDocumentBody($body);
     }
 
     return $documents;
   }
 
   private function loadContributors(array $documents) {
     $document_map = mpull($documents, null, 'getPHID');
     $edge_type = PhabricatorObjectHasContributorEdgeType::EDGECONST;
     $contributor_data = id(new PhabricatorEdgeQuery())
       ->withSourcePHIDs(array_keys($document_map))
       ->withEdgeTypes(array($edge_type))
       ->execute();
 
     foreach ($document_map as $document_phid => $document) {
       $data = $contributor_data[$document_phid];
       $contributors = array_keys(idx($data, $edge_type, array()));
       $document->attachContributors($contributors);
     }
 
     return $documents;
   }
 
   private function loadSignatures(array $documents) {
     $document_map = mpull($documents, null, 'getPHID');
 
     $signatures = id(new LegalpadDocumentSignatureQuery())
       ->setViewer($this->getViewer())
       ->withDocumentPHIDs(array_keys($document_map))
       ->execute();
     $signatures = mgroup($signatures, 'getDocumentPHID');
 
     foreach ($documents as $document) {
       $sigs = idx($signatures, $document->getPHID(), array());
       $document->attachSignatures($sigs);
     }
 
     return $documents;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorLegalpadApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'd';
   }
 
 }
diff --git a/src/applications/macro/query/PhabricatorMacroQuery.php b/src/applications/macro/query/PhabricatorMacroQuery.php
index 7261803888..70e7f7e688 100644
--- a/src/applications/macro/query/PhabricatorMacroQuery.php
+++ b/src/applications/macro/query/PhabricatorMacroQuery.php
@@ -1,268 +1,264 @@
 <?php
 
 final class PhabricatorMacroQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $names;
   private $nameLike;
   private $namePrefix;
   private $dateCreatedAfter;
   private $dateCreatedBefore;
   private $flagColor;
 
   private $needFiles;
 
   private $status = 'status-any';
   const STATUS_ANY = 'status-any';
   const STATUS_ACTIVE = 'status-active';
   const STATUS_DISABLED = 'status-disabled';
 
   public static function getStatusOptions() {
     return array(
       self::STATUS_ACTIVE   => pht('Active Macros'),
       self::STATUS_DISABLED => pht('Disabled Macros'),
       self::STATUS_ANY      => pht('Active and Disabled Macros'),
     );
   }
 
   public static function getFlagColorsOptions() {
     $options = array(
       '-1' => pht('(No Filtering)'),
       '-2' => pht('(Marked With Any Flag)'),
     );
 
     foreach (PhabricatorFlagColor::getColorNameMap() as $color => $name) {
       $options[$color] = $name;
     }
 
     return $options;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
   public function withNameLike($name) {
     $this->nameLike = $name;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNamePrefix($prefix) {
     $this->namePrefix = $prefix;
     return $this;
   }
 
   public function withStatus($status) {
     $this->status = $status;
     return $this;
   }
 
   public function withDateCreatedBefore($date_created_before) {
     $this->dateCreatedBefore = $date_created_before;
     return $this;
   }
 
   public function withDateCreatedAfter($date_created_after) {
     $this->dateCreatedAfter = $date_created_after;
     return $this;
   }
 
   public function withFlagColor($flag_color) {
     $this->flagColor = $flag_color;
     return $this;
   }
 
   public function needFiles($need_files) {
     $this->needFiles = $need_files;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorFileImageMacro();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage(new PhabricatorFileImageMacro());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'm.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'm.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'm.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if (($this->nameLike !== null) && strlen($this->nameLike)) {
       $where[] = qsprintf(
         $conn,
         'm.name LIKE %~',
         $this->nameLike);
     }
 
     if ($this->names !== null) {
       $where[] = qsprintf(
         $conn,
         'm.name IN (%Ls)',
         $this->names);
     }
 
     if (($this->namePrefix !== null) && strlen($this->namePrefix)) {
       $where[] = qsprintf(
         $conn,
         'm.name LIKE %>',
         $this->namePrefix);
     }
 
     switch ($this->status) {
       case self::STATUS_ACTIVE:
         $where[] = qsprintf(
           $conn,
           'm.isDisabled = 0');
         break;
       case self::STATUS_DISABLED:
         $where[] = qsprintf(
           $conn,
           'm.isDisabled = 1');
         break;
       case self::STATUS_ANY:
         break;
       default:
         throw new Exception(pht("Unknown status '%s'!", $this->status));
     }
 
     if ($this->dateCreatedAfter) {
       $where[] = qsprintf(
         $conn,
         'm.dateCreated >= %d',
         $this->dateCreatedAfter);
     }
 
     if ($this->dateCreatedBefore) {
       $where[] = qsprintf(
         $conn,
         'm.dateCreated <= %d',
         $this->dateCreatedBefore);
     }
 
     if ($this->flagColor != '-1' && $this->flagColor !== null) {
       if ($this->flagColor == '-2') {
         $flag_colors = array_keys(PhabricatorFlagColor::getColorNameMap());
       } else {
         $flag_colors = array($this->flagColor);
       }
       $flags = id(new PhabricatorFlagQuery())
         ->withOwnerPHIDs(array($this->getViewer()->getPHID()))
         ->withTypes(array(PhabricatorMacroMacroPHIDType::TYPECONST))
         ->withColors($flag_colors)
         ->setViewer($this->getViewer())
         ->execute();
 
       if (empty($flags)) {
         throw new PhabricatorEmptyQueryException(pht('No matching flags.'));
       } else {
         $where[] = qsprintf(
           $conn,
           'm.phid IN (%Ls)',
           mpull($flags, 'getObjectPHID'));
       }
     }
 
     return $where;
   }
 
   protected function didFilterPage(array $macros) {
     if ($this->needFiles) {
       $file_phids = mpull($macros, 'getFilePHID');
       $files = id(new PhabricatorFileQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($file_phids)
         ->execute();
       $files = mpull($files, null, 'getPHID');
 
       foreach ($macros as $key => $macro) {
         $file = idx($files, $macro->getFilePHID());
         if (!$file) {
           unset($macros[$key]);
           continue;
         }
         $macro->attachFile($file);
       }
     }
 
     return $macros;
   }
 
   protected function getPrimaryTableAlias() {
     return 'm';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorMacroApplication';
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => 'm',
         'column' => 'name',
         'type' => 'string',
         'reverse' => true,
         'unique' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
     );
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name'),
         'name' => pht('Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
 }
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php
index e6ec09f4ff..b7dd3e5ee4 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php
@@ -1,51 +1,47 @@
 <?php
 
 final class PhabricatorMetaMTAMailPropertiesQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $objectPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorMetaMTAMailProperties();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorMetaMTAApplication';
   }
 
 }
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
index 903b385ceb..d1f0235c90 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
@@ -1,132 +1,128 @@
 <?php
 
 final class PhabricatorMetaMTAMailQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $actorPHIDs;
   private $recipientPHIDs;
   private $createdMin;
   private $createdMax;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withActorPHIDs(array $phids) {
     $this->actorPHIDs = $phids;
     return $this;
   }
 
   public function withRecipientPHIDs(array $phids) {
     $this->recipientPHIDs = $phids;
     return $this;
   }
 
   public function withDateCreatedBetween($min, $max) {
     $this->createdMin = $min;
     $this->createdMax = $max;
     return $this;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'mail.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'mail.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->actorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'mail.actorPHID IN (%Ls)',
         $this->actorPHIDs);
     }
 
     if ($this->createdMin !== null) {
       $where[] = qsprintf(
         $conn,
         'mail.dateCreated >= %d',
         $this->createdMin);
     }
 
     if ($this->createdMax !== null) {
       $where[] = qsprintf(
         $conn,
         'mail.dateCreated <= %d',
         $this->createdMax);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinRecipients()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T recipient
           ON mail.phid = recipient.src
             AND recipient.type = %d
             AND recipient.dst IN (%Ls)',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST,
         $this->recipientPHIDs);
     }
 
     return $joins;
   }
 
   private function shouldJoinRecipients() {
     if ($this->recipientPHIDs === null) {
       return false;
     }
 
     return true;
   }
 
   protected function getPrimaryTableAlias() {
     return 'mail';
   }
 
   public function newResultObject() {
     return new PhabricatorMetaMTAMail();
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorMetaMTAApplication';
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->shouldJoinRecipients()) {
       if (count($this->recipientPHIDs) > 1) {
         return true;
       }
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
 }
diff --git a/src/applications/nuance/query/NuanceImportCursorDataQuery.php b/src/applications/nuance/query/NuanceImportCursorDataQuery.php
index ae451abfb9..133c940b3f 100644
--- a/src/applications/nuance/query/NuanceImportCursorDataQuery.php
+++ b/src/applications/nuance/query/NuanceImportCursorDataQuery.php
@@ -1,60 +1,56 @@
 <?php
 
 final class NuanceImportCursorDataQuery
   extends NuanceQuery {
 
   private $ids;
   private $phids;
   private $sourcePHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withSourcePHIDs(array $source_phids) {
     $this->sourcePHIDs = $source_phids;
     return $this;
   }
 
   public function newResultObject() {
     return new NuanceImportCursorData();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->sourcePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'sourcePHID IN (%Ls)',
         $this->sourcePHIDs);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/nuance/query/NuanceItemCommandQuery.php b/src/applications/nuance/query/NuanceItemCommandQuery.php
index 27137cf8f6..a694657120 100644
--- a/src/applications/nuance/query/NuanceItemCommandQuery.php
+++ b/src/applications/nuance/query/NuanceItemCommandQuery.php
@@ -1,60 +1,56 @@
 <?php
 
 final class NuanceItemCommandQuery
   extends NuanceQuery {
 
   private $ids;
   private $itemPHIDs;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withItemPHIDs(array $item_phids) {
     $this->itemPHIDs = $item_phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new NuanceItemCommand();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->itemPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'itemPHID IN (%Ls)',
         $this->itemPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/nuance/query/NuanceItemQuery.php b/src/applications/nuance/query/NuanceItemQuery.php
index 834e81ca72..e2e32c84b4 100644
--- a/src/applications/nuance/query/NuanceItemQuery.php
+++ b/src/applications/nuance/query/NuanceItemQuery.php
@@ -1,196 +1,192 @@
 <?php
 
 final class NuanceItemQuery
   extends NuanceQuery {
 
   private $ids;
   private $phids;
   private $sourcePHIDs;
   private $queuePHIDs;
   private $itemTypes;
   private $itemKeys;
   private $containerKeys;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withSourcePHIDs(array $source_phids) {
     $this->sourcePHIDs = $source_phids;
     return $this;
   }
 
   public function withQueuePHIDs(array $queue_phids) {
     $this->queuePHIDs = $queue_phids;
     return $this;
   }
 
   public function withItemTypes(array $item_types) {
     $this->itemTypes = $item_types;
     return $this;
   }
 
   public function withItemKeys(array $item_keys) {
     $this->itemKeys = $item_keys;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withItemContainerKeys(array $container_keys) {
     $this->containerKeys = $container_keys;
     return $this;
   }
 
   public function newResultObject() {
     return new NuanceItem();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $items) {
     $viewer = $this->getViewer();
     $source_phids = mpull($items, 'getSourcePHID');
 
     $sources = id(new NuanceSourceQuery())
       ->setViewer($viewer)
       ->withPHIDs($source_phids)
       ->execute();
     $sources = mpull($sources, null, 'getPHID');
 
     foreach ($items as $key => $item) {
       $source = idx($sources, $item->getSourcePHID());
       if (!$source) {
         $this->didRejectResult($items[$key]);
         unset($items[$key]);
         continue;
       }
       $item->attachSource($source);
     }
 
     $type_map = NuanceItemType::getAllItemTypes();
     foreach ($items as $key => $item) {
       $type = idx($type_map, $item->getItemType());
       if (!$type) {
         $this->didRejectResult($items[$key]);
         unset($items[$key]);
         continue;
       }
       $item->attachImplementation($type);
     }
 
     $queue_phids = array();
     foreach ($items as $item) {
       $queue_phid = $item->getQueuePHID();
       if ($queue_phid) {
         $queue_phids[$queue_phid] = $queue_phid;
       }
     }
 
     if ($queue_phids) {
       $queues = id(new NuanceQueueQuery())
         ->setViewer($viewer)
         ->withPHIDs($queue_phids)
         ->execute();
       $queues = mpull($queues, null, 'getPHID');
     } else {
       $queues = array();
     }
 
     foreach ($items as $key => $item) {
       $queue_phid = $item->getQueuePHID();
 
       if (!$queue_phid) {
         $item->attachQueue(null);
         continue;
       }
 
       $queue = idx($queues, $queue_phid);
 
       if (!$queue) {
         unset($items[$key]);
         $this->didRejectResult($item);
         continue;
       }
 
       $item->attachQueue($queue);
     }
 
     return $items;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->sourcePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'sourcePHID IN (%Ls)',
         $this->sourcePHIDs);
     }
 
     if ($this->queuePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'queuePHID IN (%Ls)',
         $this->queuePHIDs);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->itemTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'itemType IN (%Ls)',
         $this->itemTypes);
     }
 
     if ($this->itemKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'itemKey IN (%Ls)',
         $this->itemKeys);
     }
 
     if ($this->containerKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'itemContainerKey IN (%Ls)',
         $this->containerKeys);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/nuance/query/NuanceQueueQuery.php b/src/applications/nuance/query/NuanceQueueQuery.php
index 10f761d189..acb69665e0 100644
--- a/src/applications/nuance/query/NuanceQueueQuery.php
+++ b/src/applications/nuance/query/NuanceQueueQuery.php
@@ -1,47 +1,43 @@
 <?php
 
 final class NuanceQueueQuery
   extends NuanceQuery {
 
   private $ids;
   private $phids;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new NuanceQueue();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/nuance/query/NuanceSourceQuery.php b/src/applications/nuance/query/NuanceSourceQuery.php
index 907d9c314f..9186d47cdd 100644
--- a/src/applications/nuance/query/NuanceSourceQuery.php
+++ b/src/applications/nuance/query/NuanceSourceQuery.php
@@ -1,137 +1,133 @@
 <?php
 
 final class NuanceSourceQuery
   extends NuanceQuery {
 
   private $ids;
   private $phids;
   private $types;
   private $isDisabled;
   private $hasCursors;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withTypes($types) {
     $this->types = $types;
     return $this;
   }
 
   public function withIsDisabled($disabled) {
     $this->isDisabled = $disabled;
     return $this;
   }
 
   public function withHasImportCursors($has_cursors) {
     $this->hasCursors = $has_cursors;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new NuanceSourceNameNgrams(),
       $ngrams);
   }
 
   public function newResultObject() {
     return new NuanceSource();
   }
 
   protected function getPrimaryTableAlias() {
     return 'source';
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $sources) {
     $all_types = NuanceSourceDefinition::getAllDefinitions();
 
     foreach ($sources as $key => $source) {
       $definition = idx($all_types, $source->getType());
       if (!$definition) {
         $this->didRejectResult($source);
         unset($sources[$key]);
         continue;
       }
       $source->attachDefinition($definition);
     }
 
     return $sources;
   }
 
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->types !== null) {
       $where[] = qsprintf(
         $conn,
         'source.type IN (%Ls)',
         $this->types);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'source.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'source.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->isDisabled !== null) {
       $where[] = qsprintf(
         $conn,
         'source.isDisabled = %d',
         (int)$this->isDisabled);
     }
 
     if ($this->hasCursors !== null) {
       $cursor_types = array();
 
       $definitions = NuanceSourceDefinition::getAllDefinitions();
       foreach ($definitions as $key => $definition) {
         if ($definition->hasImportCursors()) {
           $cursor_types[] = $key;
         }
       }
 
       if ($this->hasCursors) {
         if (!$cursor_types) {
           throw new PhabricatorEmptyQueryException();
         } else {
           $where[] = qsprintf(
             $conn,
             'source.type IN (%Ls)',
             $cursor_types);
         }
       } else {
         if (!$cursor_types) {
           // Apply no constraint.
         } else {
           $where[] = qsprintf(
             $conn,
             'source.type NOT IN (%Ls)',
             $cursor_types);
         }
       }
     }
 
     return $where;
   }
 
 }
diff --git a/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php b/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
index a746008f55..63a62e8cd9 100644
--- a/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
+++ b/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
@@ -1,89 +1,85 @@
 <?php
 
 final class PhabricatorOAuthClientAuthorizationQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $phids;
   private $userPHIDs;
   private $clientPHIDs;
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withUserPHIDs(array $phids) {
     $this->userPHIDs = $phids;
     return $this;
   }
 
   public function withClientPHIDs(array $phids) {
     $this->clientPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorOAuthClientAuthorization();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $authorizations) {
     $client_phids = mpull($authorizations, 'getClientPHID');
 
     $clients = id(new PhabricatorOAuthServerClientQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($client_phids)
       ->execute();
     $clients = mpull($clients, null, 'getPHID');
 
     foreach ($authorizations as $key => $authorization) {
       $client = idx($clients, $authorization->getClientPHID());
 
       if (!$client) {
         $this->didRejectResult($authorization);
         unset($authorizations[$key]);
         continue;
       }
 
       $authorization->attachClient($client);
     }
 
     return $authorizations;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     if ($this->clientPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'clientPHID IN (%Ls)',
         $this->clientPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorOAuthServerApplication';
   }
 
 }
diff --git a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
index 9e5e4c3234..a80b972548 100644
--- a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
+++ b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
@@ -1,464 +1,460 @@
 <?php
 
 final class PhabricatorOwnersPackageQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $ownerPHIDs;
   private $authorityPHIDs;
   private $repositoryPHIDs;
   private $paths;
   private $statuses;
   private $authorityModes;
 
   private $controlMap = array();
   private $controlResults;
 
   private $needPaths;
 
 
   /**
    * Query owner PHIDs exactly. This does not expand authorities, so a user
    * PHID will not match projects the user is a member of.
    */
   public function withOwnerPHIDs(array $phids) {
     $this->ownerPHIDs = $phids;
     return $this;
   }
 
   /**
    * Query owner authority. This will expand authorities, so a user PHID will
    * match both packages they own directly and packages owned by a project they
    * are a member of.
    */
   public function withAuthorityPHIDs(array $phids) {
     $this->authorityPHIDs = $phids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $phids) {
     $this->repositoryPHIDs = $phids;
     return $this;
   }
 
   public function withPaths(array $paths) {
     $this->paths = $paths;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withControl($repository_phid, array $paths) {
     if (empty($this->controlMap[$repository_phid])) {
       $this->controlMap[$repository_phid] = array();
     }
 
     foreach ($paths as $path) {
       $path = (string)$path;
       $this->controlMap[$repository_phid][$path] = $path;
     }
 
     // We need to load paths to execute control queries.
     $this->needPaths = true;
 
     return $this;
   }
 
   public function withAuthorityModes(array $modes) {
     $this->authorityModes = $modes;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new PhabricatorOwnersPackageNameNgrams(),
       $ngrams);
   }
 
   public function needPaths($need_paths) {
     $this->needPaths = $need_paths;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorOwnersPackage();
   }
 
   protected function willExecute() {
     $this->controlResults = array();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $packages) {
     $package_ids = mpull($packages, 'getID');
 
     $owners = id(new PhabricatorOwnersOwner())->loadAllWhere(
       'packageID IN (%Ld)',
       $package_ids);
     $owners = mgroup($owners, 'getPackageID');
     foreach ($packages as $package) {
       $package->attachOwners(idx($owners, $package->getID(), array()));
     }
 
     return $packages;
   }
 
   protected function didFilterPage(array $packages) {
     $package_ids = mpull($packages, 'getID');
 
     if ($this->needPaths) {
       $paths = id(new PhabricatorOwnersPath())->loadAllWhere(
         'packageID IN (%Ld)',
         $package_ids);
       $paths = mgroup($paths, 'getPackageID');
 
       foreach ($packages as $package) {
         $package->attachPaths(idx($paths, $package->getID(), array()));
       }
     }
 
     if ($this->controlMap) {
       foreach ($packages as $package) {
         // If this package is archived, it's no longer a controlling package
         // for any path. In particular, it can not force active packages with
         // weak dominion to give up control.
         if ($package->isArchived()) {
           continue;
         }
 
         $this->controlResults[$package->getID()] = $package;
       }
     }
 
     return $packages;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinOwnersTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T o ON o.packageID = p.id',
         id(new PhabricatorOwnersOwner())->getTableName());
     }
 
     if ($this->shouldJoinPathTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T rpath ON rpath.packageID = p.id',
         id(new PhabricatorOwnersPath())->getTableName());
     }
 
     return $joins;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'rpath.repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->authorityPHIDs !== null) {
       $authority_phids = $this->expandAuthority($this->authorityPHIDs);
       $where[] = qsprintf(
         $conn,
         'o.userPHID IN (%Ls)',
         $authority_phids);
     }
 
     if ($this->ownerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'o.userPHID IN (%Ls)',
         $this->ownerPHIDs);
     }
 
     if ($this->paths !== null) {
       $where[] = qsprintf(
         $conn,
         'rpath.pathIndex IN (%Ls)',
         $this->getFragmentIndexesForPaths($this->paths));
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'p.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->controlMap) {
       $clauses = array();
       foreach ($this->controlMap as $repository_phid => $paths) {
         $indexes = $this->getFragmentIndexesForPaths($paths);
 
         $clauses[] = qsprintf(
           $conn,
           '(rpath.repositoryPHID = %s AND rpath.pathIndex IN (%Ls))',
           $repository_phid,
           $indexes);
       }
       $where[] = qsprintf($conn, '%LO', $clauses);
     }
 
     if ($this->authorityModes !== null) {
       $where[] = qsprintf(
         $conn,
         'authorityMode IN (%Ls)',
         $this->authorityModes);
     }
 
     return $where;
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->shouldJoinOwnersTable()) {
       return true;
     }
 
     if ($this->shouldJoinPathTable()) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name'),
         'name' => pht('Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'name',
         'type' => 'string',
         'unique' => true,
         'reverse' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
     );
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorOwnersApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'p';
   }
 
   private function shouldJoinOwnersTable() {
     if ($this->ownerPHIDs !== null) {
       return true;
     }
 
     if ($this->authorityPHIDs !== null) {
       return true;
     }
 
     return false;
   }
 
   private function shouldJoinPathTable() {
     if ($this->repositoryPHIDs !== null) {
       return true;
     }
 
     if ($this->paths !== null) {
       return true;
     }
 
     if ($this->controlMap) {
       return true;
     }
 
     return false;
   }
 
   private function expandAuthority(array $phids) {
     $projects = id(new PhabricatorProjectQuery())
       ->setViewer($this->getViewer())
       ->withMemberPHIDs($phids)
       ->execute();
     $project_phids = mpull($projects, 'getPHID');
 
     return array_fuse($phids) + array_fuse($project_phids);
   }
 
   private function getFragmentsForPaths(array $paths) {
     $fragments = array();
 
     foreach ($paths as $path) {
       foreach (PhabricatorOwnersPackage::splitPath($path) as $fragment) {
         $fragments[$fragment] = $fragment;
       }
     }
 
     return $fragments;
   }
 
   private function getFragmentIndexesForPaths(array $paths) {
     $indexes = array();
 
     foreach ($this->getFragmentsForPaths($paths) as $fragment) {
       $indexes[] = PhabricatorHash::digestForIndex($fragment);
     }
 
     return $indexes;
   }
 
 
 /* -(  Path Control  )------------------------------------------------------- */
 
 
   /**
    * Get a list of all packages which control a path or its parent directories,
    * ordered from weakest to strongest.
    *
    * The first package has the most specific claim on the path; the last
    * package has the most general claim. Multiple packages may have claims of
    * equal strength, so this ordering is primarily one of usability and
    * convenience.
    *
    * @return list<PhabricatorOwnersPackage> List of controlling packages.
    */
   public function getControllingPackagesForPath(
     $repository_phid,
     $path,
     $ignore_dominion = false) {
     $path = (string)$path;
 
     if (!isset($this->controlMap[$repository_phid][$path])) {
       throw new PhutilInvalidStateException('withControl');
     }
 
     if ($this->controlResults === null) {
       throw new PhutilInvalidStateException('execute');
     }
 
     $packages = $this->controlResults;
     $weak_dominion = PhabricatorOwnersPackage::DOMINION_WEAK;
 
     $path_fragments = PhabricatorOwnersPackage::splitPath($path);
     $fragment_count = count($path_fragments);
 
     $matches = array();
     foreach ($packages as $package_id => $package) {
       $best_match = null;
       $include = false;
 
       $repository_paths = $package->getPathsForRepository($repository_phid);
       foreach ($repository_paths as $package_path) {
         $strength = $package_path->getPathMatchStrength(
           $path_fragments,
           $fragment_count);
         if ($strength > $best_match) {
           $best_match = $strength;
           $include = !$package_path->getExcluded();
         }
       }
 
       if ($best_match && $include) {
         if ($ignore_dominion) {
           $is_weak = false;
         } else {
           $is_weak = ($package->getDominion() == $weak_dominion);
         }
         $matches[$package_id] = array(
           'strength' => $best_match,
           'weak' => $is_weak,
           'package' => $package,
         );
       }
     }
 
     // At each strength level, drop weak packages if there are also strong
     // packages of the same strength.
     $strength_map = igroup($matches, 'strength');
     foreach ($strength_map as $strength => $package_list) {
       $any_strong = false;
       foreach ($package_list as $package_id => $package) {
         if (!$package['weak']) {
           $any_strong = true;
           break;
         }
       }
       if ($any_strong) {
         foreach ($package_list as $package_id => $package) {
           if ($package['weak']) {
             unset($matches[$package_id]);
           }
         }
       }
     }
 
     $matches = isort($matches, 'strength');
     $matches = array_reverse($matches);
 
     $strongest = null;
     foreach ($matches as $package_id => $match) {
       if ($strongest === null) {
         $strongest = $match['strength'];
       }
 
       if ($match['strength'] === $strongest) {
         continue;
       }
 
       if ($match['weak']) {
         unset($matches[$package_id]);
       }
     }
 
     return array_values(ipull($matches, 'package'));
   }
 
 }
diff --git a/src/applications/packages/query/PhabricatorPackagesPackageQuery.php b/src/applications/packages/query/PhabricatorPackagesPackageQuery.php
index 67cd3954c9..c97e3b244c 100644
--- a/src/applications/packages/query/PhabricatorPackagesPackageQuery.php
+++ b/src/applications/packages/query/PhabricatorPackagesPackageQuery.php
@@ -1,135 +1,131 @@
 <?php
 
 final class PhabricatorPackagesPackageQuery
   extends PhabricatorPackagesQuery {
 
   private $ids;
   private $phids;
   private $publisherPHIDs;
   private $packageKeys;
   private $fullKeys;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withPublisherPHIDs(array $phids) {
     $this->publisherPHIDs = $phids;
     return $this;
   }
 
   public function withPackageKeys(array $keys) {
     $this->packageKeys = $keys;
     return $this;
   }
 
   public function withFullKeys(array $keys) {
     $this->fullKeys = $keys;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new PhabricatorPackagesPackageNameNgrams(),
       $ngrams);
   }
 
   public function newResultObject() {
     return new PhabricatorPackagesPackage();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->publisherPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'p.publisherPHID IN (%Ls)',
         $this->publisherPHIDs);
     }
 
     if ($this->packageKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'p.packageKey IN (%Ls)',
         $this->packageKeys);
     }
 
     if ($this->fullKeys !== null) {
       $parts = $this->buildFullKeyClauseParts($conn, $this->fullKeys);
       $where[] = qsprintf($conn, '%Q', $parts);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     $join_publisher = ($this->fullKeys !== null);
     if ($join_publisher) {
       $publisher_table = new PhabricatorPackagesPublisher();
 
       $joins[] = qsprintf(
         $conn,
         'JOIN %T u ON u.phid = p.publisherPHID',
         $publisher_table->getTableName());
     }
 
     return $joins;
   }
 
   protected function willFilterPage(array $packages) {
     $publisher_phids = mpull($packages, 'getPublisherPHID');
 
     $publishers = id(new PhabricatorPackagesPublisherQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($publisher_phids)
       ->execute();
     $publishers = mpull($publishers, null, 'getPHID');
 
     foreach ($packages as $key => $package) {
       $publisher = idx($publishers, $package->getPublisherPHID());
 
       if (!$publisher) {
         unset($packages[$key]);
         $this->didRejectResult($package);
         continue;
       }
 
       $package->attachPublisher($publisher);
     }
 
     return $packages;
   }
 
   protected function getPrimaryTableAlias() {
     return 'p';
   }
 
 }
diff --git a/src/applications/packages/query/PhabricatorPackagesPublisherQuery.php b/src/applications/packages/query/PhabricatorPackagesPublisherQuery.php
index d46535c20d..7d31e5fec6 100644
--- a/src/applications/packages/query/PhabricatorPackagesPublisherQuery.php
+++ b/src/applications/packages/query/PhabricatorPackagesPublisherQuery.php
@@ -1,70 +1,66 @@
 <?php
 
 final class PhabricatorPackagesPublisherQuery
   extends PhabricatorPackagesQuery {
 
   private $ids;
   private $phids;
   private $publisherKeys;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withPublisherKeys(array $keys) {
     $this->publisherKeys = $keys;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new PhabricatorPackagesPublisherNameNgrams(),
       $ngrams);
   }
 
   public function newResultObject() {
     return new PhabricatorPackagesPublisher();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'u.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'u.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->publisherKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'u.publisherKey IN (%Ls)',
         $this->publisherKeys);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'u';
   }
 
 }
diff --git a/src/applications/packages/query/PhabricatorPackagesVersionQuery.php b/src/applications/packages/query/PhabricatorPackagesVersionQuery.php
index 6f417e2f77..447907c4a0 100644
--- a/src/applications/packages/query/PhabricatorPackagesVersionQuery.php
+++ b/src/applications/packages/query/PhabricatorPackagesVersionQuery.php
@@ -1,147 +1,143 @@
 <?php
 
 final class PhabricatorPackagesVersionQuery
   extends PhabricatorPackagesQuery {
 
   private $ids;
   private $phids;
   private $packagePHIDs;
   private $fullKeys;
   private $names;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withPackagePHIDs(array $phids) {
     $this->packagePHIDs = $phids;
     return $this;
   }
 
   public function withFullKeys(array $keys) {
     $this->fullKeys = $keys;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       new PhabricatorPackagesVersionNameNgrams(),
       $ngrams);
   }
 
   public function newResultObject() {
     return new PhabricatorPackagesVersion();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'v.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'v.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->packagePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'v.packagePHID IN (%Ls)',
         $this->packagePHIDs);
     }
 
     if ($this->names !== null) {
       $where[] = qsprintf(
         $conn,
         'v.name IN (%Ls)',
         $this->names);
     }
 
     if ($this->fullKeys !== null) {
       $parts = $this->buildFullKeyClauseParts($conn, $this->fullKeys);
       $where[] = qsprintf($conn, '%Q', $parts);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     $join_publisher = ($this->fullKeys !== null);
     $join_package = ($this->fullKeys !== null) || $join_publisher;
 
     if ($join_package) {
       $package_table = new PhabricatorPackagesPackage();
 
       $joins[] = qsprintf(
         $conn,
         'JOIN %T p ON v.packagePHID = p.phid',
         $package_table->getTableName());
     }
 
     if ($join_publisher) {
       $publisher_table = new PhabricatorPackagesPublisher();
 
       $joins[] = qsprintf(
         $conn,
         'JOIN %T u ON u.phid = p.publisherPHID',
         $publisher_table->getTableName());
     }
 
     return $joins;
   }
 
   protected function willFilterPage(array $versions) {
     $package_phids = mpull($versions, 'getPackagePHID');
 
     $packages = id(new PhabricatorPackagesPackageQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($package_phids)
       ->execute();
     $packages = mpull($packages, null, 'getPHID');
 
     foreach ($versions as $key => $version) {
       $package = idx($packages, $version->getPackagePHID());
 
       if (!$package) {
         unset($versions[$key]);
         $this->didRejectResult($version);
         continue;
       }
 
       $version->attachPackage($package);
     }
 
     return $versions;
   }
 
   protected function getPrimaryTableAlias() {
     return 'v';
   }
 
 
 }
diff --git a/src/applications/passphrase/query/PassphraseCredentialQuery.php b/src/applications/passphrase/query/PassphraseCredentialQuery.php
index 24f5f7440c..98ae9429a8 100644
--- a/src/applications/passphrase/query/PassphraseCredentialQuery.php
+++ b/src/applications/passphrase/query/PassphraseCredentialQuery.php
@@ -1,169 +1,165 @@
 <?php
 
 final class PassphraseCredentialQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $credentialTypes;
   private $providesTypes;
   private $isDestroyed;
   private $allowConduit;
   private $nameContains;
 
   private $needSecrets;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withCredentialTypes(array $credential_types) {
     $this->credentialTypes = $credential_types;
     return $this;
   }
 
   public function withProvidesTypes(array $provides_types) {
     $this->providesTypes = $provides_types;
     return $this;
   }
 
   public function withIsDestroyed($destroyed) {
     $this->isDestroyed = $destroyed;
     return $this;
   }
 
   public function withAllowConduit($allow_conduit) {
     $this->allowConduit = $allow_conduit;
     return $this;
   }
 
   public function withNameContains($name_contains) {
     $this->nameContains = $name_contains;
     return $this;
   }
 
   public function needSecrets($need_secrets) {
     $this->needSecrets = $need_secrets;
     return $this;
   }
 
   public function newResultObject() {
     return new PassphraseCredential();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     if ($this->needSecrets) {
       $secret_ids = mpull($page, 'getSecretID');
       $secret_ids = array_filter($secret_ids);
 
       $secrets = array();
       if ($secret_ids) {
         $secret_objects = id(new PassphraseSecret())->loadAllWhere(
           'id IN (%Ld)',
           $secret_ids);
         foreach ($secret_objects as $secret) {
           $secret_data = $secret->getSecretData();
           $secrets[$secret->getID()] = new PhutilOpaqueEnvelope($secret_data);
         }
       }
 
       foreach ($page as $key => $credential) {
         $secret_id = $credential->getSecretID();
         if (!$secret_id) {
           $credential->attachSecret(null);
         } else if (isset($secrets[$secret_id])) {
           $credential->attachSecret($secrets[$secret_id]);
         } else {
           unset($page[$key]);
         }
       }
     }
 
     foreach ($page as $key => $credential) {
       $type = PassphraseCredentialType::getTypeByConstant(
         $credential->getCredentialType());
       if (!$type) {
         unset($page[$key]);
         continue;
       }
 
       $credential->attachImplementation(clone $type);
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'c.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'c.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->credentialTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'c.credentialType in (%Ls)',
         $this->credentialTypes);
     }
 
     if ($this->providesTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'c.providesType IN (%Ls)',
         $this->providesTypes);
     }
 
     if ($this->isDestroyed !== null) {
       $where[] = qsprintf(
         $conn,
         'c.isDestroyed = %d',
         (int)$this->isDestroyed);
     }
 
     if ($this->allowConduit !== null) {
       $where[] = qsprintf(
         $conn,
         'c.allowConduit = %d',
         (int)$this->allowConduit);
     }
 
     if (phutil_nonempty_string($this->nameContains)) {
       $where[] = qsprintf(
         $conn,
         'LOWER(c.name) LIKE %~',
         phutil_utf8_strtolower($this->nameContains));
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPassphraseApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'c';
   }
 
 }
diff --git a/src/applications/paste/query/PhabricatorPasteQuery.php b/src/applications/paste/query/PhabricatorPasteQuery.php
index d90ef3b1d2..e841bff300 100644
--- a/src/applications/paste/query/PhabricatorPasteQuery.php
+++ b/src/applications/paste/query/PhabricatorPasteQuery.php
@@ -1,400 +1,396 @@
 <?php
 
 final class PhabricatorPasteQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $parentPHIDs;
 
   private $needContent;
   private $needRawContent;
   private $needSnippets;
   private $languages;
   private $includeNoLanguage;
   private $dateCreatedAfter;
   private $dateCreatedBefore;
   private $statuses;
 
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function withParentPHIDs(array $phids) {
     $this->parentPHIDs = $phids;
     return $this;
   }
 
   public function needContent($need_content) {
     $this->needContent = $need_content;
     return $this;
   }
 
   public function needRawContent($need_raw_content) {
     $this->needRawContent = $need_raw_content;
     return $this;
   }
 
   public function needSnippets($need_snippets) {
     $this->needSnippets = $need_snippets;
     return $this;
   }
 
   public function withLanguages(array $languages) {
     $this->includeNoLanguage = false;
     foreach ($languages as $key => $language) {
       if ($language === null) {
         $languages[$key] = '';
         continue;
       }
     }
     $this->languages = $languages;
     return $this;
   }
 
   public function withDateCreatedBefore($date_created_before) {
     $this->dateCreatedBefore = $date_created_before;
     return $this;
   }
 
   public function withDateCreatedAfter($date_created_after) {
     $this->dateCreatedAfter = $date_created_after;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorPaste();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage(new PhabricatorPaste());
-  }
-
   protected function didFilterPage(array $pastes) {
     if ($this->needRawContent) {
       $pastes = $this->loadRawContent($pastes);
     }
 
     if ($this->needContent) {
       $pastes = $this->loadContent($pastes);
     }
 
     if ($this->needSnippets) {
       $pastes = $this->loadSnippets($pastes);
     }
 
     return $pastes;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->parentPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.parentPHID IN (%Ls)',
         $this->parentPHIDs);
     }
 
     if ($this->languages !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.language IN (%Ls)',
         $this->languages);
     }
 
     if ($this->dateCreatedAfter !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.dateCreated >= %d',
         $this->dateCreatedAfter);
     }
 
     if ($this->dateCreatedBefore !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.dateCreated <= %d',
         $this->dateCreatedBefore);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'paste.status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'paste';
   }
 
   private function getContentCacheKey(PhabricatorPaste $paste) {
     return implode(
       ':',
       array(
         'P'.$paste->getID(),
         $paste->getFilePHID(),
         $paste->getLanguage(),
         PhabricatorHash::digestForIndex($paste->getTitle()),
       ));
   }
 
   private function getSnippetCacheKey(PhabricatorPaste $paste) {
     return implode(
       ':',
       array(
         'P'.$paste->getID(),
         $paste->getFilePHID(),
         $paste->getLanguage(),
         'snippet',
         'v2.1',
         PhabricatorHash::digestForIndex($paste->getTitle()),
       ));
   }
 
   private function loadRawContent(array $pastes) {
     $file_phids = mpull($pastes, 'getFilePHID');
     $files = id(new PhabricatorFileQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($file_phids)
       ->execute();
     $files = mpull($files, null, 'getPHID');
 
     foreach ($pastes as $key => $paste) {
       $file = idx($files, $paste->getFilePHID());
       if (!$file) {
         unset($pastes[$key]);
         continue;
       }
       try {
         $paste->attachRawContent($file->loadFileData());
       } catch (Exception $ex) {
         // We can hit various sorts of file storage issues here. Just drop the
         // paste if the file is dead.
         unset($pastes[$key]);
         continue;
       }
     }
 
     return $pastes;
   }
 
   private function loadContent(array $pastes) {
     $cache = new PhabricatorKeyValueDatabaseCache();
 
     $cache = new PhutilKeyValueCacheProfiler($cache);
     $cache->setProfiler(PhutilServiceProfiler::getInstance());
 
     $keys = array();
     foreach ($pastes as $paste) {
       $keys[] = $this->getContentCacheKey($paste);
     }
 
     $caches = $cache->getKeys($keys);
 
     $need_raw = array();
     $have_cache = array();
     foreach ($pastes as $paste) {
       $key = $this->getContentCacheKey($paste);
       if (isset($caches[$key])) {
         $paste->attachContent(phutil_safe_html($caches[$key]));
         $have_cache[$paste->getPHID()] = true;
       } else {
         $need_raw[$key] = $paste;
       }
     }
 
     if (!$need_raw) {
       return $pastes;
     }
 
     $write_data = array();
 
     $have_raw = $this->loadRawContent($need_raw);
     $have_raw = mpull($have_raw, null, 'getPHID');
     foreach ($pastes as $key => $paste) {
       $paste_phid = $paste->getPHID();
       if (isset($have_cache[$paste_phid])) {
         continue;
       }
 
       if (empty($have_raw[$paste_phid])) {
         unset($pastes[$key]);
         continue;
       }
 
       $content = $this->buildContent($paste);
       $paste->attachContent($content);
       $write_data[$this->getContentCacheKey($paste)] = (string)$content;
     }
 
     if ($write_data) {
       $cache->setKeys($write_data);
     }
 
     return $pastes;
   }
 
   private function loadSnippets(array $pastes) {
     $cache = new PhabricatorKeyValueDatabaseCache();
 
     $cache = new PhutilKeyValueCacheProfiler($cache);
     $cache->setProfiler(PhutilServiceProfiler::getInstance());
 
     $keys = array();
     foreach ($pastes as $paste) {
       $keys[] = $this->getSnippetCacheKey($paste);
     }
 
     $caches = $cache->getKeys($keys);
 
     $need_raw = array();
     $have_cache = array();
     foreach ($pastes as $paste) {
       $key = $this->getSnippetCacheKey($paste);
       if (isset($caches[$key])) {
         $snippet_data = phutil_json_decode($caches[$key]);
         $snippet = new PhabricatorPasteSnippet(
           phutil_safe_html($snippet_data['content']),
           $snippet_data['type'],
           $snippet_data['contentLineCount']);
         $paste->attachSnippet($snippet);
         $have_cache[$paste->getPHID()] = true;
       } else {
         $need_raw[$key] = $paste;
       }
     }
 
     if (!$need_raw) {
       return $pastes;
     }
 
     $write_data = array();
 
     $have_raw = $this->loadRawContent($need_raw);
     $have_raw = mpull($have_raw, null, 'getPHID');
     foreach ($pastes as $key => $paste) {
       $paste_phid = $paste->getPHID();
       if (isset($have_cache[$paste_phid])) {
         continue;
       }
 
       if (empty($have_raw[$paste_phid])) {
         unset($pastes[$key]);
         continue;
       }
 
       $snippet = $this->buildSnippet($paste);
       $paste->attachSnippet($snippet);
       $snippet_data = array(
         'content' => (string)$snippet->getContent(),
         'type' => (string)$snippet->getType(),
         'contentLineCount' => $snippet->getContentLineCount(),
       );
       $write_data[$this->getSnippetCacheKey($paste)] = phutil_json_encode(
         $snippet_data);
     }
 
     if ($write_data) {
       $cache->setKeys($write_data);
     }
 
     return $pastes;
   }
 
   private function buildContent(PhabricatorPaste $paste) {
     return $this->highlightSource(
       $paste->getRawContent(),
       $paste->getTitle(),
       $paste->getLanguage());
   }
 
   private function buildSnippet(PhabricatorPaste $paste) {
     $snippet_type = PhabricatorPasteSnippet::FULL;
     $snippet = $paste->getRawContent();
 
     $lines = phutil_split_lines($snippet);
     $line_count = count($lines);
 
     if (strlen($snippet) > 1024) {
       $snippet_type = PhabricatorPasteSnippet::FIRST_BYTES;
       $snippet = id(new PhutilUTF8StringTruncator())
         ->setMaximumBytes(1024)
         ->setTerminator('')
         ->truncateString($snippet);
     }
 
     if ($line_count > 5) {
       $snippet_type = PhabricatorPasteSnippet::FIRST_LINES;
       $snippet = implode('', array_slice($lines, 0, 5));
     }
 
     return new PhabricatorPasteSnippet(
       $this->highlightSource(
         $snippet,
         $paste->getTitle(),
         $paste->getLanguage()),
       $snippet_type,
       $line_count);
   }
 
   private function highlightSource($source, $title, $language) {
     if (empty($language)) {
       return PhabricatorSyntaxHighlighter::highlightWithFilename(
         $title,
         $source);
     } else {
       return PhabricatorSyntaxHighlighter::highlightWithLanguage(
         $language,
         $source);
     }
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPasteApplication';
   }
 
 }
diff --git a/src/applications/people/query/PhabricatorPeopleLogQuery.php b/src/applications/people/query/PhabricatorPeopleLogQuery.php
index 203f79579a..e87fb33660 100644
--- a/src/applications/people/query/PhabricatorPeopleLogQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleLogQuery.php
@@ -1,139 +1,135 @@
 <?php
 
 final class PhabricatorPeopleLogQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $actorPHIDs;
   private $userPHIDs;
   private $relatedPHIDs;
   private $sessionKeys;
   private $actions;
   private $remoteAddressPrefix;
   private $dateCreatedMin;
   private $dateCreatedMax;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withActorPHIDs(array $actor_phids) {
     $this->actorPHIDs = $actor_phids;
     return $this;
   }
 
   public function withUserPHIDs(array $user_phids) {
     $this->userPHIDs = $user_phids;
     return $this;
   }
 
   public function withRelatedPHIDs(array $related_phids) {
     $this->relatedPHIDs = $related_phids;
     return $this;
   }
 
   public function withSessionKeys(array $session_keys) {
     $this->sessionKeys = $session_keys;
     return $this;
   }
 
   public function withActions(array $actions) {
     $this->actions = $actions;
     return $this;
   }
 
   public function withRemoteAddressPrefix($remote_address_prefix) {
     $this->remoteAddressPrefix = $remote_address_prefix;
     return $this;
   }
 
   public function withDateCreatedBetween($min, $max) {
     $this->dateCreatedMin = $min;
     $this->dateCreatedMax = $max;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorUserLog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->actorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'actorPHID IN (%Ls)',
         $this->actorPHIDs);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     if ($this->relatedPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         '(actorPHID IN (%Ls) OR userPHID IN (%Ls))',
         $this->relatedPHIDs,
         $this->relatedPHIDs);
     }
 
     if ($this->sessionKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'session IN (%Ls)',
         $this->sessionKeys);
     }
 
     if ($this->actions !== null) {
       $where[] = qsprintf(
         $conn,
         'action IN (%Ls)',
         $this->actions);
     }
 
     if ($this->remoteAddressPrefix !== null) {
       $where[] = qsprintf(
         $conn,
         'remoteAddr LIKE %>',
         $this->remoteAddressPrefix);
     }
 
     if ($this->dateCreatedMin !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCreated >= %d',
         $this->dateCreatedMin);
     }
 
     if ($this->dateCreatedMax !== null) {
       $where[] = qsprintf(
         $conn,
         'dateCreated <= %d',
         $this->dateCreatedMax);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPeopleApplication';
   }
 
 }
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
index e122be0b2e..b74b936ba8 100644
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -1,634 +1,630 @@
 <?php
 
 final class PhabricatorPeopleQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $usernames;
   private $realnames;
   private $emails;
   private $phids;
   private $ids;
   private $dateCreatedAfter;
   private $dateCreatedBefore;
   private $isAdmin;
   private $isSystemAgent;
   private $isMailingList;
   private $isDisabled;
   private $isApproved;
   private $nameLike;
   private $nameTokens;
   private $namePrefixes;
   private $isEnrolledInMultiFactor;
 
   private $needPrimaryEmail;
   private $needProfile;
   private $needProfileImage;
   private $needAvailability;
   private $needBadgeAwards;
   private $cacheKeys = array();
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withEmails(array $emails) {
     $this->emails = $emails;
     return $this;
   }
 
   public function withRealnames(array $realnames) {
     $this->realnames = $realnames;
     return $this;
   }
 
   public function withUsernames(array $usernames) {
     $this->usernames = $usernames;
     return $this;
   }
 
   public function withDateCreatedBefore($date_created_before) {
     $this->dateCreatedBefore = $date_created_before;
     return $this;
   }
 
   public function withDateCreatedAfter($date_created_after) {
     $this->dateCreatedAfter = $date_created_after;
     return $this;
   }
 
   public function withIsAdmin($admin) {
     $this->isAdmin = $admin;
     return $this;
   }
 
   public function withIsSystemAgent($system_agent) {
     $this->isSystemAgent = $system_agent;
     return $this;
   }
 
   public function withIsMailingList($mailing_list) {
     $this->isMailingList = $mailing_list;
     return $this;
   }
 
   public function withIsDisabled($disabled) {
     $this->isDisabled = $disabled;
     return $this;
   }
 
   public function withIsApproved($approved) {
     $this->isApproved = $approved;
     return $this;
   }
 
   public function withNameLike($like) {
     $this->nameLike = $like;
     return $this;
   }
 
   public function withNameTokens(array $tokens) {
     $this->nameTokens = array_values($tokens);
     return $this;
   }
 
   public function withNamePrefixes(array $prefixes) {
     $this->namePrefixes = $prefixes;
     return $this;
   }
 
   public function withIsEnrolledInMultiFactor($enrolled) {
     $this->isEnrolledInMultiFactor = $enrolled;
     return $this;
   }
 
   public function needPrimaryEmail($need) {
     $this->needPrimaryEmail = $need;
     return $this;
   }
 
   public function needProfile($need) {
     $this->needProfile = $need;
     return $this;
   }
 
   public function needProfileImage($need) {
     $cache_key = PhabricatorUserProfileImageCacheType::KEY_URI;
 
     if ($need) {
       $this->cacheKeys[$cache_key] = true;
     } else {
       unset($this->cacheKeys[$cache_key]);
     }
 
     return $this;
   }
 
   public function needAvailability($need) {
     $this->needAvailability = $need;
     return $this;
   }
 
   public function needUserSettings($need) {
     $cache_key = PhabricatorUserPreferencesCacheType::KEY_PREFERENCES;
 
     if ($need) {
       $this->cacheKeys[$cache_key] = true;
     } else {
       unset($this->cacheKeys[$cache_key]);
     }
 
     return $this;
   }
 
   public function needBadgeAwards($need) {
     $cache_key = PhabricatorUserBadgesCacheType::KEY_BADGES;
 
     if ($need) {
       $this->cacheKeys[$cache_key] = true;
     } else {
       unset($this->cacheKeys[$cache_key]);
     }
 
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorUser();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function didFilterPage(array $users) {
     if ($this->needProfile) {
       $user_list = mpull($users, null, 'getPHID');
       $profiles = new PhabricatorUserProfile();
       $profiles = $profiles->loadAllWhere(
         'userPHID IN (%Ls)',
         array_keys($user_list));
 
       $profiles = mpull($profiles, null, 'getUserPHID');
       foreach ($user_list as $user_phid => $user) {
         $profile = idx($profiles, $user_phid);
 
         if (!$profile) {
           $profile = PhabricatorUserProfile::initializeNewProfile($user);
         }
 
         $user->attachUserProfile($profile);
       }
     }
 
     if ($this->needAvailability) {
       $rebuild = array();
       foreach ($users as $user) {
         $cache = $user->getAvailabilityCache();
         if ($cache !== null) {
           $user->attachAvailability($cache);
         } else {
           $rebuild[] = $user;
         }
       }
 
       if ($rebuild) {
         $this->rebuildAvailabilityCache($rebuild);
       }
     }
 
     $this->fillUserCaches($users);
 
     return $users;
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->nameTokens) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->emails) {
       $email_table = new PhabricatorUserEmail();
       $joins[] = qsprintf(
         $conn,
         'JOIN %T email ON email.userPHID = user.PHID',
         $email_table->getTableName());
     }
 
     if ($this->nameTokens) {
       foreach ($this->nameTokens as $key => $token) {
         $token_table = 'token_'.$key;
         $joins[] = qsprintf(
           $conn,
           'JOIN %T %T ON %T.userID = user.id AND %T.token LIKE %>',
           PhabricatorUser::NAMETOKEN_TABLE,
           $token_table,
           $token_table,
           $token_table,
           $token);
       }
     }
 
     return  $joins;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->usernames !== null) {
       $where[] = qsprintf(
         $conn,
         'user.userName IN (%Ls)',
         $this->usernames);
     }
 
     if ($this->namePrefixes) {
       $parts = array();
       foreach ($this->namePrefixes as $name_prefix) {
         $parts[] = qsprintf(
           $conn,
           'user.username LIKE %>',
           $name_prefix);
       }
       $where[] = qsprintf($conn, '%LO', $parts);
     }
 
     if ($this->emails !== null) {
       $where[] = qsprintf(
         $conn,
         'email.address IN (%Ls)',
         $this->emails);
     }
 
     if ($this->realnames !== null) {
       $where[] = qsprintf(
         $conn,
         'user.realName IN (%Ls)',
         $this->realnames);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'user.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'user.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->dateCreatedAfter) {
       $where[] = qsprintf(
         $conn,
         'user.dateCreated >= %d',
         $this->dateCreatedAfter);
     }
 
     if ($this->dateCreatedBefore) {
       $where[] = qsprintf(
         $conn,
         'user.dateCreated <= %d',
         $this->dateCreatedBefore);
     }
 
     if ($this->isAdmin !== null) {
       $where[] = qsprintf(
         $conn,
         'user.isAdmin = %d',
         (int)$this->isAdmin);
     }
 
     if ($this->isDisabled !== null) {
       $where[] = qsprintf(
         $conn,
         'user.isDisabled = %d',
         (int)$this->isDisabled);
     }
 
     if ($this->isApproved !== null) {
       $where[] = qsprintf(
         $conn,
         'user.isApproved = %d',
         (int)$this->isApproved);
     }
 
     if ($this->isSystemAgent !== null) {
       $where[] = qsprintf(
         $conn,
         'user.isSystemAgent = %d',
         (int)$this->isSystemAgent);
     }
 
     if ($this->isMailingList !== null) {
       $where[] = qsprintf(
         $conn,
         'user.isMailingList = %d',
         (int)$this->isMailingList);
     }
 
     if ($this->nameLike !== null) {
       $where[] = qsprintf(
         $conn,
         'user.username LIKE %~ OR user.realname LIKE %~',
         $this->nameLike,
         $this->nameLike);
     }
 
     if ($this->isEnrolledInMultiFactor !== null) {
       $where[] = qsprintf(
         $conn,
         'user.isEnrolledInMultiFactor = %d',
         (int)$this->isEnrolledInMultiFactor);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'user';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPeopleApplication';
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'username' => array(
         'table' => 'user',
         'column' => 'username',
         'type' => 'string',
         'reverse' => true,
         'unique' => true,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'username' => $object->getUsername(),
     );
   }
 
   private function rebuildAvailabilityCache(array $rebuild) {
     $rebuild = mpull($rebuild, null, 'getPHID');
 
     // Limit the window we look at because far-future events are largely
     // irrelevant and this makes the cache cheaper to build and allows it to
     // self-heal over time.
     $min_range = PhabricatorTime::getNow();
     $max_range = $min_range + phutil_units('72 hours in seconds');
 
     // NOTE: We don't need to generate ghosts here, because we only care if
     // the user is attending, and you can't attend a ghost event: RSVP'ing
     // to it creates a real event.
 
     $events = id(new PhabricatorCalendarEventQuery())
       ->setViewer(PhabricatorUser::getOmnipotentUser())
       ->withInvitedPHIDs(array_keys($rebuild))
       ->withIsCancelled(false)
       ->withDateRange($min_range, $max_range)
       ->execute();
 
     // Group all the events by invited user. Only examine events that users
     // are actually attending.
     $map = array();
     $invitee_map = array();
     foreach ($events as $event) {
       foreach ($event->getInvitees() as $invitee) {
         if (!$invitee->isAttending()) {
           continue;
         }
 
         // If the user is set to "Available" for this event, don't consider it
         // when computing their away status.
         if (!$invitee->getDisplayAvailability($event)) {
           continue;
         }
 
         $invitee_phid = $invitee->getInviteePHID();
         if (!isset($rebuild[$invitee_phid])) {
           continue;
         }
 
         $map[$invitee_phid][] = $event;
 
         $event_phid = $event->getPHID();
         $invitee_map[$invitee_phid][$event_phid] = $invitee;
       }
     }
 
     // We need to load these users' timezone settings to figure out their
     // availability if they're attending all-day events.
     $this->needUserSettings(true);
     $this->fillUserCaches($rebuild);
 
     foreach ($rebuild as $phid => $user) {
       $events = idx($map, $phid, array());
 
       // We loaded events with the omnipotent user, but want to shift them
       // into the user's timezone before building the cache because they will
       // be unavailable during their own local day.
       foreach ($events as $event) {
         $event->applyViewerTimezone($user);
       }
 
       $cursor = $min_range;
       $next_event = null;
       if ($events) {
         // Find the next time when the user has no meetings. If we move forward
         // because of an event, we check again for events after that one ends.
         while (true) {
           foreach ($events as $event) {
             $from = $event->getStartDateTimeEpochForCache();
             $to = $event->getEndDateTimeEpochForCache();
             if (($from <= $cursor) && ($to > $cursor)) {
               $cursor = $to;
               if (!$next_event) {
                 $next_event = $event;
               }
               continue 2;
             }
           }
           break;
         }
       }
 
       if ($cursor > $min_range) {
         $invitee = $invitee_map[$phid][$next_event->getPHID()];
         $availability_type = $invitee->getDisplayAvailability($next_event);
         $availability = array(
           'until' => $cursor,
           'eventPHID' => $next_event->getPHID(),
           'availability' => $availability_type,
         );
 
         // We only cache this availability until the end of the current event,
         // since the event PHID (and possibly the availability type) are only
         // valid for that long.
 
         // NOTE: This doesn't handle overlapping events with the greatest
         // possible care. In theory, if you're attending multiple events
         // simultaneously we should accommodate that. However, it's complex
         // to compute, rare, and probably not confusing most of the time.
 
         $availability_ttl = $next_event->getEndDateTimeEpochForCache();
       } else {
         $availability = array(
           'until' => null,
           'eventPHID' => null,
           'availability' => null,
         );
 
         // Cache that the user is available until the next event they are
         // invited to starts.
         $availability_ttl = $max_range;
         foreach ($events as $event) {
           $from = $event->getStartDateTimeEpochForCache();
           if ($from > $cursor) {
             $availability_ttl = min($from, $availability_ttl);
           }
         }
       }
 
       // Never TTL the cache to longer than the maximum range we examined.
       $availability_ttl = min($availability_ttl, $max_range);
 
       $user->writeAvailabilityCache($availability, $availability_ttl);
       $user->attachAvailability($availability);
     }
   }
 
   private function fillUserCaches(array $users) {
     if (!$this->cacheKeys) {
       return;
     }
 
     $user_map = mpull($users, null, 'getPHID');
     $keys = array_keys($this->cacheKeys);
 
     $hashes = array();
     foreach ($keys as $key) {
       $hashes[] = PhabricatorHash::digestForIndex($key);
     }
 
     $types = PhabricatorUserCacheType::getAllCacheTypes();
 
     // First, pull any available caches. If we wanted to be particularly clever
     // we could do this with JOINs in the main query.
 
     $cache_table = new PhabricatorUserCache();
     $cache_conn = $cache_table->establishConnection('r');
 
     $cache_data = queryfx_all(
       $cache_conn,
       'SELECT cacheKey, userPHID, cacheData, cacheType FROM %T
         WHERE cacheIndex IN (%Ls) AND userPHID IN (%Ls)',
       $cache_table->getTableName(),
       $hashes,
       array_keys($user_map));
 
     $skip_validation = array();
 
     // After we read caches from the database, discard any which have data that
     // invalid or out of date. This allows cache types to implement TTLs or
     // versions instead of or in addition to explicit cache clears.
     foreach ($cache_data as $row_key => $row) {
       $cache_type = $row['cacheType'];
 
       if (isset($skip_validation[$cache_type])) {
         continue;
       }
 
       if (empty($types[$cache_type])) {
         unset($cache_data[$row_key]);
         continue;
       }
 
       $type = $types[$cache_type];
       if (!$type->shouldValidateRawCacheData()) {
         $skip_validation[$cache_type] = true;
         continue;
       }
 
       $user = $user_map[$row['userPHID']];
       $raw_data = $row['cacheData'];
       if (!$type->isRawCacheDataValid($user, $row['cacheKey'], $raw_data)) {
         unset($cache_data[$row_key]);
         continue;
       }
     }
 
     $need = array();
 
     $cache_data = igroup($cache_data, 'userPHID');
     foreach ($user_map as $user_phid => $user) {
       $raw_rows = idx($cache_data, $user_phid, array());
       $raw_data = ipull($raw_rows, 'cacheData', 'cacheKey');
 
       foreach ($keys as $key) {
         if (isset($raw_data[$key]) || array_key_exists($key, $raw_data)) {
           continue;
         }
         $need[$key][$user_phid] = $user;
       }
 
       $user->attachRawCacheData($raw_data);
     }
 
     // If we missed any cache values, bulk-construct them now. This is
     // usually much cheaper than generating them on-demand for each user
     // record.
 
     if (!$need) {
       return;
     }
 
     $writes = array();
     foreach ($need as $cache_key => $need_users) {
       $type = PhabricatorUserCacheType::getCacheTypeForKey($cache_key);
       if (!$type) {
         continue;
       }
 
       $data = $type->newValueForUsers($cache_key, $need_users);
 
       foreach ($data as $user_phid => $raw_value) {
         $data[$user_phid] = $raw_value;
         $writes[] = array(
           'userPHID' => $user_phid,
           'key' => $cache_key,
           'type' => $type,
           'value' => $raw_value,
         );
       }
 
       foreach ($need_users as $user_phid => $user) {
         if (isset($data[$user_phid]) || array_key_exists($user_phid, $data)) {
           $user->attachRawCacheData(
             array(
               $cache_key => $data[$user_phid],
             ));
         }
       }
     }
 
     PhabricatorUserCache::writeCaches($writes);
   }
 }
diff --git a/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php b/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php
index 6e2627a96d..ead44a56dc 100644
--- a/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php
@@ -1,81 +1,77 @@
 <?php
 
 final class PhabricatorPeopleUserEmailQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorUserEmail();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function getPrimaryTableAlias() {
     return 'email';
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'email.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'email.phid IN (%Ls)',
         $this->phids);
     }
 
     return $where;
   }
 
   protected function willLoadPage(array $page) {
 
     $user_phids = mpull($page, 'getUserPHID');
 
     $users = id(new PhabricatorPeopleQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($user_phids)
       ->execute();
     $users = mpull($users, null, 'getPHID');
 
     foreach ($page as $key => $address) {
       $user = idx($users, $address->getUserPHID());
 
       if (!$user) {
         unset($page[$key]);
         $this->didRejectResult($address);
         continue;
       }
 
       $address->attachUser($user);
     }
 
     return $page;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPeopleApplication';
   }
 
 }
diff --git a/src/applications/phame/query/PhameBlogQuery.php b/src/applications/phame/query/PhameBlogQuery.php
index b4018c78eb..b730f3c4aa 100644
--- a/src/applications/phame/query/PhameBlogQuery.php
+++ b/src/applications/phame/query/PhameBlogQuery.php
@@ -1,150 +1,146 @@
 <?php
 
 final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $domain;
   private $statuses;
 
   private $needBloggers;
   private $needProfileImage;
   private $needHeaderImage;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withDomain($domain) {
     $this->domain = $domain;
     return $this;
   }
 
   public function withStatuses(array $status) {
     $this->statuses = $status;
     return $this;
   }
 
   public function needProfileImage($need) {
     $this->needProfileImage = $need;
     return $this;
   }
 
   public function needHeaderImage($need) {
     $this->needHeaderImage = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new PhameBlog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'b.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'b.id IN (%Ls)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'b.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->domain !== null) {
       $where[] = qsprintf(
         $conn,
         'b.domain = %s',
         $this->domain);
     }
 
     return $where;
   }
 
   protected function didFilterPage(array $blogs) {
     if ($this->needProfileImage) {
       $default = null;
 
       $file_phids = mpull($blogs, 'getProfileImagePHID');
       $file_phids = array_filter($file_phids);
       if ($file_phids) {
         $files = id(new PhabricatorFileQuery())
           ->setParentQuery($this)
           ->setViewer($this->getViewer())
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
       } else {
         $files = array();
       }
 
       foreach ($blogs as $blog) {
         $file = idx($files, $blog->getProfileImagePHID());
         if (!$file) {
           if (!$default) {
             $default = PhabricatorFile::loadBuiltin(
               $this->getViewer(),
               'blog.png');
           }
           $file = $default;
         }
         $blog->attachProfileImageFile($file);
       }
     }
 
     if ($this->needHeaderImage) {
       $file_phids = mpull($blogs, 'getHeaderImagePHID');
       $file_phids = array_filter($file_phids);
       if ($file_phids) {
         $files = id(new PhabricatorFileQuery())
           ->setParentQuery($this)
           ->setViewer($this->getViewer())
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
       } else {
         $files = array();
       }
 
       foreach ($blogs as $blog) {
         $file = idx($files, $blog->getHeaderImagePHID());
         if ($file) {
           $blog->attachHeaderImageFile($file);
         }
       }
     }
     return $blogs;
   }
 
   public function getQueryApplicationClass() {
     // TODO: Can we set this without breaking public blogs?
     return null;
   }
 
   protected function getPrimaryTableAlias() {
     return 'b';
   }
 
 }
diff --git a/src/applications/phame/query/PhamePostQuery.php b/src/applications/phame/query/PhamePostQuery.php
index d7396e553f..61ee4f2a25 100644
--- a/src/applications/phame/query/PhamePostQuery.php
+++ b/src/applications/phame/query/PhamePostQuery.php
@@ -1,190 +1,186 @@
 <?php
 
 final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $blogPHIDs;
   private $bloggerPHIDs;
   private $visibility;
   private $publishedAfter;
   private $phids;
 
   private $needHeaderImage;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withBloggerPHIDs(array $blogger_phids) {
     $this->bloggerPHIDs = $blogger_phids;
     return $this;
   }
 
   public function withBlogPHIDs(array $blog_phids) {
     $this->blogPHIDs = $blog_phids;
     return $this;
   }
 
   public function withVisibility(array $visibility) {
     $this->visibility = $visibility;
     return $this;
   }
 
   public function withPublishedAfter($time) {
     $this->publishedAfter = $time;
     return $this;
   }
 
   public function needHeaderImage($need) {
     $this->needHeaderImage = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new PhamePost();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $posts) {
     // We require blogs to do visibility checks, so load them unconditionally.
     $blog_phids = mpull($posts, 'getBlogPHID');
 
     $blogs = id(new PhameBlogQuery())
       ->setViewer($this->getViewer())
       ->needProfileImage(true)
       ->withPHIDs($blog_phids)
       ->execute();
 
     $blogs = mpull($blogs, null, 'getPHID');
     foreach ($posts as $key => $post) {
       $blog_phid = $post->getBlogPHID();
 
       $blog = idx($blogs, $blog_phid);
       if (!$blog) {
         $this->didRejectResult($post);
         unset($posts[$key]);
         continue;
       }
 
       $post->attachBlog($blog);
     }
 
     if ($this->needHeaderImage) {
       $file_phids = mpull($posts, 'getHeaderImagePHID');
       $file_phids = array_filter($file_phids);
       if ($file_phids) {
         $files = id(new PhabricatorFileQuery())
           ->setParentQuery($this)
           ->setViewer($this->getViewer())
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
       } else {
         $files = array();
       }
 
       foreach ($posts as $post) {
         $file = idx($files, $post->getHeaderImagePHID());
         if ($file) {
           $post->attachHeaderImageFile($file);
         }
       }
     }
 
     return $posts;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->bloggerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'p.bloggerPHID IN (%Ls)',
         $this->bloggerPHIDs);
     }
 
     if ($this->visibility !== null) {
       $where[] = qsprintf(
         $conn,
         'p.visibility IN (%Ld)',
         $this->visibility);
     }
 
     if ($this->publishedAfter !== null) {
       $where[] = qsprintf(
         $conn,
         'p.datePublished > %d',
         $this->publishedAfter);
     }
 
     if ($this->blogPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'p.blogPHID in (%Ls)',
         $this->blogPHIDs);
     }
 
     return $where;
   }
 
   public function getBuiltinOrders() {
     return array(
       'datePublished' => array(
         'vector' => array('datePublished', 'id'),
         'name' => pht('Publish Date'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'datePublished' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'datePublished',
         'type' => 'int',
         'reverse' => false,
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'datePublished' => (int)$object->getDatePublished(),
     );
   }
 
   public function getQueryApplicationClass() {
     // TODO: Does setting this break public blogs?
     return null;
   }
 
   protected function getPrimaryTableAlias() {
     return 'p';
   }
 
 }
diff --git a/src/applications/pholio/query/PholioImageQuery.php b/src/applications/pholio/query/PholioImageQuery.php
index 0d64540f91..69d890ab98 100644
--- a/src/applications/pholio/query/PholioImageQuery.php
+++ b/src/applications/pholio/query/PholioImageQuery.php
@@ -1,162 +1,158 @@
 <?php
 
 final class PholioImageQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $mockPHIDs;
   private $mocks;
 
   private $needInlineComments;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withMocks(array $mocks) {
     assert_instances_of($mocks, 'PholioMock');
 
     $mocks = mpull($mocks, null, 'getPHID');
     $this->mocks = $mocks;
     $this->mockPHIDs = array_keys($mocks);
 
     return $this;
   }
 
   public function withMockPHIDs(array $mock_phids) {
     $this->mockPHIDs = $mock_phids;
     return $this;
   }
 
   public function needInlineComments($need_inline_comments) {
     $this->needInlineComments = $need_inline_comments;
     return $this;
   }
 
   public function newResultObject() {
     return new PholioImage();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->mockPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'mockPHID IN (%Ls)',
         $this->mockPHIDs);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $images) {
     assert_instances_of($images, 'PholioImage');
 
     $mock_phids = array();
     foreach ($images as $image) {
       if (!$image->hasMock()) {
         continue;
       }
 
       $mock_phids[] = $image->getMockPHID();
     }
 
     if ($mock_phids) {
       if ($this->mocks) {
         $mocks = $this->mocks;
       } else {
         $mocks = id(new PholioMockQuery())
           ->setViewer($this->getViewer())
           ->withPHIDs($mock_phids)
           ->execute();
       }
 
       $mocks = mpull($mocks, null, 'getPHID');
 
       foreach ($images as $key => $image) {
         if (!$image->hasMock()) {
           continue;
         }
 
         $mock = idx($mocks, $image->getMockPHID());
         if (!$mock) {
           unset($images[$key]);
           $this->didRejectResult($image);
           continue;
         }
 
         $image->attachMock($mock);
       }
     }
 
     return $images;
   }
 
   protected function didFilterPage(array $images) {
     assert_instances_of($images, 'PholioImage');
 
     $file_phids = mpull($images, 'getFilePHID');
 
     $all_files = id(new PhabricatorFileQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($file_phids)
       ->execute();
     $all_files = mpull($all_files, null, 'getPHID');
 
     if ($this->needInlineComments) {
       // Only load inline comments the viewer has permission to see.
       $all_inline_comments = id(new PholioTransactionComment())->loadAllWhere(
         'imageID IN (%Ld)
           AND (transactionPHID IS NOT NULL OR authorPHID = %s)',
         mpull($images, 'getID'),
         $this->getViewer()->getPHID());
       $all_inline_comments = mgroup($all_inline_comments, 'getImageID');
     }
 
     foreach ($images as $image) {
       $file = idx($all_files, $image->getFilePHID());
       if (!$file) {
         $file = PhabricatorFile::loadBuiltin($this->getViewer(), 'missing.png');
       }
       $image->attachFile($file);
       if ($this->needInlineComments) {
         $inlines = idx($all_inline_comments, $image->getID(), array());
         $image->attachInlineComments($inlines);
       }
     }
 
     return $images;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPholioApplication';
   }
 
 }
diff --git a/src/applications/phortune/query/PhortuneAccountEmailQuery.php b/src/applications/phortune/query/PhortuneAccountEmailQuery.php
index 0bdfdb78dc..0e0a668b8c 100644
--- a/src/applications/phortune/query/PhortuneAccountEmailQuery.php
+++ b/src/applications/phortune/query/PhortuneAccountEmailQuery.php
@@ -1,117 +1,113 @@
 <?php
 
 final class PhortuneAccountEmailQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $accountPHIDs;
   private $addressKeys;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAccountPHIDs(array $phids) {
     $this->accountPHIDs = $phids;
     return $this;
   }
 
   public function withAddressKeys(array $keys) {
     $this->addressKeys = $keys;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhortuneAccountEmail();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $addresses) {
     $accounts = id(new PhortuneAccountQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs(mpull($addresses, 'getAccountPHID'))
       ->execute();
     $accounts = mpull($accounts, null, 'getPHID');
 
     foreach ($addresses as $key => $address) {
       $account = idx($accounts, $address->getAccountPHID());
 
       if (!$account) {
         $this->didRejectResult($addresses[$key]);
         unset($addresses[$key]);
         continue;
       }
 
       $address->attachAccount($account);
     }
 
     return $addresses;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'address.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'address.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->accountPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'address.accountPHID IN (%Ls)',
         $this->accountPHIDs);
     }
 
     if ($this->addressKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'address.addressKey IN (%Ls)',
         $this->addressKeys);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'address.status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhortuneApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'address';
   }
 
 }
diff --git a/src/applications/phortune/query/PhortuneAccountQuery.php b/src/applications/phortune/query/PhortuneAccountQuery.php
index 70c12d9722..43c7c5f976 100644
--- a/src/applications/phortune/query/PhortuneAccountQuery.php
+++ b/src/applications/phortune/query/PhortuneAccountQuery.php
@@ -1,138 +1,134 @@
 <?php
 
 final class PhortuneAccountQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $memberPHIDs;
 
   public static function loadAccountsForUser(
     PhabricatorUser $user,
     PhabricatorContentSource $content_source) {
 
     $accounts = id(new PhortuneAccountQuery())
       ->setViewer($user)
       ->withMemberPHIDs(array($user->getPHID()))
       ->execute();
 
     if (!$accounts) {
       $accounts = array(
         PhortuneAccount::createNewAccount($user, $content_source),
       );
     }
 
     $accounts = mpull($accounts, null, 'getPHID');
 
     return $accounts;
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withMemberPHIDs(array $phids) {
     $this->memberPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhortuneAccount();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $accounts) {
     $query = id(new PhabricatorEdgeQuery())
       ->withSourcePHIDs(mpull($accounts, 'getPHID'))
       ->withEdgeTypes(
         array(
           PhortuneAccountHasMemberEdgeType::EDGECONST,
           PhortuneAccountHasMerchantEdgeType::EDGECONST,
         ));
 
     $query->execute();
 
     foreach ($accounts as $account) {
       $member_phids = $query->getDestinationPHIDs(
         array(
           $account->getPHID(),
         ),
         array(
           PhortuneAccountHasMemberEdgeType::EDGECONST,
         ));
       $member_phids = array_reverse($member_phids);
       $account->attachMemberPHIDs($member_phids);
 
       $merchant_phids = $query->getDestinationPHIDs(
         array(
           $account->getPHID(),
         ),
         array(
           PhortuneAccountHasMerchantEdgeType::EDGECONST,
         ));
       $merchant_phids = array_reverse($merchant_phids);
       $account->attachMerchantPHIDs($merchant_phids);
     }
 
     return $accounts;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'a.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'a.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->memberPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'm.dst IN (%Ls)',
         $this->memberPHIDs);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->memberPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'LEFT JOIN %T m ON a.phid = m.src AND m.type = %d',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         PhortuneAccountHasMemberEdgeType::EDGECONST);
     }
 
     return $joins;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhortuneApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'a';
   }
 
 }
diff --git a/src/applications/phortune/query/PhortuneMerchantQuery.php b/src/applications/phortune/query/PhortuneMerchantQuery.php
index aef7d8aaf1..2c9aefc74d 100644
--- a/src/applications/phortune/query/PhortuneMerchantQuery.php
+++ b/src/applications/phortune/query/PhortuneMerchantQuery.php
@@ -1,193 +1,189 @@
 <?php
 
 final class PhortuneMerchantQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $memberPHIDs;
   private $needProfileImage;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withMemberPHIDs(array $member_phids) {
     $this->memberPHIDs = $member_phids;
     return $this;
   }
 
   public function needProfileImage($need) {
     $this->needProfileImage = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new PhortuneMerchant();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $merchants) {
     $query = id(new PhabricatorEdgeQuery())
       ->withSourcePHIDs(mpull($merchants, 'getPHID'))
       ->withEdgeTypes(array(PhortuneMerchantHasMemberEdgeType::EDGECONST));
     $query->execute();
 
     foreach ($merchants as $merchant) {
       $member_phids = $query->getDestinationPHIDs(array($merchant->getPHID()));
       $member_phids = array_reverse($member_phids);
       $merchant->attachMemberPHIDs($member_phids);
     }
 
     if ($this->needProfileImage) {
       $default = null;
       $file_phids = mpull($merchants, 'getProfileImagePHID');
       $file_phids = array_filter($file_phids);
       if ($file_phids) {
         $files = id(new PhabricatorFileQuery())
           ->setParentQuery($this)
           ->setViewer($this->getViewer())
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
       } else {
         $files = array();
       }
 
       foreach ($merchants as $merchant) {
         $file = idx($files, $merchant->getProfileImagePHID());
         if (!$file) {
           if (!$default) {
             $default = PhabricatorFile::loadBuiltin(
               $this->getViewer(),
               'merchant.png');
           }
           $file = $default;
         }
         $merchant->attachProfileImageFile($file);
       }
     }
 
     return $merchants;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'merchant.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'merchant.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->memberPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'e.dst IN (%Ls)',
         $this->memberPHIDs);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->memberPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'LEFT JOIN %T e ON merchant.phid = e.src AND e.type = %d',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         PhortuneMerchantHasMemberEdgeType::EDGECONST);
     }
 
     return $joins;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhortuneApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'merchant';
   }
 
   public static function canViewersEditMerchants(
     array $viewer_phids,
     array $merchant_phids) {
 
     // See T13366 for some discussion. This is an unusual caching construct to
     // make policy filtering of Accounts easier.
 
     foreach ($viewer_phids as $key => $viewer_phid) {
       if (!$viewer_phid) {
         unset($viewer_phids[$key]);
       }
     }
 
     if (!$viewer_phids) {
       return array();
     }
 
     $cache_key = 'phortune.merchant.can-edit';
     $cache = PhabricatorCaches::getRequestCache();
 
     $cache_data = $cache->getKey($cache_key);
     if (!$cache_data) {
       $cache_data = array();
     }
 
     $load_phids = array();
     foreach ($viewer_phids as $viewer_phid) {
       if (!isset($cache_data[$viewer_phid])) {
         $load_phids[] = $viewer_phid;
       }
     }
 
     $did_write = false;
     foreach ($load_phids as $load_phid) {
       $merchants = id(new self())
         ->setViewer(PhabricatorUser::getOmnipotentUser())
         ->withMemberPHIDs(array($load_phid))
         ->execute();
       foreach ($merchants as $merchant) {
         $cache_data[$load_phid][$merchant->getPHID()] = true;
         $did_write = true;
       }
     }
 
     if ($did_write) {
       $cache->setKey($cache_key, $cache_data);
     }
 
     $results = array();
     foreach ($viewer_phids as $viewer_phid) {
       foreach ($merchant_phids as $merchant_phid) {
         if (!isset($cache_data[$viewer_phid][$merchant_phid])) {
           continue;
         }
         $results[$viewer_phid][$merchant_phid] = true;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/phortune/query/PhortunePaymentMethodQuery.php b/src/applications/phortune/query/PhortunePaymentMethodQuery.php
index 013fa147ec..b95881d3a7 100644
--- a/src/applications/phortune/query/PhortunePaymentMethodQuery.php
+++ b/src/applications/phortune/query/PhortunePaymentMethodQuery.php
@@ -1,150 +1,146 @@
 <?php
 
 final class PhortunePaymentMethodQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $accountPHIDs;
   private $merchantPHIDs;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAccountPHIDs(array $phids) {
     $this->accountPHIDs = $phids;
     return $this;
   }
 
   public function withMerchantPHIDs(array $phids) {
     $this->merchantPHIDs = $phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhortunePaymentMethod();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $methods) {
     $accounts = id(new PhortuneAccountQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs(mpull($methods, 'getAccountPHID'))
       ->execute();
     $accounts = mpull($accounts, null, 'getPHID');
 
     foreach ($methods as $key => $method) {
       $account = idx($accounts, $method->getAccountPHID());
       if (!$account) {
         unset($methods[$key]);
         $this->didRejectResult($method);
         continue;
       }
       $method->attachAccount($account);
     }
 
     if (!$methods) {
       return $methods;
     }
 
     $merchants = id(new PhortuneMerchantQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs(mpull($methods, 'getMerchantPHID'))
       ->execute();
     $merchants = mpull($merchants, null, 'getPHID');
 
     foreach ($methods as $key => $method) {
       $merchant = idx($merchants, $method->getMerchantPHID());
       if (!$merchant) {
         unset($methods[$key]);
         $this->didRejectResult($method);
         continue;
       }
       $method->attachMerchant($merchant);
     }
 
     if (!$methods) {
       return $methods;
     }
 
     $provider_configs = id(new PhortunePaymentProviderConfigQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs(mpull($methods, 'getProviderPHID'))
       ->execute();
     $provider_configs = mpull($provider_configs, null, 'getPHID');
 
     foreach ($methods as $key => $method) {
       $provider_config = idx($provider_configs, $method->getProviderPHID());
       if (!$provider_config) {
         unset($methods[$key]);
         $this->didRejectResult($method);
         continue;
       }
       $method->attachProviderConfig($provider_config);
     }
 
     return $methods;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->accountPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'accountPHID IN (%Ls)',
         $this->accountPHIDs);
     }
 
     if ($this->merchantPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'merchantPHID IN (%Ls)',
         $this->merchantPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhortuneApplication';
   }
 
 }
diff --git a/src/applications/phortune/query/PhortuneSubscriptionQuery.php b/src/applications/phortune/query/PhortuneSubscriptionQuery.php
index de0fee1980..5622578738 100644
--- a/src/applications/phortune/query/PhortuneSubscriptionQuery.php
+++ b/src/applications/phortune/query/PhortuneSubscriptionQuery.php
@@ -1,204 +1,200 @@
 <?php
 
 final class PhortuneSubscriptionQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $accountPHIDs;
   private $merchantPHIDs;
   private $statuses;
   private $paymentMethodPHIDs;
 
   private $needTriggers;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAccountPHIDs(array $account_phids) {
     $this->accountPHIDs = $account_phids;
     return $this;
   }
 
   public function withMerchantPHIDs(array $merchant_phids) {
     $this->merchantPHIDs = $merchant_phids;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withPaymentMethodPHIDs(array $method_phids) {
     $this->paymentMethodPHIDs = $method_phids;
     return $this;
   }
 
   public function needTriggers($need_triggers) {
     $this->needTriggers = $need_triggers;
     return $this;
   }
 
   public function newResultObject() {
     return new PhortuneSubscription();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $subscriptions) {
     $accounts = id(new PhortuneAccountQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs(mpull($subscriptions, 'getAccountPHID'))
       ->execute();
     $accounts = mpull($accounts, null, 'getPHID');
 
     foreach ($subscriptions as $key => $subscription) {
       $account = idx($accounts, $subscription->getAccountPHID());
       if (!$account) {
         unset($subscriptions[$key]);
         $this->didRejectResult($subscription);
         continue;
       }
       $subscription->attachAccount($account);
     }
 
     if (!$subscriptions) {
       return $subscriptions;
     }
 
     $merchants = id(new PhortuneMerchantQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs(mpull($subscriptions, 'getMerchantPHID'))
       ->execute();
     $merchants = mpull($merchants, null, 'getPHID');
 
     foreach ($subscriptions as $key => $subscription) {
       $merchant = idx($merchants, $subscription->getMerchantPHID());
       if (!$merchant) {
         unset($subscriptions[$key]);
         $this->didRejectResult($subscription);
         continue;
       }
       $subscription->attachMerchant($merchant);
     }
 
     if (!$subscriptions) {
       return $subscriptions;
     }
 
     $implementations = array();
 
     $subscription_map = mgroup($subscriptions, 'getSubscriptionClass');
     foreach ($subscription_map as $class => $class_subscriptions) {
       $sub = newv($class, array());
       $impl_objects = $sub->loadImplementationsForRefs(
         $this->getViewer(),
         mpull($class_subscriptions, 'getSubscriptionRef'));
 
       $implementations += mpull($impl_objects, null, 'getRef');
     }
 
     foreach ($subscriptions as $key => $subscription) {
       $ref = $subscription->getSubscriptionRef();
       $implementation = idx($implementations, $ref);
       if (!$implementation) {
         unset($subscriptions[$key]);
         $this->didRejectResult($subscription);
         continue;
       }
       $subscription->attachImplementation($implementation);
     }
 
     if (!$subscriptions) {
       return $subscriptions;
     }
 
     if ($this->needTriggers) {
       $trigger_phids = mpull($subscriptions, 'getTriggerPHID');
       $triggers = id(new PhabricatorWorkerTriggerQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($trigger_phids)
         ->needEvents(true)
         ->execute();
       $triggers = mpull($triggers, null, 'getPHID');
       foreach ($subscriptions as $key => $subscription) {
         $trigger = idx($triggers, $subscription->getTriggerPHID());
         if (!$trigger) {
           unset($subscriptions[$key]);
           $this->didRejectResult($subscription);
           continue;
         }
         $subscription->attachTrigger($trigger);
       }
     }
 
     return $subscriptions;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'subscription.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'subscription.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->accountPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'subscription.accountPHID IN (%Ls)',
         $this->accountPHIDs);
     }
 
     if ($this->merchantPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'subscription.merchantPHID IN (%Ls)',
         $this->merchantPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'subscription.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->paymentMethodPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'subscription.defaultPaymentMethodPHID IN (%Ls)',
         $this->paymentMethodPHIDs);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'subscription';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhortuneApplication';
   }
 
 }
diff --git a/src/applications/phriction/query/PhrictionContentQuery.php b/src/applications/phriction/query/PhrictionContentQuery.php
index 6efab5e1c6..8ac92be351 100644
--- a/src/applications/phriction/query/PhrictionContentQuery.php
+++ b/src/applications/phriction/query/PhrictionContentQuery.php
@@ -1,128 +1,124 @@
 <?php
 
 final class PhrictionContentQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $documentPHIDs;
   private $versions;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withDocumentPHIDs(array $phids) {
     $this->documentPHIDs = $phids;
     return $this;
   }
 
   public function withVersions(array $versions) {
     $this->versions = $versions;
     return $this;
   }
 
   public function newResultObject() {
     return new PhrictionContent();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'c.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'c.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->versions !== null) {
       $where[] = qsprintf(
         $conn,
         'version IN (%Ld)',
         $this->versions);
     }
 
     if ($this->documentPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'd.phid IN (%Ls)',
         $this->documentPHIDs);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinDocumentTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T d ON d.phid = c.documentPHID',
         id(new PhrictionDocument())->getTableName());
     }
 
     return $joins;
   }
 
   protected function willFilterPage(array $contents) {
     $document_phids = mpull($contents, 'getDocumentPHID');
 
     $documents = id(new PhrictionDocumentQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($document_phids)
       ->execute();
     $documents = mpull($documents, null, 'getPHID');
 
     foreach ($contents as $key => $content) {
       $document_phid = $content->getDocumentPHID();
 
       $document = idx($documents, $document_phid);
       if (!$document) {
         unset($contents[$key]);
         $this->didRejectResult($content);
         continue;
       }
 
       $content->attachDocument($document);
     }
 
     return $contents;
   }
 
   private function shouldJoinDocumentTable() {
     if ($this->documentPHIDs !== null) {
       return true;
     }
 
     return false;
   }
 
   protected function getPrimaryTableAlias() {
     return 'c';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhrictionApplication';
   }
 
 }
diff --git a/src/applications/phriction/query/PhrictionDocumentQuery.php b/src/applications/phriction/query/PhrictionDocumentQuery.php
index e7b5a0529e..298db97dbb 100644
--- a/src/applications/phriction/query/PhrictionDocumentQuery.php
+++ b/src/applications/phriction/query/PhrictionDocumentQuery.php
@@ -1,402 +1,398 @@
 <?php
 
 final class PhrictionDocumentQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $slugs;
   private $depths;
   private $slugPrefix;
   private $statuses;
 
   private $parentPaths;
   private $ancestorPaths;
 
   private $needContent;
 
   const ORDER_HIERARCHY = 'hierarchy';
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withSlugs(array $slugs) {
     $this->slugs = $slugs;
     return $this;
   }
 
   public function withDepths(array $depths) {
     $this->depths = $depths;
     return $this;
   }
 
   public function withSlugPrefix($slug_prefix) {
     $this->slugPrefix = $slug_prefix;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withParentPaths(array $paths) {
     $this->parentPaths = $paths;
     return $this;
   }
 
   public function withAncestorPaths(array $paths) {
     $this->ancestorPaths = $paths;
     return $this;
   }
 
   public function needContent($need_content) {
     $this->needContent = $need_content;
     return $this;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   public function newResultObject() {
     return new PhrictionDocument();
   }
 
   protected function willFilterPage(array $documents) {
 
     if ($documents) {
       $ancestor_slugs = array();
       foreach ($documents as $key => $document) {
         $document_slug = $document->getSlug();
         foreach (PhabricatorSlug::getAncestry($document_slug) as $ancestor) {
           $ancestor_slugs[$ancestor][] = $key;
         }
       }
 
       if ($ancestor_slugs) {
         $table = new PhrictionDocument();
         $conn_r = $table->establishConnection('r');
         $ancestors = queryfx_all(
           $conn_r,
           'SELECT * FROM %T WHERE slug IN (%Ls)',
           $document->getTableName(),
           array_keys($ancestor_slugs));
         $ancestors = $table->loadAllFromArray($ancestors);
         $ancestors = mpull($ancestors, null, 'getSlug');
 
         foreach ($ancestor_slugs as $ancestor_slug => $document_keys) {
           $ancestor = idx($ancestors, $ancestor_slug);
           foreach ($document_keys as $document_key) {
             $documents[$document_key]->attachAncestor(
               $ancestor_slug,
               $ancestor);
           }
         }
       }
     }
     // To view a Phriction document, you must also be able to view all of the
     // ancestor documents. Filter out documents which have ancestors that are
     // not visible.
 
     $document_map = array();
     foreach ($documents as $document) {
       $document_map[$document->getSlug()] = $document;
       foreach ($document->getAncestors() as $key => $ancestor) {
         if ($ancestor) {
           $document_map[$key] = $ancestor;
         }
       }
     }
 
     $filtered_map = $this->applyPolicyFilter(
       $document_map,
       array(PhabricatorPolicyCapability::CAN_VIEW));
 
     // Filter all of the documents where a parent is not visible.
     foreach ($documents as $document_key => $document) {
       // If the document itself is not visible, filter it.
       if (!isset($filtered_map[$document->getSlug()])) {
         $this->didRejectResult($documents[$document_key]);
         unset($documents[$document_key]);
         continue;
       }
 
       // If an ancestor exists but is not visible, filter the document.
       foreach ($document->getAncestors() as $ancestor_key => $ancestor) {
         if (!$ancestor) {
           continue;
         }
 
         if (!isset($filtered_map[$ancestor_key])) {
           $this->didRejectResult($documents[$document_key]);
           unset($documents[$document_key]);
           break;
         }
       }
     }
 
     if (!$documents) {
       return $documents;
     }
 
     if ($this->needContent) {
       $contents = id(new PhrictionContentQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs(mpull($documents, 'getContentPHID'))
         ->execute();
       $contents = mpull($contents, null, 'getPHID');
 
       foreach ($documents as $key => $document) {
         $content_phid = $document->getContentPHID();
         if (empty($contents[$content_phid])) {
           unset($documents[$key]);
           continue;
         }
         $document->attachContent($contents[$content_phid]);
       }
     }
 
     return $documents;
   }
 
   protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) {
     $select = parent::buildSelectClauseParts($conn);
 
     if ($this->shouldJoinContentTable()) {
       $select[] = qsprintf($conn, 'c.title');
     }
 
     return $select;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinContentTable()) {
       $content_dao = new PhrictionContent();
       $joins[] = qsprintf(
         $conn,
         'JOIN %T c ON d.contentPHID = c.phid',
         $content_dao->getTableName());
     }
 
     return $joins;
   }
 
   private function shouldJoinContentTable() {
     if ($this->getOrderVector()->containsKey('title')) {
       return true;
     }
 
     return false;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'd.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'd.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->slugs !== null) {
       $where[] = qsprintf(
         $conn,
         'd.slug IN (%Ls)',
         $this->slugs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'd.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->slugPrefix !== null) {
       $where[] = qsprintf(
         $conn,
         'd.slug LIKE %>',
         $this->slugPrefix);
     }
 
     if ($this->depths !== null) {
       $where[] = qsprintf(
         $conn,
         'd.depth IN (%Ld)',
         $this->depths);
     }
 
     if ($this->parentPaths !== null || $this->ancestorPaths !== null) {
       $sets = array(
         array(
           'paths' => $this->parentPaths,
           'parents' => true,
         ),
         array(
           'paths' => $this->ancestorPaths,
           'parents' => false,
         ),
       );
 
       $paths = array();
       foreach ($sets as $set) {
         $set_paths = $set['paths'];
         if ($set_paths === null) {
           continue;
         }
 
         if (!$set_paths) {
           throw new PhabricatorEmptyQueryException(
             pht('No parent/ancestor paths specified.'));
         }
 
         $is_parents = $set['parents'];
         foreach ($set_paths as $path) {
           $path_normal = PhabricatorSlug::normalize($path);
           if ($path !== $path_normal) {
             throw new Exception(
               pht(
                 'Document path "%s" is not a valid path. The normalized '.
                 'form of this path is "%s".',
                 $path,
                 $path_normal));
           }
 
           $depth = PhabricatorSlug::getDepth($path_normal);
           if ($is_parents) {
             $min_depth = $depth + 1;
             $max_depth = $depth + 1;
           } else {
             $min_depth = $depth + 1;
             $max_depth = null;
           }
 
           $paths[] = array(
             $path_normal,
             $min_depth,
             $max_depth,
           );
         }
       }
 
       $path_clauses = array();
       foreach ($paths as $path) {
         $parts = array();
         list($prefix, $min, $max) = $path;
 
         // If we're getting children or ancestors of the root document, they
         // aren't actually stored with the leading "/" in the database, so
         // just skip this part of the clause.
         if ($prefix !== '/') {
           $parts[] = qsprintf(
             $conn,
             'd.slug LIKE %>',
             $prefix);
         }
 
         if ($min !== null) {
           $parts[] = qsprintf(
             $conn,
             'd.depth >= %d',
             $min);
         }
 
         if ($max !== null) {
           $parts[] = qsprintf(
             $conn,
             'd.depth <= %d',
             $max);
         }
 
         if ($parts) {
           $path_clauses[] = qsprintf($conn, '%LA', $parts);
         }
       }
 
       if ($path_clauses) {
         $where[] = qsprintf($conn, '%LO', $path_clauses);
       }
     }
 
     return $where;
   }
 
   public function getBuiltinOrders() {
     return parent::getBuiltinOrders() + array(
       self::ORDER_HIERARCHY => array(
         'vector' => array('depth', 'title', 'updated', 'id'),
         'name' => pht('Hierarchy'),
       ),
     );
   }
 
   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' => 'editedEpoch',
         'type' => 'int',
         'unique' => false,
       ),
     );
   }
 
   protected function newPagingMapFromCursorObject(
     PhabricatorQueryCursor $cursor,
     array $keys) {
 
     $document = $cursor->getObject();
 
     $map = array(
       'id' => (int)$document->getID(),
       'depth' => $document->getDepth(),
       'updated' => (int)$document->getEditedEpoch(),
     );
 
     if (isset($keys['title'])) {
       $map['title'] = $cursor->getRawRowProperty('title');
     }
 
     return $map;
   }
 
   protected function getPrimaryTableAlias() {
     return 'd';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhrictionApplication';
   }
 
 }
diff --git a/src/applications/phurl/query/PhabricatorPhurlURLQuery.php b/src/applications/phurl/query/PhabricatorPhurlURLQuery.php
index 6efbbd5b4c..c30cedf09d 100644
--- a/src/applications/phurl/query/PhabricatorPhurlURLQuery.php
+++ b/src/applications/phurl/query/PhabricatorPhurlURLQuery.php
@@ -1,112 +1,108 @@
 <?php
 
 final class PhabricatorPhurlURLQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $names;
   private $longURLs;
   private $aliases;
   private $authorPHIDs;
 
   public function newResultObject() {
     return new PhabricatorPhurlURL();
   }
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNameNgrams($ngrams) {
     return $this->withNgramsConstraint(
       id(new PhabricatorPhurlURLNameNgrams()),
       $ngrams);
   }
 
   public function withLongURLs(array $long_urls) {
     $this->longURLs = $long_urls;
     return $this;
   }
 
   public function withAliases(array $aliases) {
     $this->aliases = $aliases;
     return $this;
   }
 
   public function withAuthorPHIDs(array $author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'url.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'url.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'url.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->names !== null) {
       $where[] = qsprintf(
         $conn,
         'url.name IN (%Ls)',
         $this->names);
     }
 
     if ($this->longURLs !== null) {
       $where[] = qsprintf(
         $conn,
         'url.longURL IN (%Ls)',
         $this->longURLs);
     }
 
     if ($this->aliases !== null) {
       $where[] = qsprintf(
         $conn,
         'url.alias IN (%Ls)',
         $this->aliases);
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'url';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPhurlApplication';
   }
 }
diff --git a/src/applications/ponder/query/PonderAnswerQuery.php b/src/applications/ponder/query/PonderAnswerQuery.php
index 2901f4d6a5..f100f05ae3 100644
--- a/src/applications/ponder/query/PonderAnswerQuery.php
+++ b/src/applications/ponder/query/PonderAnswerQuery.php
@@ -1,88 +1,84 @@
 <?php
 
 final class PonderAnswerQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $questionIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function withQuestionIDs(array $ids) {
     $this->questionIDs = $ids;
     return $this;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     return $where;
   }
 
   public function newResultObject() {
     return new PonderAnswer();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage(new PonderAnswer());
-  }
-
   protected function willFilterPage(array $answers) {
     $questions = id(new PonderQuestionQuery())
       ->setViewer($this->getViewer())
       ->withIDs(mpull($answers, 'getQuestionID'))
       ->execute();
 
     foreach ($answers as $key => $answer) {
       $question = idx($questions, $answer->getQuestionID());
       if (!$question) {
         unset($answers[$key]);
         continue;
       }
       $answer->attachQuestion($question);
     }
 
     return $answers;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPonderApplication';
   }
 
 }
diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php
index b2de14e52c..323f34aac5 100644
--- a/src/applications/ponder/query/PonderQuestionQuery.php
+++ b/src/applications/ponder/query/PonderQuestionQuery.php
@@ -1,154 +1,150 @@
 <?php
 
 final class PonderQuestionQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $status;
   private $authorPHIDs;
   private $answererPHIDs;
 
   private $needProjectPHIDs;
 
   private $needAnswers;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function withStatuses($status) {
     $this->status = $status;
     return $this;
   }
 
   public function withAnswererPHIDs(array $phids) {
     $this->answererPHIDs = $phids;
     return $this;
   }
 
   public function needAnswers($need_answers) {
     $this->needAnswers = $need_answers;
     return $this;
   }
 
   public function needProjectPHIDs($need_projects) {
     $this->needProjectPHIDs = $need_projects;
     return $this;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'q.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'q.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'q.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->status !== null) {
       $where[] = qsprintf(
         $conn,
         'q.status IN (%Ls)',
         $this->status);
     }
 
     return $where;
   }
 
   public function newResultObject() {
     return new PonderQuestion();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage(new PonderQuestion());
-  }
-
   protected function willFilterPage(array $questions) {
 
     $phids = mpull($questions, 'getPHID');
 
     if ($this->needAnswers) {
       $aquery = id(new PonderAnswerQuery())
         ->setViewer($this->getViewer())
         ->setOrderVector(array('-id'))
         ->withQuestionIDs(mpull($questions, 'getID'));
 
       $answers = $aquery->execute();
       $answers = mgroup($answers, 'getQuestionID');
 
       foreach ($questions as $question) {
         $question_answers = idx($answers, $question->getID(), array());
         $question->attachAnswers(mpull($question_answers, null, 'getPHID'));
       }
     }
 
     if ($this->needProjectPHIDs) {
       $edge_query = id(new PhabricatorEdgeQuery())
         ->withSourcePHIDs($phids)
         ->withEdgeTypes(
           array(
             PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
           ));
       $edge_query->execute();
 
       foreach ($questions as $question) {
         $project_phids = $edge_query->getDestinationPHIDs(
           array($question->getPHID()));
         $question->attachProjectPHIDs($project_phids);
       }
     }
 
     return $questions;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->answererPHIDs) {
       $answer_table = new PonderAnswer();
       $joins[] = qsprintf(
         $conn,
         'JOIN %T a ON a.questionID = q.id AND a.authorPHID IN (%Ls)',
         $answer_table->getTableName(),
         $this->answererPHIDs);
     }
 
     return $joins;
   }
 
   protected function getPrimaryTableAlias() {
     return 'q';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorPonderApplication';
   }
 
 }
diff --git a/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php b/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
index 438c558e6e..2673902780 100644
--- a/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
@@ -1,77 +1,73 @@
 <?php
 
 final class PhabricatorProjectColumnPositionQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $boardPHIDs;
   private $objectPHIDs;
   private $columnPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withBoardPHIDs(array $board_phids) {
     $this->boardPHIDs = $board_phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withColumnPHIDs(array $column_phids) {
     $this->columnPHIDs = $column_phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorProjectColumnPosition();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = array();
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->boardPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'boardPHID IN (%Ls)',
         $this->boardPHIDs);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->columnPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'columnPHID IN (%Ls)',
         $this->columnPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorProjectApplication';
   }
 
 }
diff --git a/src/applications/project/query/PhabricatorProjectColumnQuery.php b/src/applications/project/query/PhabricatorProjectColumnQuery.php
index 380dab5208..478d872cb4 100644
--- a/src/applications/project/query/PhabricatorProjectColumnQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnQuery.php
@@ -1,235 +1,231 @@
 <?php
 
 final class PhabricatorProjectColumnQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $projectPHIDs;
   private $proxyPHIDs;
   private $statuses;
   private $isProxyColumn;
   private $triggerPHIDs;
   private $needTriggers;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withProjectPHIDs(array $project_phids) {
     $this->projectPHIDs = $project_phids;
     return $this;
   }
 
   public function withProxyPHIDs(array $proxy_phids) {
     $this->proxyPHIDs = $proxy_phids;
     return $this;
   }
 
   public function withStatuses(array $status) {
     $this->statuses = $status;
     return $this;
   }
 
   public function withIsProxyColumn($is_proxy) {
     $this->isProxyColumn = $is_proxy;
     return $this;
   }
 
   public function withTriggerPHIDs(array $trigger_phids) {
     $this->triggerPHIDs = $trigger_phids;
     return $this;
   }
 
   public function needTriggers($need_triggers) {
     $this->needTriggers = true;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorProjectColumn();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $projects = array();
 
     $project_phids = array_filter(mpull($page, 'getProjectPHID'));
     if ($project_phids) {
       $projects = id(new PhabricatorProjectQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($project_phids)
         ->execute();
       $projects = mpull($projects, null, 'getPHID');
     }
 
     foreach ($page as $key => $column) {
       $phid = $column->getProjectPHID();
       $project = idx($projects, $phid);
       if (!$project) {
         $this->didRejectResult($page[$key]);
         unset($page[$key]);
         continue;
       }
       $column->attachProject($project);
     }
 
     $proxy_phids = array_filter(mpull($page, 'getProjectPHID'));
 
     return $page;
   }
 
   protected function didFilterPage(array $page) {
     $proxy_phids = array();
     foreach ($page as $column) {
       $proxy_phid = $column->getProxyPHID();
       if ($proxy_phid !== null) {
         $proxy_phids[$proxy_phid] = $proxy_phid;
       }
     }
 
     if ($proxy_phids) {
       $proxies = id(new PhabricatorObjectQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPHIDs($proxy_phids)
         ->execute();
       $proxies = mpull($proxies, null, 'getPHID');
     } else {
       $proxies = array();
     }
 
     foreach ($page as $key => $column) {
       $proxy_phid = $column->getProxyPHID();
 
       if ($proxy_phid !== null) {
         $proxy = idx($proxies, $proxy_phid);
 
         // Only attach valid proxies, so we don't end up getting surprised if
         // an install somehow gets junk into their database.
         if (!($proxy instanceof PhabricatorColumnProxyInterface)) {
           $proxy = null;
         }
 
         if (!$proxy) {
           $this->didRejectResult($column);
           unset($page[$key]);
           continue;
         }
       } else {
         $proxy = null;
       }
 
       $column->attachProxy($proxy);
     }
 
     if ($this->needTriggers) {
       $trigger_phids = array();
       foreach ($page as $column) {
         if ($column->canHaveTrigger()) {
           $trigger_phid = $column->getTriggerPHID();
           if ($trigger_phid) {
             $trigger_phids[] = $trigger_phid;
           }
         }
       }
 
       if ($trigger_phids) {
         $triggers = id(new PhabricatorProjectTriggerQuery())
           ->setViewer($this->getViewer())
           ->setParentQuery($this)
           ->withPHIDs($trigger_phids)
           ->execute();
         $triggers = mpull($triggers, null, 'getPHID');
       } else {
         $triggers = array();
       }
 
       foreach ($page as $column) {
         $trigger = null;
 
         if ($column->canHaveTrigger()) {
           $trigger_phid = $column->getTriggerPHID();
           if ($trigger_phid) {
             $trigger = idx($triggers, $trigger_phid);
           }
         }
 
         $column->attachTrigger($trigger);
       }
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->projectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'projectPHID IN (%Ls)',
         $this->projectPHIDs);
     }
 
     if ($this->proxyPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'proxyPHID IN (%Ls)',
         $this->proxyPHIDs);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ld)',
         $this->statuses);
     }
 
     if ($this->triggerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'triggerPHID IN (%Ls)',
         $this->triggerPHIDs);
     }
 
     if ($this->isProxyColumn !== null) {
       if ($this->isProxyColumn) {
         $where[] = qsprintf($conn, 'proxyPHID IS NOT NULL');
       } else {
         $where[] = qsprintf($conn, 'proxyPHID IS NULL');
       }
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorProjectApplication';
   }
 
 }
diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
index 22e0b59c94..b02fa647a2 100644
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -1,901 +1,897 @@
 <?php
 
 final class PhabricatorProjectQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $memberPHIDs;
   private $watcherPHIDs;
   private $slugs;
   private $slugNormals;
   private $slugMap;
   private $allSlugs;
   private $names;
   private $namePrefixes;
   private $nameTokens;
   private $icons;
   private $colors;
   private $ancestorPHIDs;
   private $parentPHIDs;
   private $isMilestone;
   private $hasSubprojects;
   private $minDepth;
   private $maxDepth;
   private $minMilestoneNumber;
   private $maxMilestoneNumber;
   private $subtypes;
 
   private $status       = 'status-any';
   const STATUS_ANY      = 'status-any';
   const STATUS_OPEN     = 'status-open';
   const STATUS_CLOSED   = 'status-closed';
   const STATUS_ACTIVE   = 'status-active';
   const STATUS_ARCHIVED = 'status-archived';
   private $statuses;
 
   private $needSlugs;
   private $needMembers;
   private $needAncestorMembers;
   private $needWatchers;
   private $needImages;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withStatus($status) {
     $this->status = $status;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function withMemberPHIDs(array $member_phids) {
     $this->memberPHIDs = $member_phids;
     return $this;
   }
 
   public function withWatcherPHIDs(array $watcher_phids) {
     $this->watcherPHIDs = $watcher_phids;
     return $this;
   }
 
   public function withSlugs(array $slugs) {
     $this->slugs = $slugs;
     return $this;
   }
 
   public function withNames(array $names) {
     $this->names = $names;
     return $this;
   }
 
   public function withNamePrefixes(array $prefixes) {
     $this->namePrefixes = $prefixes;
     return $this;
   }
 
   public function withNameTokens(array $tokens) {
     $this->nameTokens = array_values($tokens);
     return $this;
   }
 
   public function withIcons(array $icons) {
     $this->icons = $icons;
     return $this;
   }
 
   public function withColors(array $colors) {
     $this->colors = $colors;
     return $this;
   }
 
   public function withParentProjectPHIDs($parent_phids) {
     $this->parentPHIDs = $parent_phids;
     return $this;
   }
 
   public function withAncestorProjectPHIDs($ancestor_phids) {
     $this->ancestorPHIDs = $ancestor_phids;
     return $this;
   }
 
   public function withIsMilestone($is_milestone) {
     $this->isMilestone = $is_milestone;
     return $this;
   }
 
   public function withHasSubprojects($has_subprojects) {
     $this->hasSubprojects = $has_subprojects;
     return $this;
   }
 
   public function withDepthBetween($min, $max) {
     $this->minDepth = $min;
     $this->maxDepth = $max;
     return $this;
   }
 
   public function withMilestoneNumberBetween($min, $max) {
     $this->minMilestoneNumber = $min;
     $this->maxMilestoneNumber = $max;
     return $this;
   }
 
   public function withSubtypes(array $subtypes) {
     $this->subtypes = $subtypes;
     return $this;
   }
 
   public function needMembers($need_members) {
     $this->needMembers = $need_members;
     return $this;
   }
 
   public function needAncestorMembers($need_ancestor_members) {
     $this->needAncestorMembers = $need_ancestor_members;
     return $this;
   }
 
   public function needWatchers($need_watchers) {
     $this->needWatchers = $need_watchers;
     return $this;
   }
 
   public function needImages($need_images) {
     $this->needImages = $need_images;
     return $this;
   }
 
   public function needSlugs($need_slugs) {
     $this->needSlugs = $need_slugs;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorProject();
   }
 
   protected function getDefaultOrderVector() {
     return array('name');
   }
 
   public function getBuiltinOrders() {
     return array(
       'name' => array(
         'vector' => array('name'),
         'name' => pht('Name'),
       ),
     ) + parent::getBuiltinOrders();
   }
 
   public function getOrderableColumns() {
     return parent::getOrderableColumns() + array(
       'name' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'name',
         'reverse' => true,
         'type' => 'string',
         'unique' => true,
       ),
       'milestoneNumber' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'milestoneNumber',
         'type' => 'int',
       ),
       'status' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'status',
         'type' => 'int',
       ),
     );
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
       'name' => $object->getName(),
       'status' => $object->getStatus(),
     );
   }
 
   public function getSlugMap() {
     if ($this->slugMap === null) {
       throw new PhutilInvalidStateException('execute');
     }
     return $this->slugMap;
   }
 
   protected function willExecute() {
     $this->slugMap = array();
     $this->slugNormals = array();
     $this->allSlugs = array();
     if ($this->slugs) {
       foreach ($this->slugs as $slug) {
         if (PhabricatorSlug::isValidProjectSlug($slug)) {
           $normal = PhabricatorSlug::normalizeProjectSlug($slug);
           $this->slugNormals[$slug] = $normal;
           $this->allSlugs[$normal] = $normal;
         }
 
         // NOTE: At least for now, we query for the normalized slugs but also
         // for the slugs exactly as entered. This allows older projects with
         // slugs that are no longer valid to continue to work.
         $this->allSlugs[$slug] = $slug;
       }
     }
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $projects) {
     $ancestor_paths = array();
     foreach ($projects as $project) {
       foreach ($project->getAncestorProjectPaths() as $path) {
         $ancestor_paths[$path] = $path;
       }
     }
 
     if ($ancestor_paths) {
       $ancestors = id(new PhabricatorProject())->loadAllWhere(
         'projectPath IN (%Ls)',
         $ancestor_paths);
     } else {
       $ancestors = array();
     }
 
     $projects = $this->linkProjectGraph($projects, $ancestors);
 
     $viewer_phid = $this->getViewer()->getPHID();
 
     $material_type = PhabricatorProjectMaterializedMemberEdgeType::EDGECONST;
     $watcher_type = PhabricatorObjectHasWatcherEdgeType::EDGECONST;
 
     $types = array();
     $types[] = $material_type;
     if ($this->needWatchers) {
       $types[] = $watcher_type;
     }
 
     $all_graph = $this->getAllReachableAncestors($projects);
 
     // See T13484. If the graph is damaged (and contains a cycle or an edge
     // pointing at a project which has been destroyed), some of the nodes we
     // started with may be filtered out by reachability tests. If any of the
     // projects we are linking up don't have available ancestors, filter them
     // out.
 
     foreach ($projects as $key => $project) {
       $project_phid = $project->getPHID();
       if (!isset($all_graph[$project_phid])) {
         $this->didRejectResult($project);
         unset($projects[$key]);
         continue;
       }
     }
 
     if (!$projects) {
       return array();
     }
 
     // NOTE: Although we may not need much information about ancestors, we
     // always need to test if the viewer is a member, because we will return
     // ancestor projects to the policy filter via ExtendedPolicy calls. If
     // we skip populating membership data on a parent, the policy framework
     // will think the user is not a member of the parent project.
 
     $all_sources = array();
     foreach ($all_graph as $project) {
       // For milestones, we need parent members.
       if ($project->isMilestone()) {
         $parent_phid = $project->getParentProjectPHID();
         $all_sources[$parent_phid] = $parent_phid;
       }
 
       $phid = $project->getPHID();
       $all_sources[$phid] = $phid;
     }
 
     $edge_query = id(new PhabricatorEdgeQuery())
       ->withSourcePHIDs($all_sources)
       ->withEdgeTypes($types);
 
     $need_all_edges =
       $this->needMembers ||
       $this->needWatchers ||
       $this->needAncestorMembers;
 
     // If we only need to know if the viewer is a member, we can restrict
     // the query to just their PHID.
     $any_edges = true;
     if (!$need_all_edges) {
       if ($viewer_phid) {
         $edge_query->withDestinationPHIDs(array($viewer_phid));
       } else {
         // If we don't need members or watchers and don't have a viewer PHID
         // (viewer is logged-out or omnipotent), they'll never be a member
         // so we don't need to issue this query at all.
         $any_edges = false;
       }
     }
 
     if ($any_edges) {
       $edge_query->execute();
     }
 
     $membership_projects = array();
     foreach ($all_graph as $project) {
       $project_phid = $project->getPHID();
 
       if ($project->isMilestone()) {
         $source_phids = array($project->getParentProjectPHID());
       } else {
         $source_phids = array($project_phid);
       }
 
       if ($any_edges) {
         $member_phids = $edge_query->getDestinationPHIDs(
           $source_phids,
           array($material_type));
       } else {
         $member_phids = array();
       }
 
       if (in_array($viewer_phid, $member_phids)) {
         $membership_projects[$project_phid] = $project;
       }
 
       if ($this->needMembers || $this->needAncestorMembers) {
         $project->attachMemberPHIDs($member_phids);
       }
 
       if ($this->needWatchers) {
         $watcher_phids = $edge_query->getDestinationPHIDs(
           array($project_phid),
           array($watcher_type));
         $project->attachWatcherPHIDs($watcher_phids);
         $project->setIsUserWatcher(
           $viewer_phid,
           in_array($viewer_phid, $watcher_phids));
       }
     }
 
     // If we loaded ancestor members, we've already populated membership
     // lists above, so we can skip this step.
     if (!$this->needAncestorMembers) {
       $member_graph = $this->getAllReachableAncestors($membership_projects);
 
       foreach ($all_graph as $phid => $project) {
         $is_member = isset($member_graph[$phid]);
         $project->setIsUserMember($viewer_phid, $is_member);
       }
     }
 
     return $projects;
   }
 
   protected function didFilterPage(array $projects) {
     $viewer = $this->getViewer();
 
     if ($this->needImages) {
       $need_images = $projects;
 
       // First, try to load custom profile images for any projects with custom
       // images.
       $file_phids = array();
       foreach ($need_images as $key => $project) {
         $image_phid = $project->getProfileImagePHID();
         if ($image_phid) {
           $file_phids[$key] = $image_phid;
         }
       }
 
       if ($file_phids) {
         $files = id(new PhabricatorFileQuery())
           ->setParentQuery($this)
           ->setViewer($viewer)
           ->withPHIDs($file_phids)
           ->execute();
         $files = mpull($files, null, 'getPHID');
 
         foreach ($file_phids as $key => $image_phid) {
           $file = idx($files, $image_phid);
           if (!$file) {
             continue;
           }
 
           $need_images[$key]->attachProfileImageFile($file);
           unset($need_images[$key]);
         }
       }
 
       // For projects with default images, or projects where the custom image
       // failed to load, load a builtin image.
       if ($need_images) {
         $builtin_map = array();
         $builtins = array();
         foreach ($need_images as $key => $project) {
           $icon = $project->getIcon();
 
           $builtin_name = PhabricatorProjectIconSet::getIconImage($icon);
           $builtin_name = 'projects/'.$builtin_name;
 
           $builtin = id(new PhabricatorFilesOnDiskBuiltinFile())
             ->setName($builtin_name);
 
           $builtin_key = $builtin->getBuiltinFileKey();
 
           $builtins[] = $builtin;
           $builtin_map[$key] = $builtin_key;
         }
 
         $builtin_files = PhabricatorFile::loadBuiltins(
           $viewer,
           $builtins);
 
         foreach ($need_images as $key => $project) {
           $builtin_key = $builtin_map[$key];
           $builtin_file = $builtin_files[$builtin_key];
           $project->attachProfileImageFile($builtin_file);
         }
       }
     }
 
     $this->loadSlugs($projects);
 
     return $projects;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->status != self::STATUS_ANY) {
       switch ($this->status) {
         case self::STATUS_OPEN:
         case self::STATUS_ACTIVE:
           $filter = array(
             PhabricatorProjectStatus::STATUS_ACTIVE,
           );
           break;
         case self::STATUS_CLOSED:
         case self::STATUS_ARCHIVED:
           $filter = array(
             PhabricatorProjectStatus::STATUS_ARCHIVED,
           );
           break;
         default:
           throw new Exception(
             pht(
               "Unknown project status '%s'!",
               $this->status));
       }
       $where[] = qsprintf(
         $conn,
         'project.status IN (%Ld)',
         $filter);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'project.status IN (%Ls)',
         $this->statuses);
     }
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'project.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'project.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->memberPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'e.dst IN (%Ls)',
         $this->memberPHIDs);
     }
 
     if ($this->watcherPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'w.dst IN (%Ls)',
         $this->watcherPHIDs);
     }
 
     if ($this->slugs !== null) {
       $where[] = qsprintf(
         $conn,
         'slug.slug IN (%Ls)',
         $this->allSlugs);
     }
 
     if ($this->names !== null) {
       $where[] = qsprintf(
         $conn,
         'project.name IN (%Ls)',
         $this->names);
     }
 
     if ($this->namePrefixes) {
       $parts = array();
       foreach ($this->namePrefixes as $name_prefix) {
         $parts[] = qsprintf(
           $conn,
           'project.name LIKE %>',
           $name_prefix);
       }
       $where[] = qsprintf($conn, '%LO', $parts);
     }
 
     if ($this->icons !== null) {
       $where[] = qsprintf(
         $conn,
         'project.icon IN (%Ls)',
         $this->icons);
     }
 
     if ($this->colors !== null) {
       $where[] = qsprintf(
         $conn,
         'project.color IN (%Ls)',
         $this->colors);
     }
 
     if ($this->parentPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'project.parentProjectPHID IN (%Ls)',
         $this->parentPHIDs);
     }
 
     if ($this->ancestorPHIDs !== null) {
       $ancestor_paths = queryfx_all(
         $conn,
         'SELECT projectPath, projectDepth FROM %T WHERE phid IN (%Ls)',
         id(new PhabricatorProject())->getTableName(),
         $this->ancestorPHIDs);
       if (!$ancestor_paths) {
         throw new PhabricatorEmptyQueryException();
       }
 
       $sql = array();
       foreach ($ancestor_paths as $ancestor_path) {
         $sql[] = qsprintf(
           $conn,
           '(project.projectPath LIKE %> AND project.projectDepth > %d)',
           $ancestor_path['projectPath'],
           $ancestor_path['projectDepth']);
       }
 
       $where[] = qsprintf($conn, '%LO', $sql);
 
       $where[] = qsprintf(
         $conn,
         'project.parentProjectPHID IS NOT NULL');
     }
 
     if ($this->isMilestone !== null) {
       if ($this->isMilestone) {
         $where[] = qsprintf(
           $conn,
           'project.milestoneNumber IS NOT NULL');
       } else {
         $where[] = qsprintf(
           $conn,
           'project.milestoneNumber IS NULL');
       }
     }
 
 
     if ($this->hasSubprojects !== null) {
       $where[] = qsprintf(
         $conn,
         'project.hasSubprojects = %d',
         (int)$this->hasSubprojects);
     }
 
     if ($this->minDepth !== null) {
       $where[] = qsprintf(
         $conn,
         'project.projectDepth >= %d',
         $this->minDepth);
     }
 
     if ($this->maxDepth !== null) {
       $where[] = qsprintf(
         $conn,
         'project.projectDepth <= %d',
         $this->maxDepth);
     }
 
     if ($this->minMilestoneNumber !== null) {
       $where[] = qsprintf(
         $conn,
         'project.milestoneNumber >= %d',
         $this->minMilestoneNumber);
     }
 
     if ($this->maxMilestoneNumber !== null) {
       $where[] = qsprintf(
         $conn,
         'project.milestoneNumber <= %d',
         $this->maxMilestoneNumber);
     }
 
     if ($this->subtypes !== null) {
       $where[] = qsprintf(
         $conn,
         'project.subtype IN (%Ls)',
         $this->subtypes);
     }
 
     return $where;
   }
 
   protected function shouldGroupQueryResultRows() {
     if ($this->memberPHIDs || $this->watcherPHIDs || $this->nameTokens) {
       return true;
     }
 
     if ($this->slugs) {
       return true;
     }
 
     return parent::shouldGroupQueryResultRows();
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->memberPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T e ON e.src = project.phid AND e.type = %d',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         PhabricatorProjectMaterializedMemberEdgeType::EDGECONST);
     }
 
     if ($this->watcherPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T w ON w.src = project.phid AND w.type = %d',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         PhabricatorObjectHasWatcherEdgeType::EDGECONST);
     }
 
     if ($this->slugs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T slug on slug.projectPHID = project.phid',
         id(new PhabricatorProjectSlug())->getTableName());
     }
 
     if ($this->nameTokens !== null) {
       $name_tokens = $this->getNameTokensForQuery($this->nameTokens);
       foreach ($name_tokens as $key => $token) {
         $token_table = 'token_'.$key;
         $joins[] = qsprintf(
           $conn,
           'JOIN %T %T ON %T.projectID = project.id AND %T.token LIKE %>',
           PhabricatorProject::TABLE_DATASOURCE_TOKEN,
           $token_table,
           $token_table,
           $token_table,
           $token);
       }
     }
 
     return $joins;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorProjectApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'project';
   }
 
   private function linkProjectGraph(array $projects, array $ancestors) {
     $ancestor_map = mpull($ancestors, null, 'getPHID');
     $projects_map = mpull($projects, null, 'getPHID');
 
     $all_map = $projects_map + $ancestor_map;
 
     $done = array();
     foreach ($projects as $key => $project) {
       $seen = array($project->getPHID() => true);
 
       if (!$this->linkProject($project, $all_map, $done, $seen)) {
         $this->didRejectResult($project);
         unset($projects[$key]);
         continue;
       }
 
       foreach ($project->getAncestorProjects() as $ancestor) {
         $seen[$ancestor->getPHID()] = true;
       }
     }
 
     return $projects;
   }
 
   private function linkProject($project, array $all, array $done, array $seen) {
     $parent_phid = $project->getParentProjectPHID();
 
     // This project has no parent, so just attach `null` and return.
     if (!$parent_phid) {
       $project->attachParentProject(null);
       return true;
     }
 
     // This project has a parent, but it failed to load.
     if (empty($all[$parent_phid])) {
       return false;
     }
 
     // Test for graph cycles. If we encounter one, we're going to hide the
     // entire cycle since we can't meaningfully resolve it.
     if (isset($seen[$parent_phid])) {
       return false;
     }
 
     $seen[$parent_phid] = true;
 
     $parent = $all[$parent_phid];
     $project->attachParentProject($parent);
 
     if (!empty($done[$parent_phid])) {
       return true;
     }
 
     return $this->linkProject($parent, $all, $done, $seen);
   }
 
   private function getAllReachableAncestors(array $projects) {
     $ancestors = array();
 
     $seen = mpull($projects, null, 'getPHID');
 
     $stack = $projects;
     while ($stack) {
       $project = array_pop($stack);
 
       $phid = $project->getPHID();
       $ancestors[$phid] = $project;
 
       $parent_phid = $project->getParentProjectPHID();
       if (!$parent_phid) {
         continue;
       }
 
       if (isset($seen[$parent_phid])) {
         continue;
       }
 
       $seen[$parent_phid] = true;
       $stack[] = $project->getParentProject();
     }
 
     return $ancestors;
   }
 
   private function loadSlugs(array $projects) {
     // Build a map from primary slugs to projects.
     $primary_map = array();
     foreach ($projects as $project) {
       $primary_slug = $project->getPrimarySlug();
       if ($primary_slug === null) {
         continue;
       }
 
       $primary_map[$primary_slug] = $project;
     }
 
     // Link up all of the queried slugs which correspond to primary
     // slugs. If we can link up everything from this (no slugs were queried,
     // or only primary slugs were queried) we don't need to load anything
     // else.
     $unknown = $this->slugNormals;
     foreach ($unknown as $input => $normal) {
       if (isset($primary_map[$input])) {
         $match = $input;
       } else if (isset($primary_map[$normal])) {
         $match = $normal;
       } else {
         continue;
       }
 
       $this->slugMap[$input] = array(
         'slug' => $match,
         'projectPHID' => $primary_map[$match]->getPHID(),
       );
 
       unset($unknown[$input]);
     }
 
     // If we need slugs, we have to load everything.
     // If we still have some queried slugs which we haven't mapped, we only
     // need to look for them.
     // If we've mapped everything, we don't have to do any work.
     $project_phids = mpull($projects, 'getPHID');
     if ($this->needSlugs) {
       $slugs = id(new PhabricatorProjectSlug())->loadAllWhere(
         'projectPHID IN (%Ls)',
         $project_phids);
     } else if ($unknown) {
       $slugs = id(new PhabricatorProjectSlug())->loadAllWhere(
         'projectPHID IN (%Ls) AND slug IN (%Ls)',
         $project_phids,
         $unknown);
     } else {
       $slugs = array();
     }
 
     // Link up any slugs we were not able to link up earlier.
     $extra_map = mpull($slugs, 'getProjectPHID', 'getSlug');
     foreach ($unknown as $input => $normal) {
       if (isset($extra_map[$input])) {
         $match = $input;
       } else if (isset($extra_map[$normal])) {
         $match = $normal;
       } else {
         continue;
       }
 
       $this->slugMap[$input] = array(
         'slug' => $match,
         'projectPHID' => $extra_map[$match],
       );
 
       unset($unknown[$input]);
     }
 
     if ($this->needSlugs) {
       $slug_groups = mgroup($slugs, 'getProjectPHID');
       foreach ($projects as $project) {
         $project_slugs = idx($slug_groups, $project->getPHID(), array());
         $project->attachSlugs($project_slugs);
       }
     }
   }
 
   private function getNameTokensForQuery(array $tokens) {
     // When querying for projects by name, only actually search for the five
     // longest tokens. MySQL can get grumpy with a large number of JOINs
     // with LIKEs and queries for more than 5 tokens are essentially never
     // legitimate searches for projects, but users copy/pasting nonsense.
     // See also PHI47.
 
     $length_map = array();
     foreach ($tokens as $token) {
       $length_map[$token] = strlen($token);
     }
     arsort($length_map);
 
     $length_map = array_slice($length_map, 0, 5, true);
 
     return array_keys($length_map);
   }
 
 }
diff --git a/src/applications/project/query/PhabricatorProjectTriggerQuery.php b/src/applications/project/query/PhabricatorProjectTriggerQuery.php
index 452e3e53f1..306fcb50fe 100644
--- a/src/applications/project/query/PhabricatorProjectTriggerQuery.php
+++ b/src/applications/project/query/PhabricatorProjectTriggerQuery.php
@@ -1,135 +1,131 @@
 <?php
 
 final class PhabricatorProjectTriggerQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $activeColumnMin;
   private $activeColumnMax;
 
   private $needUsage;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function needUsage($need_usage) {
     $this->needUsage = $need_usage;
     return $this;
   }
 
   public function withActiveColumnCountBetween($min, $max) {
     $this->activeColumnMin = $min;
     $this->activeColumnMax = $max;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorProjectTrigger();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'trigger.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'trigger.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->activeColumnMin !== null) {
       $where[] = qsprintf(
         $conn,
         'trigger_usage.activeColumnCount >= %d',
         $this->activeColumnMin);
     }
 
     if ($this->activeColumnMax !== null) {
       $where[] = qsprintf(
         $conn,
         'trigger_usage.activeColumnCount <= %d',
         $this->activeColumnMax);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinUsageTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %R trigger_usage ON trigger.phid = trigger_usage.triggerPHID',
         new PhabricatorProjectTriggerUsage());
     }
 
     return $joins;
   }
 
   private function shouldJoinUsageTable() {
     if ($this->activeColumnMin !== null) {
       return true;
     }
 
     if ($this->activeColumnMax !== null) {
       return true;
     }
 
     return false;
   }
 
   protected function didFilterPage(array $triggers) {
     if ($this->needUsage) {
       $usage_map = id(new PhabricatorProjectTriggerUsage())->loadAllWhere(
         'triggerPHID IN (%Ls)',
         mpull($triggers, 'getPHID'));
       $usage_map = mpull($usage_map, null, 'getTriggerPHID');
 
       foreach ($triggers as $trigger) {
         $trigger_phid = $trigger->getPHID();
 
         $usage = idx($usage_map, $trigger_phid);
         if (!$usage) {
           $usage = id(new PhabricatorProjectTriggerUsage())
             ->setTriggerPHID($trigger_phid)
             ->setExamplePHID(null)
             ->setColumnCount(0)
             ->setActiveColumnCount(0);
         }
 
         $trigger->attachUsage($usage);
       }
     }
 
     return $triggers;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorProjectApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'trigger';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php b/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php
index cd693be605..08f0ada159 100644
--- a/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php
@@ -1,64 +1,60 @@
 <?php
 
 final class PhabricatorRepositoryGitLFSRefQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $repositoryPHIDs;
   private $objectHashes;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $phids) {
     $this->repositoryPHIDs = $phids;
     return $this;
   }
 
   public function withObjectHashes(array $hashes) {
     $this->objectHashes = $hashes;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryGitLFSRef();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->objectHashes !== null) {
       $where[] = qsprintf(
         $conn,
         'objectHash IN (%Ls)',
         $this->objectHashes);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
index 7de97de4d6..2b05b542d5 100644
--- a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
@@ -1,160 +1,156 @@
 <?php
 
 final class PhabricatorRepositoryIdentityQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $identityNames;
   private $emailAddresses;
   private $assignedPHIDs;
   private $effectivePHIDs;
   private $identityNameLike;
   private $hasEffectivePHID;
   private $relatedPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withIdentityNames(array $names) {
     $this->identityNames = $names;
     return $this;
   }
 
   public function withIdentityNameLike($name_like) {
     $this->identityNameLike = $name_like;
     return $this;
   }
 
   public function withEmailAddresses(array $addresses) {
     $this->emailAddresses = $addresses;
     return $this;
   }
 
   public function withAssignedPHIDs(array $assigned) {
     $this->assignedPHIDs = $assigned;
     return $this;
   }
 
   public function withEffectivePHIDs(array $effective) {
     $this->effectivePHIDs = $effective;
     return $this;
   }
 
   public function withRelatedPHIDs(array $related) {
     $this->relatedPHIDs = $related;
     return $this;
   }
 
   public function withHasEffectivePHID($has_effective_phid) {
     $this->hasEffectivePHID = $has_effective_phid;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryIdentity();
   }
 
   protected function getPrimaryTableAlias() {
      return 'identity';
    }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'identity.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'identity.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->assignedPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'identity.manuallySetUserPHID IN (%Ls)',
         $this->assignedPHIDs);
     }
 
     if ($this->effectivePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'identity.currentEffectiveUserPHID IN (%Ls)',
         $this->effectivePHIDs);
     }
 
     if ($this->hasEffectivePHID !== null) {
       if ($this->hasEffectivePHID) {
         $where[] = qsprintf(
           $conn,
           'identity.currentEffectiveUserPHID IS NOT NULL');
       } else {
         $where[] = qsprintf(
           $conn,
           'identity.currentEffectiveUserPHID IS NULL');
       }
     }
 
     if ($this->identityNames !== null) {
       $name_hashes = array();
       foreach ($this->identityNames as $name) {
         $name_hashes[] = PhabricatorHash::digestForIndex($name);
       }
 
       $where[] = qsprintf(
         $conn,
         'identity.identityNameHash IN (%Ls)',
         $name_hashes);
     }
 
     if ($this->emailAddresses !== null) {
       $where[] = qsprintf(
         $conn,
         'identity.emailAddress IN (%Ls)',
         $this->emailAddresses);
     }
 
     if ($this->identityNameLike != null) {
       $where[] = qsprintf(
         $conn,
         'identity.identityNameRaw LIKE %~',
         $this->identityNameLike);
     }
 
     if ($this->relatedPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         '(identity.manuallySetUserPHID IN (%Ls) OR
           identity.currentEffectiveUserPHID IN (%Ls) OR
           identity.automaticGuessedUserPHID IN (%Ls))',
         $this->relatedPHIDs,
         $this->relatedPHIDs,
         $this->relatedPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php b/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php
index ce14a6f831..8d4f14e0ce 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php
@@ -1,135 +1,131 @@
 <?php
 
 final class PhabricatorRepositoryPullEventQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $repositoryPHIDs;
   private $pullerPHIDs;
   private $epochMin;
   private $epochMax;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $repository_phids) {
     $this->repositoryPHIDs = $repository_phids;
     return $this;
   }
 
   public function withPullerPHIDs(array $puller_phids) {
     $this->pullerPHIDs = $puller_phids;
     return $this;
   }
 
   public function withEpochBetween($min, $max) {
     $this->epochMin = $min;
     $this->epochMax = $max;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryPullEvent();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $events) {
     // If a pull targets an invalid repository or fails before authenticating,
     // it may not have an associated repository.
 
     $repository_phids = mpull($events, 'getRepositoryPHID');
     $repository_phids = array_filter($repository_phids);
 
     if ($repository_phids) {
       $repositories = id(new PhabricatorRepositoryQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($repository_phids)
         ->execute();
       $repositories = mpull($repositories, null, 'getPHID');
     } else {
       $repositories = array();
     }
 
     foreach ($events as $key => $event) {
       $phid = $event->getRepositoryPHID();
       if (!$phid) {
         $event->attachRepository(null);
         continue;
       }
 
       if (empty($repositories[$phid])) {
         unset($events[$key]);
         $this->didRejectResult($event);
         continue;
       }
 
       $event->attachRepository($repositories[$phid]);
     }
 
     return $events;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->pullerPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'pullerPHID in (%Ls)',
         $this->pullerPHIDs);
     }
 
     if ($this->epochMin !== null) {
       $where[] = qsprintf(
         $conn,
         'epoch >= %d',
         $this->epochMin);
     }
 
     if ($this->epochMax !== null) {
       $where[] = qsprintf(
         $conn,
         'epoch <= %d',
         $this->epochMax);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
index f3e5fc62b4..d1ce937b86 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
@@ -1,122 +1,118 @@
 <?php
 
 final class PhabricatorRepositoryPushEventQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $repositoryPHIDs;
   private $pusherPHIDs;
   private $needLogs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $repository_phids) {
     $this->repositoryPHIDs = $repository_phids;
     return $this;
   }
 
   public function withPusherPHIDs(array $pusher_phids) {
     $this->pusherPHIDs = $pusher_phids;
     return $this;
   }
 
   public function needLogs($need_logs) {
     $this->needLogs = $need_logs;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryPushEvent();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $events) {
     $repository_phids = mpull($events, 'getRepositoryPHID');
     $repositories = id(new PhabricatorRepositoryQuery())
       ->setViewer($this->getViewer())
       ->withPHIDs($repository_phids)
       ->execute();
     $repositories = mpull($repositories, null, 'getPHID');
 
     foreach ($events as $key => $event) {
       $phid = $event->getRepositoryPHID();
       if (empty($repositories[$phid])) {
         unset($events[$key]);
         continue;
       }
       $event->attachRepository($repositories[$phid]);
     }
 
     return $events;
   }
 
   protected function didFilterPage(array $events) {
     $phids = mpull($events, 'getPHID');
 
     if ($this->needLogs) {
       $logs = id(new PhabricatorRepositoryPushLogQuery())
         ->setParentQuery($this)
         ->setViewer($this->getViewer())
         ->withPushEventPHIDs($phids)
         ->execute();
       $logs = mgroup($logs, 'getPushEventPHID');
       foreach ($events as $key => $event) {
         $event_logs = idx($logs, $event->getPHID(), array());
         $event->attachLogs($event_logs);
       }
     }
 
     return $events;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->pusherPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'pusherPHID in (%Ls)',
         $this->pusherPHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
index d4734f61e6..16897a1e4b 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
@@ -1,199 +1,195 @@
 <?php
 
 final class PhabricatorRepositoryPushLogQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $repositoryPHIDs;
   private $pusherPHIDs;
   private $refTypes;
   private $newRefs;
   private $pushEventPHIDs;
   private $epochMin;
   private $epochMax;
   private $blockingHeraldRulePHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $repository_phids) {
     $this->repositoryPHIDs = $repository_phids;
     return $this;
   }
 
   public function withPusherPHIDs(array $pusher_phids) {
     $this->pusherPHIDs = $pusher_phids;
     return $this;
   }
 
   public function withRefTypes(array $ref_types) {
     $this->refTypes = $ref_types;
     return $this;
   }
 
   public function withNewRefs(array $new_refs) {
     $this->newRefs = $new_refs;
     return $this;
   }
 
   public function withPushEventPHIDs(array $phids) {
     $this->pushEventPHIDs = $phids;
     return $this;
   }
 
   public function withEpochBetween($min, $max) {
     $this->epochMin = $min;
     $this->epochMax = $max;
     return $this;
   }
 
   public function withBlockingHeraldRulePHIDs(array $phids) {
     $this->blockingHeraldRulePHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryPushLog();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $logs) {
     $event_phids = mpull($logs, 'getPushEventPHID');
     $events = id(new PhabricatorObjectQuery())
       ->setParentQuery($this)
       ->setViewer($this->getViewer())
       ->withPHIDs($event_phids)
       ->execute();
     $events = mpull($events, null, 'getPHID');
 
     foreach ($logs as $key => $log) {
       $event = idx($events, $log->getPushEventPHID());
       if (!$event) {
         unset($logs[$key]);
         continue;
       }
       $log->attachPushEvent($event);
     }
 
     return $logs;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'log.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'log.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'log.repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->pusherPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'log.pusherPHID in (%Ls)',
         $this->pusherPHIDs);
     }
 
     if ($this->pushEventPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'log.pushEventPHID in (%Ls)',
         $this->pushEventPHIDs);
     }
 
     if ($this->refTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'log.refType IN (%Ls)',
         $this->refTypes);
     }
 
     if ($this->newRefs !== null) {
       $where[] = qsprintf(
         $conn,
         'log.refNew IN (%Ls)',
         $this->newRefs);
     }
 
     if ($this->epochMin !== null) {
       $where[] = qsprintf(
         $conn,
         'log.epoch >= %d',
         $this->epochMin);
     }
 
     if ($this->epochMax !== null) {
       $where[] = qsprintf(
         $conn,
         'log.epoch <= %d',
         $this->epochMax);
     }
 
     if ($this->blockingHeraldRulePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         '(event.rejectCode = %d AND event.rejectDetails IN (%Ls))',
         PhabricatorRepositoryPushLog::REJECT_HERALD,
         $this->blockingHeraldRulePHIDs);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->shouldJoinPushEventTable()) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T event ON event.phid = log.pushEventPHID',
         id(new PhabricatorRepositoryPushEvent())->getTableName());
     }
 
     return $joins;
   }
 
   private function shouldJoinPushEventTable() {
     if ($this->blockingHeraldRulePHIDs !== null) {
       return true;
     }
 
     return false;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'log';
   }
 
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php b/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
index b3c960e025..5e894333f6 100644
--- a/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
@@ -1,153 +1,149 @@
 <?php
 
 final class PhabricatorRepositoryRefCursorQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $repositoryPHIDs;
   private $refTypes;
   private $refNames;
   private $datasourceQuery;
   private $needPositions;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $phids) {
     $this->repositoryPHIDs = $phids;
     return $this;
   }
 
   public function withRefTypes(array $types) {
     $this->refTypes = $types;
     return $this;
   }
 
   public function withRefNames(array $names) {
     $this->refNames = $names;
     return $this;
   }
 
   public function withDatasourceQuery($query) {
     $this->datasourceQuery = $query;
     return $this;
   }
 
   public function needPositions($need) {
     $this->needPositions = $need;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryRefCursor();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $refs) {
     $repository_phids = mpull($refs, 'getRepositoryPHID');
 
     $repositories = id(new PhabricatorRepositoryQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($repository_phids)
       ->execute();
     $repositories = mpull($repositories, null, 'getPHID');
 
     foreach ($refs as $key => $ref) {
       $repository = idx($repositories, $ref->getRepositoryPHID());
       if (!$repository) {
         $this->didRejectResult($ref);
         unset($refs[$key]);
         continue;
       }
       $ref->attachRepository($repository);
     }
 
     if (!$refs) {
       return $refs;
     }
 
     if ($this->needPositions) {
       $positions = id(new PhabricatorRepositoryRefPosition())->loadAllWhere(
         'cursorID IN (%Ld)',
         mpull($refs, 'getID'));
       $positions = mgroup($positions, 'getCursorID');
 
       foreach ($refs as $key => $ref) {
         $ref_positions = idx($positions, $ref->getID(), array());
         $ref->attachPositions($ref_positions);
       }
     }
 
     return $refs;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->refTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'refType IN (%Ls)',
         $this->refTypes);
     }
 
     if ($this->refNames !== null) {
       $name_hashes = array();
       foreach ($this->refNames as $name) {
         $name_hashes[] = PhabricatorHash::digestForIndex($name);
       }
 
       $where[] = qsprintf(
         $conn,
         'refNameHash IN (%Ls)',
         $name_hashes);
     }
 
     if (strlen($this->datasourceQuery)) {
       $where[] = qsprintf(
         $conn,
         'refNameRaw LIKE %>',
         $this->datasourceQuery);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php b/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
index 542cb5cdc0..cc568ef8e1 100644
--- a/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
@@ -1,115 +1,111 @@
 <?php
 
 final class PhabricatorRepositorySyncEventQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $repositoryPHIDs;
   private $epochMin;
   private $epochMax;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $repository_phids) {
     $this->repositoryPHIDs = $repository_phids;
     return $this;
   }
 
   public function withEpochBetween($min, $max) {
     $this->epochMin = $min;
     $this->epochMax = $max;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositorySyncEvent();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $events) {
     $repository_phids = mpull($events, 'getRepositoryPHID');
     $repository_phids = array_filter($repository_phids);
 
     if ($repository_phids) {
       $repositories = id(new PhabricatorRepositoryQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($repository_phids)
         ->execute();
       $repositories = mpull($repositories, null, 'getPHID');
     } else {
       $repositories = array();
     }
 
     foreach ($events as $key => $event) {
       $phid = $event->getRepositoryPHID();
 
       if (empty($repositories[$phid])) {
         unset($events[$key]);
         $this->didRejectResult($event);
         continue;
       }
 
       $event->attachRepository($repositories[$phid]);
     }
 
     return $events;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     if ($this->epochMin !== null) {
       $where[] = qsprintf(
         $conn,
         'epoch >= %d',
         $this->epochMin);
     }
 
     if ($this->epochMax !== null) {
       $where[] = qsprintf(
         $conn,
         'epoch <= %d',
         $this->epochMax);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/repository/query/PhabricatorRepositoryURIQuery.php b/src/applications/repository/query/PhabricatorRepositoryURIQuery.php
index 71252a6fb7..5b75e1ef63 100644
--- a/src/applications/repository/query/PhabricatorRepositoryURIQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryURIQuery.php
@@ -1,101 +1,97 @@
 <?php
 
 final class PhabricatorRepositoryURIQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $repositoryPHIDs;
   private $repositories = array();
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withRepositoryPHIDs(array $phids) {
     $this->repositoryPHIDs = $phids;
     return $this;
   }
 
   public function withRepositories(array $repositories) {
     $repositories = mpull($repositories, null, 'getPHID');
     $this->withRepositoryPHIDs(array_keys($repositories));
     $this->repositories = $repositories;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorRepositoryURI();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->repositoryPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'repositoryPHID IN (%Ls)',
         $this->repositoryPHIDs);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $uris) {
     $repositories = $this->repositories;
 
     $repository_phids = mpull($uris, 'getRepositoryPHID');
     $repository_phids = array_fuse($repository_phids);
     $repository_phids = array_diff_key($repository_phids, $repositories);
 
     if ($repository_phids) {
       $more_repositories = id(new PhabricatorRepositoryQuery())
         ->setViewer($this->getViewer())
         ->withPHIDs($repository_phids)
         ->execute();
       $repositories += mpull($more_repositories, null, 'getPHID');
     }
 
     foreach ($uris as $key => $uri) {
       $repository_phid = $uri->getRepositoryPHID();
       $repository = idx($repositories, $repository_phid);
       if (!$repository) {
         $this->didRejectResult($uri);
         unset($uris[$key]);
         continue;
       }
       $uri->attachRepository($repository);
     }
 
     return $uris;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDiffusionApplication';
   }
 
 }
diff --git a/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php b/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php
index 6c4fad31a3..862f694fc8 100644
--- a/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php
+++ b/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php
@@ -1,64 +1,60 @@
 <?php
 
 final class PhabricatorNamedQueryConfigQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $engineClassNames;
   private $scopePHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withScopePHIDs(array $scope_phids) {
     $this->scopePHIDs = $scope_phids;
     return $this;
   }
 
   public function withEngineClassNames(array $engine_class_names) {
     $this->engineClassNames = $engine_class_names;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorNamedQueryConfig();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->engineClassNames !== null) {
       $where[] = qsprintf(
         $conn,
         'engineClassName IN (%Ls)',
         $this->engineClassNames);
     }
 
     if ($this->scopePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'scopePHID IN (%Ls)',
         $this->scopePHIDs);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorSearchApplication';
   }
 
 }
diff --git a/src/applications/search/query/PhabricatorNamedQueryQuery.php b/src/applications/search/query/PhabricatorNamedQueryQuery.php
index 3decff5494..0ed92646e6 100644
--- a/src/applications/search/query/PhabricatorNamedQueryQuery.php
+++ b/src/applications/search/query/PhabricatorNamedQueryQuery.php
@@ -1,77 +1,73 @@
 <?php
 
 final class PhabricatorNamedQueryQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $engineClassNames;
   private $userPHIDs;
   private $queryKeys;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withUserPHIDs(array $user_phids) {
     $this->userPHIDs = $user_phids;
     return $this;
   }
 
   public function withEngineClassNames(array $engine_class_names) {
     $this->engineClassNames = $engine_class_names;
     return $this;
   }
 
   public function withQueryKeys(array $query_keys) {
     $this->queryKeys = $query_keys;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorNamedQuery();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->engineClassNames !== null) {
       $where[] = qsprintf(
         $conn,
         'engineClassName IN (%Ls)',
         $this->engineClassNames);
     }
 
     if ($this->userPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'userPHID IN (%Ls)',
         $this->userPHIDs);
     }
 
     if ($this->queryKeys !== null) {
       $where[] = qsprintf(
         $conn,
         'queryKey IN (%Ls)',
         $this->queryKeys);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorSearchApplication';
   }
 
 }
diff --git a/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
index 16b5d793a4..9f26a81424 100644
--- a/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
+++ b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
@@ -1,163 +1,159 @@
 <?php
 
 final class PhabricatorProfileMenuItemConfigurationQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $profilePHIDs;
   private $customPHIDs;
   private $includeGlobal;
   private $affectedObjectPHIDs;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withProfilePHIDs(array $phids) {
     $this->profilePHIDs = $phids;
     return $this;
   }
 
   public function withCustomPHIDs(array $phids, $include_global = false) {
     $this->customPHIDs = $phids;
     $this->includeGlobal = $include_global;
     return $this;
   }
 
   public function withAffectedObjectPHIDs(array $phids) {
     $this->affectedObjectPHIDs = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorProfileMenuItemConfiguration();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'config.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'config.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->profilePHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'config.profilePHID IN (%Ls)',
         $this->profilePHIDs);
     }
 
     if ($this->customPHIDs !== null) {
       if ($this->customPHIDs && $this->includeGlobal) {
         $where[] = qsprintf(
           $conn,
           'config.customPHID IN (%Ls) OR config.customPHID IS NULL',
           $this->customPHIDs);
       } else if ($this->customPHIDs) {
         $where[] = qsprintf(
           $conn,
           'config.customPHID IN (%Ls)',
           $this->customPHIDs);
       } else {
         $where[] = qsprintf(
           $conn,
           'config.customPHID IS NULL');
       }
     }
 
     if ($this->affectedObjectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'affected.dst IN (%Ls)',
         $this->affectedObjectPHIDs);
     }
 
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->affectedObjectPHIDs !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T affected ON affected.src = config.phid
           AND affected.type = %d',
         PhabricatorEdgeConfig::TABLE_NAME_EDGE,
         PhabricatorProfileMenuItemAffectsObjectEdgeType::EDGECONST);
     }
 
     return $joins;
   }
 
   protected function willFilterPage(array $page) {
     $items = PhabricatorProfileMenuItem::getAllMenuItems();
     foreach ($page as $key => $item) {
       $item_type = idx($items, $item->getMenuItemKey());
       if (!$item_type) {
         $this->didRejectResult($item);
         unset($page[$key]);
         continue;
       }
       $item_type = clone $item_type;
       $item_type->setViewer($this->getViewer());
       $item->attachMenuItem($item_type);
     }
 
     if (!$page) {
       return array();
     }
 
     $profile_phids = mpull($page, 'getProfilePHID');
 
     $profiles = id(new PhabricatorObjectQuery())
       ->setViewer($this->getViewer())
       ->setParentQuery($this)
       ->withPHIDs($profile_phids)
       ->execute();
     $profiles = mpull($profiles, null, 'getPHID');
 
     foreach ($page as $key => $item) {
       $profile = idx($profiles, $item->getProfilePHID());
       if (!$profile) {
         $this->didRejectResult($item);
         unset($page[$key]);
         continue;
       }
 
       $item->attachProfileObject($profile);
     }
 
     return $page;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorSearchApplication';
   }
 
   protected function getPrimaryTableAlias() {
     return 'config';
   }
 
 }
diff --git a/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php b/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
index 0b7335326c..72368a654a 100644
--- a/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
+++ b/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
@@ -1,174 +1,170 @@
 <?php
 
 final class PhabricatorSlowvoteQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $withVotesByViewer;
   private $isClosed;
 
   private $needOptions;
   private $needChoices;
   private $needViewerChoices;
 
   public function withIDs($ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs($phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs($author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
   public function withVotesByViewer($with_vote) {
     $this->withVotesByViewer = $with_vote;
     return $this;
   }
 
   public function withIsClosed($with_closed) {
     $this->isClosed = $with_closed;
     return $this;
   }
 
   public function needOptions($need_options) {
     $this->needOptions = $need_options;
     return $this;
   }
 
   public function needChoices($need_choices) {
     $this->needChoices = $need_choices;
     return $this;
   }
 
   public function needViewerChoices($need_viewer_choices) {
     $this->needViewerChoices = $need_viewer_choices;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorSlowvotePoll();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $polls) {
     assert_instances_of($polls, 'PhabricatorSlowvotePoll');
 
     $ids = mpull($polls, 'getID');
     $viewer = $this->getViewer();
 
     if ($this->needOptions) {
       $options = id(new PhabricatorSlowvoteOption())->loadAllWhere(
         'pollID IN (%Ld)',
         $ids);
 
       $options = mgroup($options, 'getPollID');
       foreach ($polls as $poll) {
         $poll->attachOptions(idx($options, $poll->getID(), array()));
       }
     }
 
     if ($this->needChoices) {
       $choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
         'pollID IN (%Ld)',
         $ids);
 
       $choices = mgroup($choices, 'getPollID');
       foreach ($polls as $poll) {
         $poll->attachChoices(idx($choices, $poll->getID(), array()));
       }
 
       // If we need the viewer's choices, we can just fill them from the data
       // we already loaded.
       if ($this->needViewerChoices) {
         foreach ($polls as $poll) {
           $poll->attachViewerChoices(
             $viewer,
             idx(
               mgroup($poll->getChoices(), 'getAuthorPHID'),
               $viewer->getPHID(),
               array()));
         }
       }
     } else if ($this->needViewerChoices) {
       $choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
         'pollID IN (%Ld) AND authorPHID = %s',
         $ids,
         $viewer->getPHID());
 
       $choices = mgroup($choices, 'getPollID');
       foreach ($polls as $poll) {
         $poll->attachViewerChoices(
           $viewer,
           idx($choices, $poll->getID(), array()));
       }
     }
 
     return $polls;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'p.phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'p.authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->isClosed !== null) {
       $where[] = qsprintf(
         $conn,
         'p.isClosed = %d',
         (int)$this->isClosed);
     }
     return $where;
   }
 
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = parent::buildJoinClauseParts($conn);
 
     if ($this->withVotesByViewer !== null) {
       $joins[] = qsprintf(
         $conn,
         'JOIN %T vv ON vv.pollID = p.id AND vv.authorPHID = %s',
         id(new PhabricatorSlowvoteChoice())->getTableName(),
         $this->getViewer()->getPHID());
     }
     return $joins;
   }
 
   protected function getPrimaryTableAlias() {
     return 'p';
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorSlowvoteApplication';
   }
 
 }
diff --git a/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php b/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
index ee11dcdd06..388b6ab4d8 100644
--- a/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
+++ b/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
@@ -1,238 +1,238 @@
 <?php
 
 final class PhabricatorSpacesNamespaceQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   const KEY_ALL = 'spaces.all';
   const KEY_DEFAULT = 'spaces.default';
   const KEY_VIEWER = 'spaces.viewer';
 
   private $ids;
   private $phids;
   private $isDefaultNamespace;
   private $isArchived;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withIsDefaultNamespace($default) {
     $this->isDefaultNamespace = $default;
     return $this;
   }
 
   public function withIsArchived($archived) {
     $this->isArchived = $archived;
     return $this;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorSpacesApplication';
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage(new PhabricatorSpacesNamespace());
+  public function newResultObject() {
+    return new PhabricatorSpacesNamespace();
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->isDefaultNamespace !== null) {
       if ($this->isDefaultNamespace) {
         $where[] = qsprintf(
           $conn,
           'isDefaultNamespace = 1');
       } else {
         $where[] = qsprintf(
           $conn,
           'isDefaultNamespace IS NULL');
       }
     }
 
     if ($this->isArchived !== null) {
       $where[] = qsprintf(
         $conn,
         'isArchived = %d',
         (int)$this->isArchived);
     }
 
     return $where;
   }
 
   public static function destroySpacesCache() {
     $cache = PhabricatorCaches::getRequestCache();
     $cache->deleteKeys(
       array(
         self::KEY_ALL,
         self::KEY_DEFAULT,
       ));
   }
 
   public static function getSpacesExist() {
     return (bool)self::getAllSpaces();
   }
 
   public static function getViewerSpacesExist(PhabricatorUser $viewer) {
     if (!self::getSpacesExist()) {
       return false;
     }
 
     // If the viewer has access to only one space, pretend spaces simply don't
     // exist.
     $spaces = self::getViewerSpaces($viewer);
     return (count($spaces) > 1);
   }
 
   public static function getAllSpaces() {
     $cache = PhabricatorCaches::getRequestCache();
     $cache_key = self::KEY_ALL;
 
     $spaces = $cache->getKey($cache_key);
     if ($spaces === null) {
       $spaces = id(new PhabricatorSpacesNamespaceQuery())
         ->setViewer(PhabricatorUser::getOmnipotentUser())
         ->execute();
       $spaces = mpull($spaces, null, 'getPHID');
       $cache->setKey($cache_key, $spaces);
     }
 
     return $spaces;
   }
 
   public static function getDefaultSpace() {
     $cache = PhabricatorCaches::getRequestCache();
     $cache_key = self::KEY_DEFAULT;
 
     $default_space = $cache->getKey($cache_key, false);
     if ($default_space === false) {
       $default_space = null;
 
       $spaces = self::getAllSpaces();
       foreach ($spaces as $space) {
         if ($space->getIsDefaultNamespace()) {
           $default_space = $space;
           break;
         }
       }
 
       $cache->setKey($cache_key, $default_space);
     }
 
     return $default_space;
   }
 
   public static function getViewerSpaces(PhabricatorUser $viewer) {
     $cache = PhabricatorCaches::getRequestCache();
     $cache_key = self::KEY_VIEWER.'('.$viewer->getCacheFragment().')';
 
     $result = $cache->getKey($cache_key);
     if ($result === null) {
       $spaces = self::getAllSpaces();
 
       $result = array();
       foreach ($spaces as $key => $space) {
         $can_see = PhabricatorPolicyFilter::hasCapability(
           $viewer,
           $space,
           PhabricatorPolicyCapability::CAN_VIEW);
         if ($can_see) {
           $result[$key] = $space;
         }
       }
 
       $cache->setKey($cache_key, $result);
     }
 
     return $result;
   }
 
 
   public static function getViewerActiveSpaces(PhabricatorUser $viewer) {
     $spaces = self::getViewerSpaces($viewer);
 
     foreach ($spaces as $key => $space) {
       if ($space->getIsArchived()) {
         unset($spaces[$key]);
       }
     }
 
     return $spaces;
   }
 
   public static function getSpaceOptionsForViewer(
     PhabricatorUser $viewer,
     $space_phid) {
 
     $viewer_spaces = self::getViewerSpaces($viewer);
     $viewer_spaces = msort($viewer_spaces, 'getNamespaceName');
 
     $map = array();
     foreach ($viewer_spaces as $space) {
 
       // Skip archived spaces, unless the object is already in that space.
       if ($space->getIsArchived()) {
         if ($space->getPHID() != $space_phid) {
           continue;
         }
       }
 
       $map[$space->getPHID()] = pht(
         'Space %s: %s',
         $space->getMonogram(),
         $space->getNamespaceName());
     }
 
     return $map;
   }
 
 
   /**
    * Get the Space PHID for an object, if one exists.
    *
    * This is intended to simplify performing a bunch of redundant checks; you
    * can intentionally pass any value in (including `null`).
    *
    * @param wild
    * @return phid|null
    */
   public static function getObjectSpacePHID($object) {
     if (!$object) {
       return null;
     }
 
     if (!($object instanceof PhabricatorSpacesInterface)) {
       return null;
     }
 
     $space_phid = $object->getSpacePHID();
     if ($space_phid === null) {
       $default_space = self::getDefaultSpace();
       if ($default_space) {
         $space_phid = $default_space->getPHID();
       }
     }
 
     return $space_phid;
   }
 
 }
diff --git a/src/applications/tokens/query/PhabricatorTokenGivenQuery.php b/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
index b4a86428c1..0e6ad9eb54 100644
--- a/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
@@ -1,117 +1,113 @@
 <?php
 
 final class PhabricatorTokenGivenQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $authorPHIDs;
   private $objectPHIDs;
   private $tokenPHIDs;
 
   public function withTokenPHIDs(array $token_phids) {
     $this->tokenPHIDs = $token_phids;
     return $this;
   }
 
   public function withObjectPHIDs(array $object_phids) {
     $this->objectPHIDs = $object_phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorTokenGiven();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->objectPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'objectPHID IN (%Ls)',
         $this->objectPHIDs);
     }
 
     if ($this->tokenPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'tokenPHID IN (%Ls)',
         $this->tokenPHIDs);
     }
 
     return $where;
   }
 
   protected function willFilterPage(array $results) {
     $viewer = $this->getViewer();
 
     $object_phids = mpull($results, 'getObjectPHID');
 
     $objects = id(new PhabricatorObjectQuery())
       ->setViewer($viewer)
       ->withPHIDs($object_phids)
       ->execute();
     $objects = mpull($objects, null, 'getPHID');
 
     foreach ($results as $key => $result) {
       $object = idx($objects, $result->getObjectPHID());
 
       if ($object) {
         if ($object instanceof PhabricatorTokenReceiverInterface) {
           $result->attachObject($object);
           continue;
         }
       }
 
       $this->didRejectResult($result);
       unset($results[$key]);
     }
 
     if (!$results) {
       return $results;
     }
 
     $token_phids = mpull($results, 'getTokenPHID');
 
     $tokens = id(new PhabricatorTokenQuery())
       ->setViewer($viewer)
       ->withPHIDs($token_phids)
       ->execute();
     $tokens = mpull($tokens, null, 'getPHID');
 
     foreach ($results as $key => $result) {
       $token_phid = $result->getTokenPHID();
 
       $token = idx($tokens, $token_phid);
       if (!$token) {
         $this->didRejectResult($result);
         unset($results[$key]);
         continue;
       }
 
       $result->attachToken($token);
     }
 
     return $results;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorTokensApplication';
   }
 
 }
diff --git a/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php b/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
index 4f6f45bea7..eb4d4d8174 100644
--- a/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
+++ b/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
@@ -1,123 +1,119 @@
 <?php
 
 abstract class PhabricatorApplicationTransactionCommentQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $authorPHIDs;
   private $phids;
   private $transactionPHIDs;
   private $isDeleted;
   private $hasTransaction;
 
   abstract protected function newApplicationTransactionCommentTemplate();
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withTransactionPHIDs(array $transaction_phids) {
     $this->transactionPHIDs = $transaction_phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $phids) {
     $this->authorPHIDs = $phids;
     return $this;
   }
 
   public function withIsDeleted($deleted) {
     $this->isDeleted = $deleted;
     return $this;
   }
 
   public function withHasTransaction($has_transaction) {
     $this->hasTransaction = $has_transaction;
     return $this;
   }
 
   public function newResultObject() {
     return $this->newApplicationTransactionCommentTemplate();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
     $alias = $this->getPrimaryTableAlias();
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         '%T.id IN (%Ld)',
         $alias,
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         '%T.phid IN (%Ls)',
         $alias,
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         '%T.authorPHID IN (%Ls)',
         $alias,
         $this->authorPHIDs);
     }
 
     if ($this->transactionPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         '%T.transactionPHID IN (%Ls)',
         $alias,
         $this->transactionPHIDs);
     }
 
     if ($this->isDeleted !== null) {
       $where[] = qsprintf(
         $conn,
         '%T.isDeleted = %d',
         $alias,
         (int)$this->isDeleted);
     }
 
     if ($this->hasTransaction !== null) {
       if ($this->hasTransaction) {
         $where[] = qsprintf(
           $conn,
           '%T.transactionPHID IS NOT NULL',
           $alias);
       } else {
         $where[] = qsprintf(
           $conn,
           '%T.transactionPHID IS NULL',
           $alias);
       }
     }
 
     return $where;
   }
 
   protected function getPrimaryTableAlias() {
     return 'xcomment';
   }
 
   public function getQueryApplicationClass() {
     // TODO: Figure out the app via the template?
     return null;
   }
 
 }
diff --git a/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php b/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php
index 3e9643a7fc..2001fec0c7 100644
--- a/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php
+++ b/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php
@@ -1,51 +1,47 @@
 <?php
 
 final class PhabricatorXHProfSampleQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorXHProfSample();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorXHProfApplication';
   }
 
 }
diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php
index 32a9419a33..b359157e06 100644
--- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php
+++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php
@@ -1,106 +1,102 @@
 <?php
 
 final class PhabricatorWorkerBulkJobQuery
   extends PhabricatorCursorPagedPolicyAwareQuery {
 
   private $ids;
   private $phids;
   private $authorPHIDs;
   private $bulkJobTypes;
   private $statuses;
 
   public function withIDs(array $ids) {
     $this->ids = $ids;
     return $this;
   }
 
   public function withPHIDs(array $phids) {
     $this->phids = $phids;
     return $this;
   }
 
   public function withAuthorPHIDs(array $author_phids) {
     $this->authorPHIDs = $author_phids;
     return $this;
   }
 
   public function withBulkJobTypes(array $job_types) {
     $this->bulkJobTypes = $job_types;
     return $this;
   }
 
   public function withStatuses(array $statuses) {
     $this->statuses = $statuses;
     return $this;
   }
 
   public function newResultObject() {
     return new PhabricatorWorkerBulkJob();
   }
 
-  protected function loadPage() {
-    return $this->loadStandardPage($this->newResultObject());
-  }
-
   protected function willFilterPage(array $page) {
     $map = PhabricatorWorkerBulkJobType::getAllJobTypes();
 
     foreach ($page as $key => $job) {
       $implementation = idx($map, $job->getJobTypeKey());
       if (!$implementation) {
         $this->didRejectResult($job);
         unset($page[$key]);
         continue;
       }
       $job->attachJobImplementation($implementation);
     }
 
     return $page;
   }
 
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = parent::buildWhereClauseParts($conn);
 
     if ($this->ids !== null) {
       $where[] = qsprintf(
         $conn,
         'id IN (%Ld)',
         $this->ids);
     }
 
     if ($this->phids !== null) {
       $where[] = qsprintf(
         $conn,
         'phid IN (%Ls)',
         $this->phids);
     }
 
     if ($this->authorPHIDs !== null) {
       $where[] = qsprintf(
         $conn,
         'authorPHID IN (%Ls)',
         $this->authorPHIDs);
     }
 
     if ($this->bulkJobTypes !== null) {
       $where[] = qsprintf(
         $conn,
         'bulkJobType IN (%Ls)',
         $this->bulkJobTypes);
     }
 
     if ($this->statuses !== null) {
       $where[] = qsprintf(
         $conn,
         'status IN (%Ls)',
         $this->statuses);
     }
 
     return $where;
   }
 
   public function getQueryApplicationClass() {
     return 'PhabricatorDaemonsApplication';
   }
 
 }
diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
index 80791400e0..42ccad3316 100644
--- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
+++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
@@ -1,3265 +1,3283 @@
 <?php
 
 /**
  * A query class which uses cursor-based paging. This paging is much more
  * performant than offset-based paging in the presence of policy filtering.
  *
  * @task cursors Query Cursors
  * @task clauses Building Query Clauses
  * @task appsearch Integration with ApplicationSearch
  * @task customfield Integration with CustomField
  * @task paging Paging
  * @task order Result Ordering
  * @task edgelogic Working with Edge Logic
  * @task spaces Working with Spaces
  */
 abstract class PhabricatorCursorPagedPolicyAwareQuery
   extends PhabricatorPolicyAwareQuery {
 
   private $externalCursorString;
   private $internalCursorObject;
   private $isQueryOrderReversed = false;
   private $rawCursorRow;
 
   private $applicationSearchConstraints = array();
   private $internalPaging;
   private $orderVector;
   private $groupVector;
   private $builtinOrder;
   private $edgeLogicConstraints = array();
   private $edgeLogicConstraintsAreValid = false;
   private $spacePHIDs;
   private $spaceIsArchived;
   private $ngrams = array();
   private $ferretEngine;
   private $ferretTokens = array();
   private $ferretTables = array();
   private $ferretQuery;
   private $ferretMetadata = array();
   private $ngramEngine;
 
   const FULLTEXT_RANK = '_ft_rank';
   const FULLTEXT_MODIFIED = '_ft_epochModified';
   const FULLTEXT_CREATED = '_ft_epochCreated';
 
 /* -(  Cursors  )------------------------------------------------------------ */
 
   protected function newExternalCursorStringForResult($object) {
     if (!($object instanceof LiskDAO)) {
       throw new Exception(
         pht(
           'Expected to be passed a result object of class "LiskDAO" in '.
           '"newExternalCursorStringForResult()", actually passed "%s". '.
           'Return storage objects from "loadPage()" or override '.
           '"newExternalCursorStringForResult()".',
           phutil_describe_type($object)));
     }
 
     return (string)$object->getID();
   }
 
   protected function newInternalCursorFromExternalCursor($cursor) {
     $viewer = $this->getViewer();
 
     $query = newv(get_class($this), array());
 
     $query
       ->setParentQuery($this)
       ->setViewer($viewer);
 
     // We're copying our order vector to the subquery so that the subquery
     // knows it should generate any supplemental information required by the
     // ordering.
 
     // For example, Phriction documents may be ordered by title, but the title
     // isn't a column in the "document" table: the query must JOIN the
     // "content" table to perform the ordering. Passing the ordering to the
     // subquery tells it that we need it to do that JOIN and attach relevant
     // paging information to the internal cursor object.
 
     // We only expect to load a single result, so the actual result order does
     // not matter. We only want the internal cursor for that result to look
     // like a cursor this parent query would generate.
     $query->setOrderVector($this->getOrderVector());
 
     $this->applyExternalCursorConstraintsToQuery($query, $cursor);
 
     // If we have a Ferret fulltext query, copy it to the subquery so that we
     // generate ranking columns appropriately, and compute the correct object
     // ranking score for the current query.
     if ($this->ferretEngine) {
       $query->withFerretConstraint($this->ferretEngine, $this->ferretTokens);
     }
 
     // We're executing the subquery normally to make sure the viewer can
     // actually see the object, and that it's a completely valid object which
     // passes all filtering and policy checks. You aren't allowed to use an
     // object you can't see as a cursor, since this can leak information.
     $result = $query->executeOne();
     if (!$result) {
       $this->throwCursorException(
         pht(
           'Cursor "%s" does not identify a valid object in query "%s".',
           $cursor,
           get_class($this)));
     }
 
     // Now that we made sure the viewer can actually see the object the
     // external cursor identifies, return the internal cursor the query
     // generated as a side effect while loading the object.
     return $query->getInternalCursorObject();
   }
 
   final protected function throwCursorException($message) {
     throw new PhabricatorInvalidQueryCursorException($message);
   }
 
   protected function applyExternalCursorConstraintsToQuery(
     PhabricatorCursorPagedPolicyAwareQuery $subquery,
     $cursor) {
     $subquery->withIDs(array($cursor));
   }
 
   protected function newPagingMapFromCursorObject(
     PhabricatorQueryCursor $cursor,
     array $keys) {
 
     $object = $cursor->getObject();
 
     return $this->newPagingMapFromPartialObject($object);
   }
 
   protected function newPagingMapFromPartialObject($object) {
     return array(
       'id' => (int)$object->getID(),
     );
   }
 
   private function getExternalCursorStringForResult($object) {
     $cursor = $this->newExternalCursorStringForResult($object);
 
     if (!is_string($cursor)) {
       throw new Exception(
         pht(
           'Expected "newExternalCursorStringForResult()"  in class "%s" to '.
           'return a string, but got "%s".',
           get_class($this),
           phutil_describe_type($cursor)));
     }
 
     return $cursor;
   }
 
   final protected function getExternalCursorString() {
     return $this->externalCursorString;
   }
 
   private function setExternalCursorString($external_cursor) {
     $this->externalCursorString = $external_cursor;
     return $this;
   }
 
   final protected function getIsQueryOrderReversed() {
     return $this->isQueryOrderReversed;
   }
 
   final protected function setIsQueryOrderReversed($is_reversed) {
     $this->isQueryOrderReversed = $is_reversed;
     return $this;
   }
 
   private function getInternalCursorObject() {
     return $this->internalCursorObject;
   }
 
   private function setInternalCursorObject(
     PhabricatorQueryCursor $cursor) {
     $this->internalCursorObject = $cursor;
     return $this;
   }
 
   private function getInternalCursorFromExternalCursor(
     $cursor_string) {
 
     $cursor_object = $this->newInternalCursorFromExternalCursor($cursor_string);
 
     if (!($cursor_object instanceof PhabricatorQueryCursor)) {
       throw new Exception(
         pht(
           'Expected "newInternalCursorFromExternalCursor()" to return an '.
           'object of class "PhabricatorQueryCursor", but got "%s" (in '.
           'class "%s").',
           phutil_describe_type($cursor_object),
           get_class($this)));
     }
 
     return $cursor_object;
   }
 
   private function getPagingMapFromCursorObject(
     PhabricatorQueryCursor $cursor,
     array $keys) {
 
     $map = $this->newPagingMapFromCursorObject($cursor, $keys);
 
     if (!is_array($map)) {
       throw new Exception(
         pht(
           'Expected "newPagingMapFromCursorObject()" to return a map of '.
           'paging values, but got "%s" (in class "%s").',
           phutil_describe_type($map),
           get_class($this)));
     }
 
     if ($this->supportsFerretEngine()) {
       if ($this->hasFerretOrder()) {
         $map += array(
           'rank' =>
             $cursor->getRawRowProperty(self::FULLTEXT_RANK),
           'fulltext-modified' =>
             $cursor->getRawRowProperty(self::FULLTEXT_MODIFIED),
           'fulltext-created' =>
             $cursor->getRawRowProperty(self::FULLTEXT_CREATED),
         );
       }
     }
 
     foreach ($keys as $key) {
       if (!array_key_exists($key, $map)) {
         throw new Exception(
           pht(
             'Map returned by "newPagingMapFromCursorObject()" in class "%s" '.
             'omits required key "%s".',
             get_class($this),
             $key));
       }
     }
 
     return $map;
   }
 
   final protected function nextPage(array $page) {
     if (!$page) {
       return;
     }
 
     $cursor = id(new PhabricatorQueryCursor())
       ->setObject(last($page));
 
     if ($this->rawCursorRow) {
       $cursor->setRawRow($this->rawCursorRow);
     }
 
     $this->setInternalCursorObject($cursor);
   }
 
   final public function getFerretMetadata() {
     if (!$this->supportsFerretEngine()) {
       throw new Exception(
         pht(
           'Unable to retrieve Ferret engine metadata, this class ("%s") does '.
           'not support the Ferret engine.',
           get_class($this)));
     }
 
     return $this->ferretMetadata;
   }
 
+  protected function loadPage() {
+    $object = $this->newResultObject();
+
+    if (!$object instanceof PhabricatorLiskDAO) {
+      throw new Exception(
+        pht(
+          'Query class ("%s") did not return the correct type of object '.
+          'from "newResultObject()" (expected a subclass of '.
+          '"PhabricatorLiskDAO", found "%s"). Return an object of the '.
+          'expected type (this is common), or implement a custom '.
+          '"loadPage()" method (this is unusual in modern code).',
+          get_class($this),
+          phutil_describe_type($object)));
+    }
+
+    return $this->loadStandardPage($object);
+  }
+
   protected function loadStandardPage(PhabricatorLiskDAO $table) {
     $rows = $this->loadStandardPageRows($table);
     return $table->loadAllFromArray($rows);
   }
 
   protected function loadStandardPageRows(PhabricatorLiskDAO $table) {
     $conn = $table->establishConnection('r');
     return $this->loadStandardPageRowsWithConnection(
       $conn,
       $table->getTableName());
   }
 
   protected function loadStandardPageRowsWithConnection(
     AphrontDatabaseConnection $conn,
     $table_name) {
 
     $query = $this->buildStandardPageQuery($conn, $table_name);
 
     $rows = queryfx_all($conn, '%Q', $query);
     $rows = $this->didLoadRawRows($rows);
 
     return $rows;
   }
 
   protected function buildStandardPageQuery(
     AphrontDatabaseConnection $conn,
     $table_name) {
 
     $table_alias = $this->getPrimaryTableAlias();
     if ($table_alias === null) {
       $table_alias = qsprintf($conn, '');
     } else {
       $table_alias = qsprintf($conn, '%T', $table_alias);
     }
 
     return qsprintf(
       $conn,
       '%Q FROM %T %Q %Q %Q %Q %Q %Q %Q',
       $this->buildSelectClause($conn),
       $table_name,
       $table_alias,
       $this->buildJoinClause($conn),
       $this->buildWhereClause($conn),
       $this->buildGroupClause($conn),
       $this->buildHavingClause($conn),
       $this->buildOrderClause($conn),
       $this->buildLimitClause($conn));
   }
 
   protected function didLoadRawRows(array $rows) {
     $this->rawCursorRow = last($rows);
 
     if ($this->ferretEngine) {
       foreach ($rows as $row) {
         $phid = $row['phid'];
 
         $metadata = id(new PhabricatorFerretMetadata())
           ->setPHID($phid)
           ->setEngine($this->ferretEngine)
           ->setRelevance(idx($row, self::FULLTEXT_RANK));
 
         $this->ferretMetadata[$phid] = $metadata;
 
         unset($row[self::FULLTEXT_RANK]);
         unset($row[self::FULLTEXT_MODIFIED]);
         unset($row[self::FULLTEXT_CREATED]);
       }
     }
 
     return $rows;
   }
 
   final protected function buildLimitClause(AphrontDatabaseConnection $conn) {
     if ($this->shouldLimitResults()) {
       $limit = $this->getRawResultLimit();
       if ($limit) {
         return qsprintf($conn, 'LIMIT %d', $limit);
       }
     }
 
     return qsprintf($conn, '');
   }
 
   protected function shouldLimitResults() {
     return true;
   }
 
   final protected function didLoadResults(array $results) {
     if ($this->getIsQueryOrderReversed()) {
       $results = array_reverse($results, $preserve_keys = true);
     }
 
     return $results;
   }
 
   final public function newIterator() {
     return new PhabricatorQueryIterator($this);
   }
 
   final public function executeWithCursorPager(AphrontCursorPagerView $pager) {
     $limit = $pager->getPageSize();
 
     $this->setLimit($limit + 1);
 
     $after_id = phutil_string_cast($pager->getAfterID());
     $before_id = phutil_string_cast($pager->getBeforeID());
 
     if (phutil_nonempty_string($after_id)) {
       $this->setExternalCursorString($after_id);
     } else if (phutil_nonempty_string($before_id)) {
       $this->setExternalCursorString($before_id);
       $this->setIsQueryOrderReversed(true);
     }
 
     $results = $this->execute();
     $count = count($results);
 
     $sliced_results = $pager->sliceResults($results);
     if ($sliced_results) {
 
       // If we have results, generate external-facing cursors from the visible
       // results. This stops us from leaking any internal details about objects
       // which we loaded but which were not visible to the viewer.
 
       if ($pager->getBeforeID() || ($count > $limit)) {
         $last_object = last($sliced_results);
         $cursor = $this->getExternalCursorStringForResult($last_object);
         $pager->setNextPageID($cursor);
       }
 
       if ($pager->getAfterID() ||
          ($pager->getBeforeID() && ($count > $limit))) {
         $head_object = head($sliced_results);
         $cursor = $this->getExternalCursorStringForResult($head_object);
         $pager->setPrevPageID($cursor);
       }
     }
 
     return $sliced_results;
   }
 
 
   /**
    * Return the alias this query uses to identify the primary table.
    *
    * Some automatic query constructions may need to be qualified with a table
    * alias if the query performs joins which make column names ambiguous. If
    * this is the case, return the alias for the primary table the query
    * uses; generally the object table which has `id` and `phid` columns.
    *
    * @return string Alias for the primary table.
    */
   protected function getPrimaryTableAlias() {
     return null;
   }
 
   public function newResultObject() {
     return null;
   }
 
 
 /* -(  Building Query Clauses  )--------------------------------------------- */
 
 
   /**
    * @task clauses
    */
   protected function buildSelectClause(AphrontDatabaseConnection $conn) {
     $parts = $this->buildSelectClauseParts($conn);
     return $this->formatSelectClause($conn, $parts);
   }
 
 
   /**
    * @task clauses
    */
   protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) {
     $select = array();
 
     $alias = $this->getPrimaryTableAlias();
     if ($alias) {
       $select[] = qsprintf($conn, '%T.*', $alias);
     } else {
       $select[] = qsprintf($conn, '*');
     }
 
     $select[] = $this->buildEdgeLogicSelectClause($conn);
     $select[] = $this->buildFerretSelectClause($conn);
 
     return $select;
   }
 
 
   /**
    * @task clauses
    */
   protected function buildJoinClause(AphrontDatabaseConnection $conn) {
     $joins = $this->buildJoinClauseParts($conn);
     return $this->formatJoinClause($conn, $joins);
   }
 
 
   /**
    * @task clauses
    */
   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
     $joins = array();
     $joins[] = $this->buildEdgeLogicJoinClause($conn);
     $joins[] = $this->buildApplicationSearchJoinClause($conn);
     $joins[] = $this->buildNgramsJoinClause($conn);
     $joins[] = $this->buildFerretJoinClause($conn);
     return $joins;
   }
 
 
   /**
    * @task clauses
    */
   protected function buildWhereClause(AphrontDatabaseConnection $conn) {
     $where = $this->buildWhereClauseParts($conn);
     return $this->formatWhereClause($conn, $where);
   }
 
 
   /**
    * @task clauses
    */
   protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
     $where = array();
     $where[] = $this->buildPagingWhereClause($conn);
     $where[] = $this->buildEdgeLogicWhereClause($conn);
     $where[] = $this->buildSpacesWhereClause($conn);
     $where[] = $this->buildNgramsWhereClause($conn);
     $where[] = $this->buildFerretWhereClause($conn);
     $where[] = $this->buildApplicationSearchWhereClause($conn);
     return $where;
   }
 
 
   /**
    * @task clauses
    */
   protected function buildHavingClause(AphrontDatabaseConnection $conn) {
     $having = $this->buildHavingClauseParts($conn);
     $having[] = $this->buildPagingHavingClause($conn);
     return $this->formatHavingClause($conn, $having);
   }
 
 
   /**
    * @task clauses
    */
   protected function buildHavingClauseParts(AphrontDatabaseConnection $conn) {
     $having = array();
     $having[] = $this->buildEdgeLogicHavingClause($conn);
     return $having;
   }
 
 
   /**
    * @task clauses
    */
   protected function buildGroupClause(AphrontDatabaseConnection $conn) {
     if (!$this->shouldGroupQueryResultRows()) {
       return qsprintf($conn, '');
     }
 
     return qsprintf(
       $conn,
       'GROUP BY %Q',
       $this->getApplicationSearchObjectPHIDColumn($conn));
   }
 
 
   /**
    * @task clauses
    */
   protected function shouldGroupQueryResultRows() {
     if ($this->shouldGroupEdgeLogicResultRows()) {
       return true;
     }
 
     if ($this->getApplicationSearchMayJoinMultipleRows()) {
       return true;
     }
 
     if ($this->shouldGroupNgramResultRows()) {
       return true;
     }
 
     if ($this->shouldGroupFerretResultRows()) {
       return true;
     }
 
     return false;
   }
 
 
 
 /* -(  Paging  )------------------------------------------------------------- */
 
 
   private function buildPagingWhereClause(AphrontDatabaseConnection $conn) {
     if ($this->shouldPageWithHavingClause()) {
       return null;
     }
 
     return $this->buildPagingClause($conn);
   }
 
   private function buildPagingHavingClause(AphrontDatabaseConnection $conn) {
     if (!$this->shouldPageWithHavingClause()) {
       return null;
     }
 
     return $this->buildPagingClause($conn);
   }
 
   private function shouldPageWithHavingClause() {
     // If any of the paging conditions reference dynamic columns, we need to
     // put the paging conditions in a "HAVING" clause instead of a "WHERE"
     // clause.
 
     // For example, this happens when paging on the Ferret "rank" column,
     // since the "rank" value is computed dynamically in the SELECT statement.
 
     $orderable = $this->getOrderableColumns();
     $vector = $this->getOrderVector();
 
     foreach ($vector as $order) {
       $key = $order->getOrderKey();
       $column = $orderable[$key];
 
       if (!empty($column['having'])) {
         return true;
       }
     }
 
     return false;
   }
 
   /**
    * @task paging
    */
   protected function buildPagingClause(AphrontDatabaseConnection $conn) {
     $orderable = $this->getOrderableColumns();
     $vector = $this->getQueryableOrderVector();
 
     // If we don't have a cursor object yet, it means we're trying to load
     // the first result page. We may need to build a cursor object from the
     // external string, or we may not need a paging clause yet.
     $cursor_object = $this->getInternalCursorObject();
     if (!$cursor_object) {
       $external_cursor = $this->getExternalCursorString();
       if ($external_cursor !== null) {
         $cursor_object = $this->getInternalCursorFromExternalCursor(
           $external_cursor);
       }
     }
 
     // If we still don't have a cursor object, this is the first result page
     // and we aren't paging it. We don't need to build a paging clause.
     if (!$cursor_object) {
       return qsprintf($conn, '');
     }
 
     $reversed = $this->getIsQueryOrderReversed();
 
     $keys = array();
     foreach ($vector as $order) {
       $keys[] = $order->getOrderKey();
     }
     $keys = array_fuse($keys);
 
     $value_map = $this->getPagingMapFromCursorObject(
       $cursor_object,
       $keys);
 
     $columns = array();
     foreach ($vector as $order) {
       $key = $order->getOrderKey();
 
       $column = $orderable[$key];
       $column['value'] = $value_map[$key];
 
       // If the vector component is reversed, we need to reverse whatever the
       // order of the column is.
       if ($order->getIsReversed()) {
         $column['reverse'] = !idx($column, 'reverse', false);
       }
 
       $columns[] = $column;
     }
 
     return $this->buildPagingClauseFromMultipleColumns(
       $conn,
       $columns,
       array(
         'reversed' => $reversed,
       ));
   }
 
 
   /**
    * Simplifies the task of constructing a paging clause across multiple
    * columns. In the general case, this looks like:
    *
    *   A > a OR (A = a AND B > b) OR (A = a AND B = b AND C > c)
    *
    * To build a clause, specify the name, type, and value of each column
    * to include:
    *
    *   $this->buildPagingClauseFromMultipleColumns(
    *     $conn_r,
    *     array(
    *       array(
    *         'table' => 't',
    *         'column' => 'title',
    *         'type' => 'string',
    *         'value' => $cursor->getTitle(),
    *         'reverse' => true,
    *       ),
    *       array(
    *         'table' => 't',
    *         'column' => 'id',
    *         'type' => 'int',
    *         'value' => $cursor->getID(),
    *       ),
    *     ),
    *     array(
    *       'reversed' => $is_reversed,
    *     ));
    *
    * This method will then return a composable clause for inclusion in WHERE.
    *
    * @param AphrontDatabaseConnection Connection query will execute on.
    * @param list<map> Column description dictionaries.
    * @param map Additional construction options.
    * @return string Query clause.
    * @task paging
    */
   final protected function buildPagingClauseFromMultipleColumns(
     AphrontDatabaseConnection $conn,
     array $columns,
     array $options) {
 
     foreach ($columns as $column) {
       PhutilTypeSpec::checkMap(
         $column,
         array(
           'table' => 'optional string|null',
           'column' => 'string',
           'value' => 'wild',
           'type' => 'string',
           'reverse' => 'optional bool',
           'unique' => 'optional bool',
           'null' => 'optional string|null',
           'requires-ferret' => 'optional bool',
           'having' => 'optional bool',
         ));
     }
 
     PhutilTypeSpec::checkMap(
       $options,
       array(
         'reversed' => 'optional bool',
       ));
 
     $is_query_reversed = idx($options, 'reversed', false);
 
     $clauses = array();
     $accumulated = array();
     $last_key = last_key($columns);
     foreach ($columns as $key => $column) {
       $type = $column['type'];
 
       $null = idx($column, 'null');
       if ($column['value'] === null) {
         if ($null) {
           $value = null;
         } else {
           throw new Exception(
             pht(
               'Column "%s" has null value, but does not specify a null '.
               'behavior.',
               $key));
         }
       } else {
         switch ($type) {
           case 'int':
             $value = qsprintf($conn, '%d', $column['value']);
             break;
           case 'float':
             $value = qsprintf($conn, '%f', $column['value']);
             break;
           case 'string':
             $value = qsprintf($conn, '%s', $column['value']);
             break;
           default:
             throw new Exception(
               pht(
                 'Column "%s" has unknown column type "%s".',
                 $column['column'],
                 $type));
         }
       }
 
       $is_column_reversed = idx($column, 'reverse', false);
       $reverse = ($is_query_reversed xor $is_column_reversed);
 
       $clause = $accumulated;
 
       $table_name = idx($column, 'table');
       $column_name = $column['column'];
       if ($table_name !== null) {
         $field = qsprintf($conn, '%T.%T', $table_name, $column_name);
       } else {
         $field = qsprintf($conn, '%T', $column_name);
       }
 
       $parts = array();
       if ($null) {
         $can_page_if_null = ($null === 'head');
         $can_page_if_nonnull = ($null === 'tail');
 
         if ($reverse) {
           $can_page_if_null = !$can_page_if_null;
           $can_page_if_nonnull = !$can_page_if_nonnull;
         }
 
         $subclause = null;
         if ($can_page_if_null && $value === null) {
           $parts[] = qsprintf(
             $conn,
             '(%Q IS NOT NULL)',
             $field);
         } else if ($can_page_if_nonnull && $value !== null) {
           $parts[] = qsprintf(
             $conn,
             '(%Q IS NULL)',
             $field);
         }
       }
 
       if ($value !== null) {
         $parts[] = qsprintf(
           $conn,
           '%Q %Q %Q',
           $field,
           $reverse ? qsprintf($conn, '>') : qsprintf($conn, '<'),
           $value);
       }
 
       if ($parts) {
         $clause[] = qsprintf($conn, '%LO', $parts);
       }
 
       if ($clause) {
         $clauses[] = qsprintf($conn, '%LA', $clause);
       }
 
       if ($value === null) {
         $accumulated[] = qsprintf(
           $conn,
           '%Q IS NULL',
           $field);
       } else {
         $accumulated[] = qsprintf(
           $conn,
           '%Q = %Q',
           $field,
           $value);
       }
     }
 
     if ($clauses) {
       return qsprintf($conn, '%LO', $clauses);
     }
 
     return qsprintf($conn, '');
   }
 
 
 /* -(  Result Ordering  )---------------------------------------------------- */
 
 
   /**
    * Select a result ordering.
    *
    * This is a high-level method which selects an ordering from a predefined
    * list of builtin orders, as provided by @{method:getBuiltinOrders}. These
    * options are user-facing and not exhaustive, but are generally convenient
    * and meaningful.
    *
    * You can also use @{method:setOrderVector} to specify a low-level ordering
    * across individual orderable columns. This offers greater control but is
    * also more involved.
    *
    * @param string Key of a builtin order supported by this query.
    * @return this
    * @task order
    */
   public function setOrder($order) {
     $aliases = $this->getBuiltinOrderAliasMap();
 
     if (empty($aliases[$order])) {
       throw new Exception(
         pht(
           'Query "%s" does not support a builtin order "%s". Supported orders '.
           'are: %s.',
           get_class($this),
           $order,
           implode(', ', array_keys($aliases))));
     }
 
     $this->builtinOrder = $aliases[$order];
     $this->orderVector = null;
 
     return $this;
   }
 
 
   /**
    * Set a grouping order to apply before primary result ordering.
    *
    * This allows you to preface the query order vector with additional orders,
    * so you can effect "group by" queries while still respecting "order by".
    *
    * This is a high-level method which works alongside @{method:setOrder}. For
    * lower-level control over order vectors, use @{method:setOrderVector}.
    *
    * @param PhabricatorQueryOrderVector|list<string> List of order keys.
    * @return this
    * @task order
    */
   public function setGroupVector($vector) {
     $this->groupVector = $vector;
     $this->orderVector = null;
 
     return $this;
   }
 
 
   /**
    * Get builtin orders for this class.
    *
    * In application UIs, we want to be able to present users with a small
    * selection of meaningful order options (like "Order by Title") rather than
    * an exhaustive set of column ordering options.
    *
    * Meaningful user-facing orders are often really orders across multiple
    * columns: for example, a "title" ordering is usually implemented as a
    * "title, id" ordering under the hood.
    *
    * Builtin orders provide a mapping from convenient, understandable
    * user-facing orders to implementations.
    *
    * A builtin order should provide these keys:
    *
    *   - `vector` (`list<string>`): The actual order vector to use.
    *   - `name` (`string`): Human-readable order name.
    *
    * @return map<string, wild> Map from builtin order keys to specification.
    * @task order
    */
   public function getBuiltinOrders() {
     $orders = array(
       'newest' => array(
         'vector' => array('id'),
         'name' => pht('Creation (Newest First)'),
         'aliases' => array('created'),
       ),
       'oldest' => array(
         'vector' => array('-id'),
         'name' => pht('Creation (Oldest First)'),
       ),
     );
 
     $object = $this->newResultObject();
     if ($object instanceof PhabricatorCustomFieldInterface) {
       $list = PhabricatorCustomField::getObjectFields(
         $object,
         PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
       foreach ($list->getFields() as $field) {
         $index = $field->buildOrderIndex();
         if (!$index) {
           continue;
         }
 
         $legacy_key = 'custom:'.$field->getFieldKey();
         $modern_key = $field->getModernFieldKey();
 
         $orders[$modern_key] = array(
           'vector' => array($modern_key, 'id'),
           'name' => $field->getFieldName(),
           'aliases' => array($legacy_key),
         );
 
         $orders['-'.$modern_key] = array(
           'vector' => array('-'.$modern_key, '-id'),
           'name' => pht('%s (Reversed)', $field->getFieldName()),
         );
       }
     }
 
     if ($this->supportsFerretEngine()) {
       $orders['relevance'] = array(
         'vector' => array('rank', 'fulltext-modified', 'id'),
         'name' => pht('Relevance'),
       );
     }
 
     return $orders;
   }
 
   public function getBuiltinOrderAliasMap() {
     $orders = $this->getBuiltinOrders();
 
     $map = array();
     foreach ($orders as $key => $order) {
       $keys = array();
       $keys[] = $key;
       foreach (idx($order, 'aliases', array()) as $alias) {
         $keys[] = $alias;
       }
 
       foreach ($keys as $alias) {
         if (isset($map[$alias])) {
           throw new Exception(
             pht(
               'Two builtin orders ("%s" and "%s") define the same key or '.
               'alias ("%s"). Each order alias and key must be unique and '.
               'identify a single order.',
               $key,
               $map[$alias],
               $alias));
         }
         $map[$alias] = $key;
       }
     }
 
     return $map;
   }
 
 
   /**
    * Set a low-level column ordering.
    *
    * This is a low-level method which offers granular control over column
    * ordering. In most cases, applications can more easily use
    * @{method:setOrder} to choose a high-level builtin order.
    *
    * To set an order vector, specify a list of order keys as provided by
    * @{method:getOrderableColumns}.
    *
    * @param PhabricatorQueryOrderVector|list<string> List of order keys.
    * @return this
    * @task order
    */
   public function setOrderVector($vector) {
     $vector = PhabricatorQueryOrderVector::newFromVector($vector);
 
     $orderable = $this->getOrderableColumns();
 
     // Make sure that all the components identify valid columns.
     $unique = array();
     foreach ($vector as $order) {
       $key = $order->getOrderKey();
       if (empty($orderable[$key])) {
         $valid = implode(', ', array_keys($orderable));
         throw new Exception(
           pht(
             'This query ("%s") does not support sorting by order key "%s". '.
             'Supported orders are: %s.',
             get_class($this),
             $key,
             $valid));
       }
 
       $unique[$key] = idx($orderable[$key], 'unique', false);
     }
 
     // Make sure that the last column is unique so that this is a strong
     // ordering which can be used for paging.
     $last = last($unique);
     if ($last !== true) {
       throw new Exception(
         pht(
           'Order vector "%s" is invalid: the last column in an order must '.
           'be a column with unique values, but "%s" is not unique.',
           $vector->getAsString(),
           last_key($unique)));
     }
 
     // Make sure that other columns are not unique; an ordering like "id, name"
     // does not make sense because only "id" can ever have an effect.
     array_pop($unique);
     foreach ($unique as $key => $is_unique) {
       if ($is_unique) {
         throw new Exception(
           pht(
             'Order vector "%s" is invalid: only the last column in an order '.
             'may be unique, but "%s" is a unique column and not the last '.
             'column in the order.',
             $vector->getAsString(),
             $key));
       }
     }
 
     $this->orderVector = $vector;
     return $this;
   }
 
 
   /**
    * Get the effective order vector.
    *
    * @return PhabricatorQueryOrderVector Effective vector.
    * @task order
    */
   protected function getOrderVector() {
     if (!$this->orderVector) {
       if ($this->builtinOrder !== null) {
         $builtin_order = idx($this->getBuiltinOrders(), $this->builtinOrder);
         $vector = $builtin_order['vector'];
       } else {
         $vector = $this->getDefaultOrderVector();
       }
 
       if ($this->groupVector) {
         $group = PhabricatorQueryOrderVector::newFromVector($this->groupVector);
         $group->appendVector($vector);
         $vector = $group;
       }
 
       $vector = PhabricatorQueryOrderVector::newFromVector($vector);
 
       // We call setOrderVector() here to apply checks to the default vector.
       // This catches any errors in the implementation.
       $this->setOrderVector($vector);
     }
 
     return $this->orderVector;
   }
 
 
   /**
    * @task order
    */
   protected function getDefaultOrderVector() {
     return array('id');
   }
 
 
   /**
    * @task order
    */
   public function getOrderableColumns() {
     $cache = PhabricatorCaches::getRequestCache();
     $class = get_class($this);
     $cache_key = 'query.orderablecolumns.'.$class;
 
     $columns = $cache->getKey($cache_key);
     if ($columns !== null) {
       return $columns;
     }
 
     $columns = array(
       'id' => array(
         'table' => $this->getPrimaryTableAlias(),
         'column' => 'id',
         'reverse' => false,
         'type' => 'int',
         'unique' => true,
       ),
     );
 
     $object = $this->newResultObject();
     if ($object instanceof PhabricatorCustomFieldInterface) {
       $list = PhabricatorCustomField::getObjectFields(
         $object,
         PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
       foreach ($list->getFields() as $field) {
         $index = $field->buildOrderIndex();
         if (!$index) {
           continue;
         }
 
         $digest = $field->getFieldIndex();
 
         $key = $field->getModernFieldKey();
 
         $columns[$key] = array(
           'table' => 'appsearch_order_'.$digest,
           'column' => 'indexValue',
           'type' => $index->getIndexValueType(),
           'null' => 'tail',
           'customfield' => true,
           'customfield.index.table' => $index->getTableName(),
           'customfield.index.key' => $digest,
         );
       }
     }
 
     if ($this->supportsFerretEngine()) {
       $columns['rank'] = array(
         'table' => null,
         'column' => self::FULLTEXT_RANK,
         'type' => 'int',
         'requires-ferret' => true,
         'having' => true,
       );
       $columns['fulltext-created'] = array(
         'table' => null,
         'column' => self::FULLTEXT_CREATED,
         'type' => 'int',
         'requires-ferret' => true,
       );
       $columns['fulltext-modified'] = array(
         'table' => null,
         'column' => self::FULLTEXT_MODIFIED,
         'type' => 'int',
         'requires-ferret' => true,
       );
     }
 
     $cache->setKey($cache_key, $columns);
 
     return $columns;
   }
 
 
   /**
    * @task order
    */
   final protected function buildOrderClause(
     AphrontDatabaseConnection $conn,
     $for_union = false) {
 
     $orderable = $this->getOrderableColumns();
     $vector = $this->getQueryableOrderVector();
 
     $parts = array();
     foreach ($vector as $order) {
       $part = $orderable[$order->getOrderKey()];
 
       if ($order->getIsReversed()) {
         $part['reverse'] = !idx($part, 'reverse', false);
       }
       $parts[] = $part;
     }
 
     return $this->formatOrderClause($conn, $parts, $for_union);
   }
 
   /**
    * @task order
    */
   private function getQueryableOrderVector() {
     $vector = $this->getOrderVector();
     $orderable = $this->getOrderableColumns();
 
     $keep = array();
     foreach ($vector as $order) {
       $column = $orderable[$order->getOrderKey()];
 
       // If this is a Ferret fulltext column but the query doesn't actually
       // have a fulltext query, we'll skip most of the Ferret stuff and won't
       // actually have the columns in the result set. Just skip them.
       if (!empty($column['requires-ferret'])) {
         if (!$this->getFerretTokens()) {
           continue;
         }
       }
 
       $keep[] = $order->getAsScalar();
     }
 
     return PhabricatorQueryOrderVector::newFromVector($keep);
   }
 
   /**
    * @task order
    */
   protected function formatOrderClause(
     AphrontDatabaseConnection $conn,
     array $parts,
     $for_union = false) {
 
     $is_query_reversed = $this->getIsQueryOrderReversed();
 
     $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;
       }
 
       $table = idx($part, 'table');
 
       // When we're building an ORDER BY clause for a sequence of UNION
       // statements, we can't refer to tables from the subqueries.
       if ($for_union) {
         $table = null;
       }
 
       $column = $part['column'];
 
       if ($table !== null) {
         $field = qsprintf($conn, '%T.%T', $table, $column);
       } else {
         $field = qsprintf($conn, '%T', $column);
       }
 
       $null = idx($part, 'null');
       if ($null) {
         switch ($null) {
           case 'head':
             $null_field = qsprintf($conn, '(%Q IS NULL)', $field);
             break;
           case 'tail':
             $null_field = qsprintf($conn, '(%Q IS NOT NULL)', $field);
             break;
           default:
             throw new Exception(
               pht(
                 'NULL value "%s" is invalid. Valid values are "head" and '.
                 '"tail".',
                 $null));
         }
 
         if ($descending) {
           $sql[] = qsprintf($conn, '%Q DESC', $null_field);
         } else {
           $sql[] = qsprintf($conn, '%Q ASC', $null_field);
         }
       }
 
       if ($descending) {
         $sql[] = qsprintf($conn, '%Q DESC', $field);
       } else {
         $sql[] = qsprintf($conn, '%Q ASC', $field);
       }
     }
 
     return qsprintf($conn, 'ORDER BY %LQ', $sql);
   }
 
 
 /* -(  Application Search  )------------------------------------------------- */
 
 
   /**
    * Constrain the query with an ApplicationSearch index, requiring field values
    * contain at least one of the values in a set.
    *
    * This constraint can build the most common types of queries, like:
    *
    *   - Find users with shirt sizes "X" or "XL".
    *   - Find shoes with size "13".
    *
    * @param PhabricatorCustomFieldIndexStorage Table where the index is stored.
    * @param string|list<string> One or more values to filter by.
    * @return this
    * @task appsearch
    */
   public function withApplicationSearchContainsConstraint(
     PhabricatorCustomFieldIndexStorage $index,
     $value) {
 
     $values = (array)$value;
 
     $data_values = array();
     $constraint_values = array();
     foreach ($values as $value) {
       if ($value instanceof PhabricatorQueryConstraint) {
         $constraint_values[] = $value;
       } else {
         $data_values[] = $value;
       }
     }
 
     $alias = 'appsearch_'.count($this->applicationSearchConstraints);
 
     $this->applicationSearchConstraints[] = array(
       'type'  => $index->getIndexValueType(),
       'cond'  => '=',
       'table' => $index->getTableName(),
       'index' => $index->getIndexKey(),
       'alias' => $alias,
       'value' => $values,
       'data' => $data_values,
       'constraints' => $constraint_values,
     );
 
     return $this;
   }
 
 
   /**
    * Constrain the query with an ApplicationSearch index, requiring values
    * exist in a given range.
    *
    * This constraint is useful for expressing date ranges:
    *
    *   - Find events between July 1st and July 7th.
    *
    * The ends of the range are inclusive, so a `$min` of `3` and a `$max` of
    * `5` will match fields with values `3`, `4`, or `5`. Providing `null` for
    * either end of the range will leave that end of the constraint open.
    *
    * @param PhabricatorCustomFieldIndexStorage Table where the index is stored.
    * @param int|null Minimum permissible value, inclusive.
    * @param int|null Maximum permissible value, inclusive.
    * @return this
    * @task appsearch
    */
   public function withApplicationSearchRangeConstraint(
     PhabricatorCustomFieldIndexStorage $index,
     $min,
     $max) {
 
     $index_type = $index->getIndexValueType();
     if ($index_type != 'int') {
       throw new Exception(
         pht(
           'Attempting to apply a range constraint to a field with index type '.
           '"%s", expected type "%s".',
           $index_type,
           'int'));
     }
 
     $alias = 'appsearch_'.count($this->applicationSearchConstraints);
 
     $this->applicationSearchConstraints[] = array(
       'type' => $index->getIndexValueType(),
       'cond' => 'range',
       'table' => $index->getTableName(),
       'index' => $index->getIndexKey(),
       'alias' => $alias,
       'value' => array($min, $max),
       'data' => null,
       'constraints' => null,
     );
 
     return $this;
   }
 
 
   /**
    * Get the name of the query's primary object PHID column, for constructing
    * JOIN clauses. Normally (and by default) this is just `"phid"`, but it may
    * be something more exotic.
    *
    * See @{method:getPrimaryTableAlias} if the column needs to be qualified with
    * a table alias.
    *
    * @param AphrontDatabaseConnection Connection executing queries.
    * @return PhutilQueryString Column name.
    * @task appsearch
    */
   protected function getApplicationSearchObjectPHIDColumn(
     AphrontDatabaseConnection $conn) {
 
     if ($this->getPrimaryTableAlias()) {
       return qsprintf($conn, '%T.phid', $this->getPrimaryTableAlias());
     } else {
       return qsprintf($conn, 'phid');
     }
   }
 
 
   /**
    * Determine if the JOINs built by ApplicationSearch might cause each primary
    * object to return multiple result rows. Generally, this means the query
    * needs an extra GROUP BY clause.
    *
    * @return bool True if the query may return multiple rows for each object.
    * @task appsearch
    */
   protected function getApplicationSearchMayJoinMultipleRows() {
     foreach ($this->applicationSearchConstraints as $constraint) {
       $type = $constraint['type'];
       $value = $constraint['value'];
       $cond = $constraint['cond'];
 
       switch ($cond) {
         case '=':
           switch ($type) {
             case 'string':
             case 'int':
               if (count($value) > 1) {
                 return true;
               }
               break;
             default:
               throw new Exception(pht('Unknown index type "%s"!', $type));
           }
           break;
         case 'range':
           // NOTE: It's possible to write a custom field where multiple rows
           // match a range constraint, but we don't currently ship any in the
           // upstream and I can't immediately come up with cases where this
           // would make sense.
           break;
         default:
           throw new Exception(pht('Unknown constraint condition "%s"!', $cond));
       }
     }
 
     return false;
   }
 
 
   /**
    * Construct a GROUP BY clause appropriate for ApplicationSearch constraints.
    *
    * @param AphrontDatabaseConnection Connection executing the query.
    * @return string Group clause.
    * @task appsearch
    */
   protected function buildApplicationSearchGroupClause(
     AphrontDatabaseConnection $conn) {
 
     if ($this->getApplicationSearchMayJoinMultipleRows()) {
       return qsprintf(
         $conn,
         'GROUP BY %Q',
         $this->getApplicationSearchObjectPHIDColumn($conn));
     } else {
       return qsprintf($conn, '');
     }
   }
 
 
   /**
    * Construct a JOIN clause appropriate for applying ApplicationSearch
    * constraints.
    *
    * @param AphrontDatabaseConnection Connection executing the query.
    * @return string Join clause.
    * @task appsearch
    */
   protected function buildApplicationSearchJoinClause(
     AphrontDatabaseConnection $conn) {
 
     $joins = array();
     foreach ($this->applicationSearchConstraints as $key => $constraint) {
       $table = $constraint['table'];
       $alias = $constraint['alias'];
       $index = $constraint['index'];
       $cond = $constraint['cond'];
       $phid_column = $this->getApplicationSearchObjectPHIDColumn($conn);
       switch ($cond) {
         case '=':
           // Figure out whether we need to do a LEFT JOIN or not. We need to
           // LEFT JOIN if we're going to select "IS NULL" rows.
           $join_type = qsprintf($conn, 'JOIN');
           foreach ($constraint['constraints'] as $query_constraint) {
             $op = $query_constraint->getOperator();
             if ($op === PhabricatorQueryConstraint::OPERATOR_NULL) {
               $join_type = qsprintf($conn, 'LEFT JOIN');
               break;
             }
           }
 
           $joins[] = qsprintf(
             $conn,
             '%Q %T %T ON %T.objectPHID = %Q
               AND %T.indexKey = %s',
             $join_type,
             $table,
             $alias,
             $alias,
             $phid_column,
             $alias,
             $index);
           break;
         case 'range':
           list($min, $max) = $constraint['value'];
           if (($min === null) && ($max === null)) {
             // If there's no actual range constraint, just move on.
             break;
           }
 
           if ($min === null) {
             $constraint_clause = qsprintf(
               $conn,
               '%T.indexValue <= %d',
               $alias,
               $max);
           } else if ($max === null) {
             $constraint_clause = qsprintf(
               $conn,
               '%T.indexValue >= %d',
               $alias,
               $min);
           } else {
             $constraint_clause = qsprintf(
               $conn,
               '%T.indexValue BETWEEN %d AND %d',
               $alias,
               $min,
               $max);
           }
 
           $joins[] = qsprintf(
             $conn,
             'JOIN %T %T ON %T.objectPHID = %Q
               AND %T.indexKey = %s
               AND (%Q)',
             $table,
             $alias,
             $alias,
             $phid_column,
             $alias,
             $index,
             $constraint_clause);
           break;
         default:
           throw new Exception(pht('Unknown constraint condition "%s"!', $cond));
       }
     }
 
     $phid_column = $this->getApplicationSearchObjectPHIDColumn($conn);
     $orderable = $this->getOrderableColumns();
 
     $vector = $this->getOrderVector();
     foreach ($vector as $order) {
       $spec = $orderable[$order->getOrderKey()];
       if (empty($spec['customfield'])) {
         continue;
       }
 
       $table = $spec['customfield.index.table'];
       $alias = $spec['table'];
       $key = $spec['customfield.index.key'];
 
       $joins[] = qsprintf(
         $conn,
         'LEFT JOIN %T %T ON %T.objectPHID = %Q
           AND %T.indexKey = %s',
         $table,
         $alias,
         $alias,
         $phid_column,
         $alias,
         $key);
     }
 
     if ($joins) {
       return qsprintf($conn, '%LJ', $joins);
     } else {
       return qsprintf($conn, '');
     }
   }
 
   /**
    * Construct a WHERE clause appropriate for applying ApplicationSearch
    * constraints.
    *
    * @param AphrontDatabaseConnection Connection executing the query.
    * @return list<string> Where clause parts.
    * @task appsearch
    */
   protected function buildApplicationSearchWhereClause(
     AphrontDatabaseConnection $conn) {
 
     $where = array();
 
     foreach ($this->applicationSearchConstraints as $key => $constraint) {
       $alias = $constraint['alias'];
       $cond = $constraint['cond'];
       $type = $constraint['type'];
 
       $data_values = $constraint['data'];
       $constraint_values = $constraint['constraints'];
 
       $constraint_parts = array();
       switch ($cond) {
         case '=':
           if ($data_values) {
             switch ($type) {
               case 'string':
                 $constraint_parts[] = qsprintf(
                   $conn,
                   '%T.indexValue IN (%Ls)',
                   $alias,
                   $data_values);
                 break;
               case 'int':
                 $constraint_parts[] = qsprintf(
                   $conn,
                   '%T.indexValue IN (%Ld)',
                   $alias,
                   $data_values);
                 break;
               default:
                 throw new Exception(pht('Unknown index type "%s"!', $type));
             }
           }
 
           if ($constraint_values) {
             foreach ($constraint_values as $value) {
               $op = $value->getOperator();
               switch ($op) {
                 case PhabricatorQueryConstraint::OPERATOR_NULL:
                   $constraint_parts[] = qsprintf(
                     $conn,
                     '%T.indexValue IS NULL',
                     $alias);
                   break;
                 case PhabricatorQueryConstraint::OPERATOR_ANY:
                   $constraint_parts[] = qsprintf(
                     $conn,
                     '%T.indexValue IS NOT NULL',
                     $alias);
                   break;
                 default:
                   throw new Exception(
                     pht(
                       'No support for applying operator "%s" against '.
                       'index of type "%s".',
                       $op,
                       $type));
               }
             }
           }
 
           if ($constraint_parts) {
             $where[] = qsprintf($conn, '%LO', $constraint_parts);
           }
           break;
       }
     }
 
     return $where;
   }
 
 
 /* -(  Integration with CustomField  )--------------------------------------- */
 
 
   /**
    * @task customfield
    */
   protected function getPagingValueMapForCustomFields(
     PhabricatorCustomFieldInterface $object) {
 
     // We have to get the current field values on the cursor object.
     $fields = PhabricatorCustomField::getObjectFields(
       $object,
       PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
     $fields->setViewer($this->getViewer());
     $fields->readFieldsFromStorage($object);
 
     $map = array();
     foreach ($fields->getFields() as $field) {
       $map['custom:'.$field->getFieldKey()] = $field->getValueForStorage();
     }
 
     return $map;
   }
 
 
   /**
    * @task customfield
    */
   protected function isCustomFieldOrderKey($key) {
     $prefix = 'custom:';
     return !strncmp($key, $prefix, strlen($prefix));
   }
 
 
 /* -(  Ferret  )------------------------------------------------------------- */
 
 
   public function supportsFerretEngine() {
     $object = $this->newResultObject();
     return ($object instanceof PhabricatorFerretInterface);
   }
 
   public function withFerretQuery(
     PhabricatorFerretEngine $engine,
     PhabricatorSavedQuery $query) {
 
     if (!$this->supportsFerretEngine()) {
       throw new Exception(
         pht(
           'Query ("%s") does not support the Ferret fulltext engine.',
           get_class($this)));
     }
 
     $this->ferretEngine = $engine;
     $this->ferretQuery = $query;
 
     return $this;
   }
 
   public function getFerretTokens() {
     if (!$this->supportsFerretEngine()) {
       throw new Exception(
         pht(
           'Query ("%s") does not support the Ferret fulltext engine.',
           get_class($this)));
     }
 
     return $this->ferretTokens;
   }
 
   public function withFerretConstraint(
     PhabricatorFerretEngine $engine,
     array $fulltext_tokens) {
 
     if (!$this->supportsFerretEngine()) {
       throw new Exception(
         pht(
           'Query ("%s") does not support the Ferret fulltext engine.',
           get_class($this)));
     }
 
     if ($this->ferretEngine) {
       throw new Exception(
         pht(
           'Query may not have multiple fulltext constraints.'));
     }
 
     if (!$fulltext_tokens) {
       return $this;
     }
 
     $this->ferretEngine = $engine;
     $this->ferretTokens = $fulltext_tokens;
 
     $op_absent = PhutilSearchQueryCompiler::OPERATOR_ABSENT;
 
     $default_function = $engine->getDefaultFunctionKey();
     $table_map = array();
     $idx = 1;
     foreach ($this->ferretTokens as $fulltext_token) {
       $raw_token = $fulltext_token->getToken();
 
       $function = $raw_token->getFunction();
       if ($function === null) {
         $function = $default_function;
       }
 
       $function_def = $engine->getFunctionForName($function);
 
       // NOTE: The query compiler guarantees that a query can not make a
       // field both "present" and "absent", so it's safe to just use the
       // first operator we encounter to determine whether the table is
       // optional or not.
 
       $operator = $raw_token->getOperator();
       $is_optional = ($operator === $op_absent);
 
       if (!isset($table_map[$function])) {
         $alias = 'ftfield_'.$idx++;
         $table_map[$function] = array(
           'alias' => $alias,
           'function' => $function_def,
           'optional' => $is_optional,
         );
       }
     }
 
     // Join the title field separately so we can rank results.
     $table_map['rank'] = array(
       'alias' => 'ft_rank',
       'function' => $engine->getFunctionForName('title'),
 
       // See T13345. Not every document has a title, so we want to LEFT JOIN
       // this table to avoid excluding documents with no title that match
       // the query in other fields.
       'optional' => true,
     );
 
     $this->ferretTables = $table_map;
 
     return $this;
   }
 
   protected function buildFerretSelectClause(AphrontDatabaseConnection $conn) {
     $select = array();
 
     if (!$this->supportsFerretEngine()) {
       return $select;
     }
 
     if (!$this->hasFerretOrder()) {
       // We only need to SELECT the virtual rank/relevance columns if we're
       // actually sorting the results by rank.
       return $select;
     }
 
     if (!$this->ferretEngine) {
       $select[] = qsprintf($conn, '0 AS %T', self::FULLTEXT_RANK);
       $select[] = qsprintf($conn, '0 AS %T', self::FULLTEXT_CREATED);
       $select[] = qsprintf($conn, '0 AS %T', self::FULLTEXT_MODIFIED);
       return $select;
     }
 
     $engine = $this->ferretEngine;
     $stemmer = $engine->newStemmer();
 
     $op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
     $op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
     $table_alias = 'ft_rank';
 
     $parts = array();
     foreach ($this->ferretTokens as $fulltext_token) {
       $raw_token = $fulltext_token->getToken();
       $value = $raw_token->getValue();
 
       if ($raw_token->getOperator() == $op_not) {
         // Ignore "not" terms when ranking, since they aren't useful.
         continue;
       }
 
       if ($raw_token->getOperator() == $op_sub) {
         $is_substring = true;
       } else {
         $is_substring = false;
       }
 
       if ($is_substring) {
         $parts[] = qsprintf(
           $conn,
           'IF(%T.rawCorpus LIKE %~, 2, 0)',
           $table_alias,
           $value);
         continue;
       }
 
       if ($raw_token->isQuoted()) {
         $is_quoted = true;
         $is_stemmed = false;
       } else {
         $is_quoted = false;
         $is_stemmed = true;
       }
 
       $term_constraints = array();
 
       $term_value = $engine->newTermsCorpus($value);
 
       $parts[] = qsprintf(
         $conn,
         'IF(%T.termCorpus LIKE %~, 2, 0)',
         $table_alias,
         $term_value);
 
       if ($is_stemmed) {
         $stem_value = $stemmer->stemToken($value);
         $stem_value = $engine->newTermsCorpus($stem_value);
 
         $parts[] = qsprintf(
           $conn,
           'IF(%T.normalCorpus LIKE %~, 1, 0)',
           $table_alias,
           $stem_value);
       }
     }
 
     $parts[] = qsprintf($conn, '%d', 0);
 
     $sum = array_shift($parts);
     foreach ($parts as $part) {
       $sum = qsprintf(
         $conn,
         '%Q + %Q',
         $sum,
         $part);
     }
 
     $select[] = qsprintf(
       $conn,
       '%Q AS %T',
       $sum,
       self::FULLTEXT_RANK);
 
     // See D20297. We select these as real columns in the result set so that
     // constructions like this will work:
     //
     //   ((SELECT ...) UNION (SELECT ...)) ORDER BY ...
     //
     // If the columns aren't part of the result set, the final "ORDER BY" can
     // not act on them.
 
     $select[] = qsprintf(
       $conn,
       'ft_doc.epochCreated AS %T',
       self::FULLTEXT_CREATED);
 
     $select[] = qsprintf(
       $conn,
       'ft_doc.epochModified AS %T',
       self::FULLTEXT_MODIFIED);
 
     return $select;
   }
 
   protected function buildFerretJoinClause(AphrontDatabaseConnection $conn) {
     if (!$this->ferretEngine) {
       return array();
     }
 
     $op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
     $op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
     $op_absent = PhutilSearchQueryCompiler::OPERATOR_ABSENT;
     $op_present = PhutilSearchQueryCompiler::OPERATOR_PRESENT;
 
     $engine = $this->ferretEngine;
     $stemmer = $engine->newStemmer();
 
     $ngram_table = $engine->getNgramsTableName();
     $ngram_engine = $this->getNgramEngine();
 
     $flat = array();
     foreach ($this->ferretTokens as $fulltext_token) {
       $raw_token = $fulltext_token->getToken();
 
       $operator = $raw_token->getOperator();
 
       // If this is a negated term like "-pomegranate", don't join the ngram
       // table since we aren't looking for documents with this term. (We could
       // LEFT JOIN the table and require a NULL row, but this is probably more
       // trouble than it's worth.)
       if ($operator === $op_not) {
         continue;
       }
 
       // Neither the "present" or "absent" operators benefit from joining
       // the ngram table.
       if ($operator === $op_absent || $operator === $op_present) {
         continue;
       }
 
       $value = $raw_token->getValue();
 
       $length = count(phutil_utf8v($value));
 
       if ($raw_token->getOperator() == $op_sub) {
         $is_substring = true;
       } else {
         $is_substring = false;
       }
 
       // If the user specified a substring query for a substring which is
       // shorter than the ngram length, we can't use the ngram index, so
       // don't do a join. We'll fall back to just doing LIKE on the full
       // corpus.
       if ($is_substring) {
         if ($length < 3) {
           continue;
         }
       }
 
       if ($raw_token->isQuoted()) {
         $is_stemmed = false;
       } else {
         $is_stemmed = true;
       }
 
       if ($is_substring) {
         $ngrams = $ngram_engine->getSubstringNgramsFromString($value);
       } else {
         $terms_value = $engine->newTermsCorpus($value);
         $ngrams = $ngram_engine->getTermNgramsFromString($terms_value);
 
         // If this is a stemmed term, only look for ngrams present in both the
         // unstemmed and stemmed variations.
         if ($is_stemmed) {
           // Trim the boundary space characters so the stemmer recognizes this
           // is (or, at least, may be) a normal word and activates.
           $terms_value = trim($terms_value, ' ');
           $stem_value = $stemmer->stemToken($terms_value);
           $stem_ngrams = $ngram_engine->getTermNgramsFromString($stem_value);
           $ngrams = array_intersect($ngrams, $stem_ngrams);
         }
       }
 
       foreach ($ngrams as $ngram) {
         $flat[] = array(
           'table' => $ngram_table,
           'ngram' => $ngram,
         );
       }
     }
 
     // Remove common ngrams, like "the", which occur too frequently in
     // documents to be useful in constraining the query. The best ngrams
     // are obscure sequences which occur in very few documents.
 
     if ($flat) {
       $common_ngrams = queryfx_all(
         $conn,
         'SELECT ngram FROM %T WHERE ngram IN (%Ls)',
         $engine->getCommonNgramsTableName(),
         ipull($flat, 'ngram'));
       $common_ngrams = ipull($common_ngrams, 'ngram', 'ngram');
 
       foreach ($flat as $key => $spec) {
         $ngram = $spec['ngram'];
         if (isset($common_ngrams[$ngram])) {
           unset($flat[$key]);
           continue;
         }
 
         // NOTE: MySQL discards trailing whitespace in CHAR(X) columns.
         $trim_ngram = rtrim($ngram, ' ');
         if (isset($common_ngrams[$trim_ngram])) {
           unset($flat[$key]);
           continue;
         }
       }
     }
 
     // MySQL only allows us to join a maximum of 61 tables per query. Each
     // ngram is going to cost us a join toward that limit, so if the user
     // specified a very long query string, just pick 16 of the ngrams
     // at random.
     if (count($flat) > 16) {
       shuffle($flat);
       $flat = array_slice($flat, 0, 16);
     }
 
     $alias = $this->getPrimaryTableAlias();
     if ($alias) {
       $phid_column = qsprintf($conn, '%T.%T', $alias, 'phid');
     } else {
       $phid_column = qsprintf($conn, '%T', 'phid');
     }
 
     $document_table = $engine->getDocumentTableName();
     $field_table = $engine->getFieldTableName();
 
     $joins = array();
     $joins[] = qsprintf(
       $conn,
       'JOIN %T ft_doc ON ft_doc.objectPHID = %Q',
       $document_table,
       $phid_column);
 
     $idx = 1;
     foreach ($flat as $spec) {
       $table = $spec['table'];
       $ngram = $spec['ngram'];
 
       $alias = 'ftngram_'.$idx++;
 
       $joins[] = qsprintf(
         $conn,
         'JOIN %T %T ON %T.documentID = ft_doc.id AND %T.ngram = %s',
         $table,
         $alias,
         $alias,
         $alias,
         $ngram);
     }
 
     $object = $this->newResultObject();
     if (!$object) {
       throw new Exception(
         pht(
           'Query class ("%s") must define "newResultObject()" to use '.
           'Ferret constraints.',
           get_class($this)));
     }
 
     // See T13511. If we have a fulltext query which uses valid field
     // functions, but at least one of the functions applies to a field which
     // the object can never have, the query can never match anything. Detect
     // this and return an empty result set.
 
     // (Even if the query is "field is absent" or "field does not contain
     // such-and-such", the interpretation is that these constraints are
     // not meaningful when applied to an object which can never have the
     // field.)
 
     $functions = ipull($this->ferretTables, 'function');
     $functions = mpull($functions, null, 'getFerretFunctionName');
     foreach ($functions as $function) {
       if (!$function->supportsObject($object)) {
         throw new PhabricatorEmptyQueryException(
           pht(
             'This query uses a fulltext function which this document '.
             'type does not support.'));
       }
     }
 
     foreach ($this->ferretTables as $table) {
       $alias = $table['alias'];
 
       if (empty($table['optional'])) {
         $join_type = qsprintf($conn, 'JOIN');
       } else {
         $join_type = qsprintf($conn, 'LEFT JOIN');
       }
 
       $joins[] = qsprintf(
         $conn,
         '%Q %T %T ON ft_doc.id = %T.documentID
           AND %T.fieldKey = %s',
         $join_type,
         $field_table,
         $alias,
         $alias,
         $alias,
         $table['function']->getFerretFieldKey());
     }
 
     return $joins;
   }
 
   protected function buildFerretWhereClause(AphrontDatabaseConnection $conn) {
     if (!$this->ferretEngine) {
       return array();
     }
 
     $engine = $this->ferretEngine;
     $stemmer = $engine->newStemmer();
     $table_map = $this->ferretTables;
 
     $op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
     $op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
     $op_exact = PhutilSearchQueryCompiler::OPERATOR_EXACT;
     $op_absent = PhutilSearchQueryCompiler::OPERATOR_ABSENT;
     $op_present = PhutilSearchQueryCompiler::OPERATOR_PRESENT;
 
     $where = array();
     $default_function = $engine->getDefaultFunctionKey();
     foreach ($this->ferretTokens as $fulltext_token) {
       $raw_token = $fulltext_token->getToken();
       $value = $raw_token->getValue();
 
       $function = $raw_token->getFunction();
       if ($function === null) {
         $function = $default_function;
       }
 
       $operator = $raw_token->getOperator();
 
       $table_alias = $table_map[$function]['alias'];
 
       // If this is a "field is present" operator, we've already implicitly
       // guaranteed this by JOINing the table. We don't need to do any
       // more work.
       $is_present = ($operator === $op_present);
       if ($is_present) {
         continue;
       }
 
       // If this is a "field is absent" operator, we just want documents
       // which failed to match to a row when we LEFT JOINed the table. This
       // means there's no index for the field.
       $is_absent = ($operator === $op_absent);
       if ($is_absent) {
         $where[] = qsprintf(
           $conn,
           '(%T.rawCorpus IS NULL)',
           $table_alias);
         continue;
       }
 
       $is_not = ($operator === $op_not);
 
       if ($operator == $op_sub) {
         $is_substring = true;
       } else {
         $is_substring = false;
       }
 
       // If we're doing exact search, just test the raw corpus.
       $is_exact = ($operator === $op_exact);
       if ($is_exact) {
         if ($is_not) {
           $where[] = qsprintf(
             $conn,
             '(%T.rawCorpus != %s)',
             $table_alias,
             $value);
         } else {
           $where[] = qsprintf(
             $conn,
             '(%T.rawCorpus = %s)',
             $table_alias,
             $value);
         }
         continue;
       }
 
       // If we're doing substring search, we just match against the raw corpus
       // and we're done.
       if ($is_substring) {
         if ($is_not) {
           $where[] = qsprintf(
             $conn,
             '(%T.rawCorpus NOT LIKE %~)',
             $table_alias,
             $value);
         } else {
           $where[] = qsprintf(
             $conn,
             '(%T.rawCorpus LIKE %~)',
             $table_alias,
             $value);
         }
         continue;
       }
 
       // Otherwise, we need to match against the term corpus and the normal
       // corpus, so that searching for "raw" does not find "strawberry".
       if ($raw_token->isQuoted()) {
         $is_quoted = true;
         $is_stemmed = false;
       } else {
         $is_quoted = false;
         $is_stemmed = true;
       }
 
       // Never stem negated queries, since this can exclude results users
       // did not mean to exclude and generally confuse things.
       if ($is_not) {
         $is_stemmed = false;
       }
 
       $term_constraints = array();
 
       $term_value = $engine->newTermsCorpus($value);
       if ($is_not) {
         $term_constraints[] = qsprintf(
           $conn,
           '(%T.termCorpus NOT LIKE %~)',
           $table_alias,
           $term_value);
       } else {
         $term_constraints[] = qsprintf(
           $conn,
           '(%T.termCorpus LIKE %~)',
           $table_alias,
           $term_value);
       }
 
       if ($is_stemmed) {
         $stem_value = $stemmer->stemToken($value);
         $stem_value = $engine->newTermsCorpus($stem_value);
 
         $term_constraints[] = qsprintf(
           $conn,
           '(%T.normalCorpus LIKE %~)',
           $table_alias,
           $stem_value);
       }
 
       if ($is_not) {
         $where[] = qsprintf(
           $conn,
           '%LA',
           $term_constraints);
       } else if ($is_quoted) {
         $where[] = qsprintf(
           $conn,
           '(%T.rawCorpus LIKE %~ AND %LO)',
           $table_alias,
           $value,
           $term_constraints);
       } else {
         $where[] = qsprintf(
           $conn,
           '%LO',
           $term_constraints);
       }
     }
 
     if ($this->ferretQuery) {
       $query = $this->ferretQuery;
 
       $author_phids = $query->getParameter('authorPHIDs');
       if ($author_phids) {
         $where[] = qsprintf(
           $conn,
           'ft_doc.authorPHID IN (%Ls)',
           $author_phids);
       }
 
       $with_unowned = $query->getParameter('withUnowned');
       $with_any = $query->getParameter('withAnyOwner');
 
       if ($with_any && $with_unowned) {
         throw new PhabricatorEmptyQueryException(
           pht(
             'This query matches only unowned documents owned by anyone, '.
             'which is impossible.'));
       }
 
       $owner_phids = $query->getParameter('ownerPHIDs');
       if ($owner_phids && !$with_any) {
         if ($with_unowned) {
           $where[] = qsprintf(
             $conn,
             'ft_doc.ownerPHID IN (%Ls) OR ft_doc.ownerPHID IS NULL',
             $owner_phids);
         } else {
           $where[] = qsprintf(
             $conn,
             'ft_doc.ownerPHID IN (%Ls)',
             $owner_phids);
         }
       } else if ($with_unowned) {
         $where[] = qsprintf(
           $conn,
           'ft_doc.ownerPHID IS NULL');
       }
 
       if ($with_any) {
         $where[] = qsprintf(
           $conn,
           'ft_doc.ownerPHID IS NOT NULL');
       }
 
       $rel_open = PhabricatorSearchRelationship::RELATIONSHIP_OPEN;
 
       $statuses = $query->getParameter('statuses');
       $is_closed = null;
       if ($statuses) {
         $statuses = array_fuse($statuses);
         if (count($statuses) == 1) {
           if (isset($statuses[$rel_open])) {
             $is_closed = 0;
           } else {
             $is_closed = 1;
           }
         }
       }
 
       if ($is_closed !== null) {
         $where[] = qsprintf(
           $conn,
           'ft_doc.isClosed = %d',
           $is_closed);
       }
     }
 
     return $where;
   }
 
   protected function shouldGroupFerretResultRows() {
     return (bool)$this->ferretTokens;
   }
 
 
 /* -(  Ngrams  )------------------------------------------------------------- */
 
 
   protected function withNgramsConstraint(
     PhabricatorSearchNgrams $index,
     $value) {
 
     if (strlen($value)) {
       $this->ngrams[] = array(
         'index' => $index,
         'value' => $value,
         'length' => count(phutil_utf8v($value)),
       );
     }
 
     return $this;
   }
 
 
   protected function buildNgramsJoinClause(AphrontDatabaseConnection $conn) {
     $ngram_engine = $this->getNgramEngine();
 
     $flat = array();
     foreach ($this->ngrams as $spec) {
       $length = $spec['length'];
 
       if ($length < 3) {
         continue;
       }
 
       $index = $spec['index'];
       $value = $spec['value'];
 
       $ngrams = $ngram_engine->getSubstringNgramsFromString($value);
 
       foreach ($ngrams as $ngram) {
         $flat[] = array(
           'table' => $index->getTableName(),
           'ngram' => $ngram,
         );
       }
     }
 
     if (!$flat) {
       return array();
     }
 
     // MySQL only allows us to join a maximum of 61 tables per query. Each
     // ngram is going to cost us a join toward that limit, so if the user
     // specified a very long query string, just pick 16 of the ngrams
     // at random.
     if (count($flat) > 16) {
       shuffle($flat);
       $flat = array_slice($flat, 0, 16);
     }
 
     $alias = $this->getPrimaryTableAlias();
     if ($alias) {
       $id_column = qsprintf($conn, '%T.%T', $alias, 'id');
     } else {
       $id_column = qsprintf($conn, '%T', 'id');
     }
 
     $idx = 1;
     $joins = array();
     foreach ($flat as $spec) {
       $table = $spec['table'];
       $ngram = $spec['ngram'];
 
       $alias = 'ngm'.$idx++;
 
       $joins[] = qsprintf(
         $conn,
         'JOIN %T %T ON %T.objectID = %Q AND %T.ngram = %s',
         $table,
         $alias,
         $alias,
         $id_column,
         $alias,
         $ngram);
     }
 
     return $joins;
   }
 
 
   protected function buildNgramsWhereClause(AphrontDatabaseConnection $conn) {
     $where = array();
 
     $ngram_engine = $this->getNgramEngine();
 
     foreach ($this->ngrams as $ngram) {
       $index = $ngram['index'];
       $value = $ngram['value'];
 
       $column = $index->getColumnName();
       $alias = $this->getPrimaryTableAlias();
       if ($alias) {
         $column = qsprintf($conn, '%T.%T', $alias, $column);
       } else {
         $column = qsprintf($conn, '%T', $column);
       }
 
       $tokens = $ngram_engine->tokenizeNgramString($value);
 
       foreach ($tokens as $token) {
         $where[] = qsprintf(
           $conn,
           '%Q LIKE %~',
           $column,
           $token);
       }
     }
 
     return $where;
   }
 
 
   protected function shouldGroupNgramResultRows() {
     return (bool)$this->ngrams;
   }
 
   private function getNgramEngine() {
     if (!$this->ngramEngine) {
       $this->ngramEngine = new PhabricatorSearchNgramEngine();
     }
 
     return $this->ngramEngine;
   }
 
 
 /* -(  Edge Logic  )--------------------------------------------------------- */
 
 
   /**
    * Convenience method for specifying edge logic constraints with a list of
    * PHIDs.
    *
    * @param const Edge constant.
    * @param const Constraint operator.
    * @param list<phid> List of PHIDs.
    * @return this
    * @task edgelogic
    */
   public function withEdgeLogicPHIDs($edge_type, $operator, array $phids) {
     $constraints = array();
     foreach ($phids as $phid) {
       $constraints[] = new PhabricatorQueryConstraint($operator, $phid);
     }
 
     return $this->withEdgeLogicConstraints($edge_type, $constraints);
   }
 
 
   /**
    * @return this
    * @task edgelogic
    */
   public function withEdgeLogicConstraints($edge_type, array $constraints) {
     assert_instances_of($constraints, 'PhabricatorQueryConstraint');
 
     $constraints = mgroup($constraints, 'getOperator');
     foreach ($constraints as $operator => $list) {
       foreach ($list as $item) {
         $this->edgeLogicConstraints[$edge_type][$operator][] = $item;
       }
     }
 
     $this->edgeLogicConstraintsAreValid = false;
 
     return $this;
   }
 
 
   /**
    * @task edgelogic
    */
   public function buildEdgeLogicSelectClause(AphrontDatabaseConnection $conn) {
     $select = array();
 
     $this->validateEdgeLogicConstraints();
 
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
       foreach ($constraints as $operator => $list) {
         $alias = $this->getEdgeLogicTableAlias($operator, $type);
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_AND:
             if (count($list) > 1) {
               $select[] = qsprintf(
                 $conn,
                 'COUNT(DISTINCT(%T.dst)) %T',
                 $alias,
                 $this->buildEdgeLogicTableAliasCount($alias));
             }
             break;
           case PhabricatorQueryConstraint::OPERATOR_ANCESTOR:
             // This is tricky. We have a query which specifies multiple
             // projects, each of which may have an arbitrarily large number
             // of descendants.
 
             // Suppose the projects are "Engineering" and "Operations", and
             // "Engineering" has subprojects X, Y and Z.
 
             // We first use `FIELD(dst, X, Y, Z)` to produce a 0 if a row
             // is not part of Engineering at all, or some number other than
             // 0 if it is.
 
             // Then we use `IF(..., idx, NULL)` to convert the 0 to a NULL and
             // any other value to an index (say, 1) for the ancestor.
 
             // We build these up for every ancestor, then use `COALESCE(...)`
             // to select the non-null one, giving us an ancestor which this
             // row is a member of.
 
             // From there, we use `COUNT(DISTINCT(...))` to make sure that
             // each result row is a member of all ancestors.
             if (count($list) > 1) {
               $idx = 1;
               $parts = array();
               foreach ($list as $constraint) {
                 $parts[] = qsprintf(
                   $conn,
                   'IF(FIELD(%T.dst, %Ls) != 0, %d, NULL)',
                   $alias,
                   (array)$constraint->getValue(),
                   $idx++);
               }
               $parts = qsprintf($conn, '%LQ', $parts);
 
               $select[] = qsprintf(
                 $conn,
                 'COUNT(DISTINCT(COALESCE(%Q))) %T',
                 $parts,
                 $this->buildEdgeLogicTableAliasAncestor($alias));
             }
             break;
           default:
             break;
         }
       }
     }
 
     return $select;
   }
 
 
   /**
    * @task edgelogic
    */
   public function buildEdgeLogicJoinClause(AphrontDatabaseConnection $conn) {
     $edge_table = PhabricatorEdgeConfig::TABLE_NAME_EDGE;
     $phid_column = $this->getApplicationSearchObjectPHIDColumn($conn);
 
     $joins = array();
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
 
       $op_null = PhabricatorQueryConstraint::OPERATOR_NULL;
       $has_null = isset($constraints[$op_null]);
 
       // If we're going to process an only() operator, build a list of the
       // acceptable set of PHIDs first. We'll only match results which have
       // no edges to any other PHIDs.
       $all_phids = array();
       if (isset($constraints[PhabricatorQueryConstraint::OPERATOR_ONLY])) {
         foreach ($constraints as $operator => $list) {
           switch ($operator) {
             case PhabricatorQueryConstraint::OPERATOR_ANCESTOR:
             case PhabricatorQueryConstraint::OPERATOR_AND:
             case PhabricatorQueryConstraint::OPERATOR_OR:
               foreach ($list as $constraint) {
                 $value = (array)$constraint->getValue();
                 foreach ($value as $v) {
                   $all_phids[$v] = $v;
                 }
               }
               break;
           }
         }
       }
 
       foreach ($constraints as $operator => $list) {
         $alias = $this->getEdgeLogicTableAlias($operator, $type);
 
         $phids = array();
         foreach ($list as $constraint) {
           $value = (array)$constraint->getValue();
           foreach ($value as $v) {
             $phids[$v] = $v;
           }
         }
         $phids = array_keys($phids);
 
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_NOT:
             $joins[] = qsprintf(
               $conn,
               'LEFT JOIN %T %T ON %Q = %T.src AND %T.type = %d
                 AND %T.dst IN (%Ls)',
               $edge_table,
               $alias,
               $phid_column,
               $alias,
               $alias,
               $type,
               $alias,
               $phids);
             break;
           case PhabricatorQueryConstraint::OPERATOR_ANCESTOR:
           case PhabricatorQueryConstraint::OPERATOR_AND:
           case PhabricatorQueryConstraint::OPERATOR_OR:
             // If we're including results with no matches, we have to degrade
             // this to a LEFT join. We'll use WHERE to select matching rows
             // later.
             if ($has_null) {
               $join_type = qsprintf($conn, 'LEFT');
             } else {
               $join_type = qsprintf($conn, '');
             }
 
             $joins[] = qsprintf(
               $conn,
               '%Q JOIN %T %T ON %Q = %T.src AND %T.type = %d
                 AND %T.dst IN (%Ls)',
               $join_type,
               $edge_table,
               $alias,
               $phid_column,
               $alias,
               $alias,
               $type,
               $alias,
               $phids);
             break;
           case PhabricatorQueryConstraint::OPERATOR_NULL:
             $joins[] = qsprintf(
               $conn,
               'LEFT JOIN %T %T ON %Q = %T.src AND %T.type = %d',
               $edge_table,
               $alias,
               $phid_column,
               $alias,
               $alias,
               $type);
             break;
           case PhabricatorQueryConstraint::OPERATOR_ONLY:
             $joins[] = qsprintf(
               $conn,
               'LEFT JOIN %T %T ON %Q = %T.src AND %T.type = %d
                 AND %T.dst NOT IN (%Ls)',
               $edge_table,
               $alias,
               $phid_column,
               $alias,
               $alias,
               $type,
               $alias,
               $all_phids);
             break;
         }
       }
     }
 
     return $joins;
   }
 
 
   /**
    * @task edgelogic
    */
   public function buildEdgeLogicWhereClause(AphrontDatabaseConnection $conn) {
     $where = array();
 
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
 
       $full = array();
       $null = array();
 
       $op_null = PhabricatorQueryConstraint::OPERATOR_NULL;
       $has_null = isset($constraints[$op_null]);
 
       foreach ($constraints as $operator => $list) {
         $alias = $this->getEdgeLogicTableAlias($operator, $type);
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_NOT:
           case PhabricatorQueryConstraint::OPERATOR_ONLY:
             $full[] = qsprintf(
               $conn,
               '%T.dst IS NULL',
               $alias);
             break;
           case PhabricatorQueryConstraint::OPERATOR_AND:
           case PhabricatorQueryConstraint::OPERATOR_OR:
             if ($has_null) {
               $full[] = qsprintf(
                 $conn,
                 '%T.dst IS NOT NULL',
                 $alias);
             }
             break;
           case PhabricatorQueryConstraint::OPERATOR_NULL:
             $null[] = qsprintf(
               $conn,
               '%T.dst IS NULL',
               $alias);
             break;
         }
       }
 
       if ($full && $null) {
         $where[] = qsprintf($conn, '(%LA OR %LA)', $full, $null);
       } else if ($full) {
         foreach ($full as $condition) {
           $where[] = $condition;
         }
       } else if ($null) {
         foreach ($null as $condition) {
           $where[] = $condition;
         }
       }
     }
 
     return $where;
   }
 
 
   /**
    * @task edgelogic
    */
   public function buildEdgeLogicHavingClause(AphrontDatabaseConnection $conn) {
     $having = array();
 
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
       foreach ($constraints as $operator => $list) {
         $alias = $this->getEdgeLogicTableAlias($operator, $type);
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_AND:
             if (count($list) > 1) {
               $having[] = qsprintf(
                 $conn,
                 '%T = %d',
                 $this->buildEdgeLogicTableAliasCount($alias),
                 count($list));
             }
             break;
           case PhabricatorQueryConstraint::OPERATOR_ANCESTOR:
             if (count($list) > 1) {
               $having[] = qsprintf(
                 $conn,
                 '%T = %d',
                 $this->buildEdgeLogicTableAliasAncestor($alias),
                 count($list));
             }
             break;
         }
       }
     }
 
     return $having;
   }
 
 
   /**
    * @task edgelogic
    */
   public function shouldGroupEdgeLogicResultRows() {
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
       foreach ($constraints as $operator => $list) {
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_NOT:
           case PhabricatorQueryConstraint::OPERATOR_AND:
           case PhabricatorQueryConstraint::OPERATOR_OR:
             if (count($list) > 1) {
               return true;
             }
             break;
           case PhabricatorQueryConstraint::OPERATOR_ANCESTOR:
             // NOTE: We must always group query results rows when using an
             // "ANCESTOR" operator because a single task may be related to
             // two different descendants of a particular ancestor. For
             // discussion, see T12753.
             return true;
           case PhabricatorQueryConstraint::OPERATOR_NULL:
           case PhabricatorQueryConstraint::OPERATOR_ONLY:
             return true;
         }
       }
     }
 
     return false;
   }
 
 
   /**
    * @task edgelogic
    */
   private function getEdgeLogicTableAlias($operator, $type) {
     return 'edgelogic_'.$operator.'_'.$type;
   }
 
 
   /**
    * @task edgelogic
    */
   private function buildEdgeLogicTableAliasCount($alias) {
     return $alias.'_count';
   }
 
   /**
    * @task edgelogic
    */
   private function buildEdgeLogicTableAliasAncestor($alias) {
     return $alias.'_ancestor';
   }
 
 
   /**
    * Select certain edge logic constraint values.
    *
    * @task edgelogic
    */
   protected function getEdgeLogicValues(
     array $edge_types,
     array $operators) {
 
     $values = array();
 
     $constraint_lists = $this->edgeLogicConstraints;
     if ($edge_types) {
       $constraint_lists = array_select_keys($constraint_lists, $edge_types);
     }
 
     foreach ($constraint_lists as $type => $constraints) {
       if ($operators) {
         $constraints = array_select_keys($constraints, $operators);
       }
       foreach ($constraints as $operator => $list) {
         foreach ($list as $constraint) {
           $value = (array)$constraint->getValue();
           foreach ($value as $v) {
             $values[] = $v;
           }
         }
       }
     }
 
     return $values;
   }
 
 
   /**
    * Validate edge logic constraints for the query.
    *
    * @return this
    * @task edgelogic
    */
   private function validateEdgeLogicConstraints() {
     if ($this->edgeLogicConstraintsAreValid) {
       return $this;
     }
 
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
       foreach ($constraints as $operator => $list) {
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_EMPTY:
             throw new PhabricatorEmptyQueryException(
               pht('This query specifies an empty constraint.'));
         }
       }
     }
 
     // This should probably be more modular, eventually, but we only do
     // project-based edge logic today.
 
     $project_phids = $this->getEdgeLogicValues(
       array(
         PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
       ),
       array(
         PhabricatorQueryConstraint::OPERATOR_AND,
         PhabricatorQueryConstraint::OPERATOR_OR,
         PhabricatorQueryConstraint::OPERATOR_NOT,
         PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
       ));
     if ($project_phids) {
       $projects = id(new PhabricatorProjectQuery())
         ->setViewer($this->getViewer())
         ->setParentQuery($this)
         ->withPHIDs($project_phids)
         ->execute();
       $projects = mpull($projects, null, 'getPHID');
       foreach ($project_phids as $phid) {
         if (empty($projects[$phid])) {
           throw new PhabricatorEmptyQueryException(
             pht(
               'This query is constrained by a project you do not have '.
               'permission to see.'));
         }
       }
     }
 
     $op_and = PhabricatorQueryConstraint::OPERATOR_AND;
     $op_or = PhabricatorQueryConstraint::OPERATOR_OR;
     $op_ancestor = PhabricatorQueryConstraint::OPERATOR_ANCESTOR;
 
     foreach ($this->edgeLogicConstraints as $type => $constraints) {
       foreach ($constraints as $operator => $list) {
         switch ($operator) {
           case PhabricatorQueryConstraint::OPERATOR_ONLY:
             if (count($list) > 1) {
               throw new PhabricatorEmptyQueryException(
                 pht(
                   'This query specifies only() more than once.'));
             }
 
             $have_and = idx($constraints, $op_and);
             $have_or = idx($constraints, $op_or);
             $have_ancestor = idx($constraints, $op_ancestor);
             if (!$have_and && !$have_or && !$have_ancestor) {
               throw new PhabricatorEmptyQueryException(
                 pht(
                   'This query specifies only(), but no other constraints '.
                   'which it can apply to.'));
             }
             break;
         }
       }
     }
 
     $this->edgeLogicConstraintsAreValid = true;
 
     return $this;
   }
 
 
 /* -(  Spaces  )------------------------------------------------------------- */
 
 
   /**
    * Constrain the query to return results from only specific Spaces.
    *
    * Pass a list of Space PHIDs, or `null` to represent the default space. Only
    * results in those Spaces will be returned.
    *
    * Queries are always constrained to include only results from spaces the
    * viewer has access to.
    *
    * @param list<phid|null>
    * @task spaces
    */
   public function withSpacePHIDs(array $space_phids) {
     $object = $this->newResultObject();
 
     if (!$object) {
       throw new Exception(
         pht(
           'This query (of class "%s") does not implement newResultObject(), '.
           'but must implement this method to enable support for Spaces.',
           get_class($this)));
     }
 
     if (!($object instanceof PhabricatorSpacesInterface)) {
       throw new Exception(
         pht(
           'This query (of class "%s") returned an object of class "%s" from '.
           'getNewResultObject(), but it does not implement the required '.
           'interface ("%s"). Objects must implement this interface to enable '.
           'Spaces support.',
           get_class($this),
           get_class($object),
           'PhabricatorSpacesInterface'));
     }
 
     $this->spacePHIDs = $space_phids;
 
     return $this;
   }
 
   public function withSpaceIsArchived($archived) {
     $this->spaceIsArchived = $archived;
     return $this;
   }
 
 
   /**
    * Constrain the query to include only results in valid Spaces.
    *
    * This method builds part of a WHERE clause which considers the spaces the
    * viewer has access to see with any explicit constraint on spaces added by
    * @{method:withSpacePHIDs}.
    *
    * @param AphrontDatabaseConnection Database connection.
    * @return string Part of a WHERE clause.
    * @task spaces
    */
   private function buildSpacesWhereClause(AphrontDatabaseConnection $conn) {
     $object = $this->newResultObject();
     if (!$object) {
       return null;
     }
 
     if (!($object instanceof PhabricatorSpacesInterface)) {
       return null;
     }
 
     $viewer = $this->getViewer();
 
     // If we have an omnipotent viewer and no formal space constraints, don't
     // emit a clause. This primarily enables older migrations to run cleanly,
     // without fataling because they try to match a `spacePHID` column which
     // does not exist yet. See T8743, T8746.
     if ($viewer->isOmnipotent()) {
       if ($this->spaceIsArchived === null && $this->spacePHIDs === null) {
         return null;
       }
     }
 
     // See T13240. If this query raises policy exceptions, don't filter objects
     // in the MySQL layer. We want them to reach the application layer so we
     // can reject them and raise an exception.
     if ($this->shouldRaisePolicyExceptions()) {
       return null;
     }
 
     $space_phids = array();
     $include_null = false;
 
     $all = PhabricatorSpacesNamespaceQuery::getAllSpaces();
     if (!$all) {
       // If there are no spaces at all, implicitly give the viewer access to
       // the default space.
       $include_null = true;
     } else {
       // Otherwise, give them access to the spaces they have permission to
       // see.
       $viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces(
         $viewer);
       foreach ($viewer_spaces as $viewer_space) {
         if ($this->spaceIsArchived !== null) {
           if ($viewer_space->getIsArchived() != $this->spaceIsArchived) {
             continue;
           }
         }
         $phid = $viewer_space->getPHID();
         $space_phids[$phid] = $phid;
         if ($viewer_space->getIsDefaultNamespace()) {
           $include_null = true;
         }
       }
     }
 
     // If we have additional explicit constraints, evaluate them now.
     if ($this->spacePHIDs !== null) {
       $explicit = array();
       $explicit_null = false;
       foreach ($this->spacePHIDs as $phid) {
         if ($phid === null) {
           $space = PhabricatorSpacesNamespaceQuery::getDefaultSpace();
         } else {
           $space = idx($all, $phid);
         }
 
         if ($space) {
           $phid = $space->getPHID();
           $explicit[$phid] = $phid;
           if ($space->getIsDefaultNamespace()) {
             $explicit_null = true;
           }
         }
       }
 
       // If the viewer can see the default space but it isn't on the explicit
       // list of spaces to query, don't match it.
       if ($include_null && !$explicit_null) {
         $include_null = false;
       }
 
       // Include only the spaces common to the viewer and the constraints.
       $space_phids = array_intersect_key($space_phids, $explicit);
     }
 
     if (!$space_phids && !$include_null) {
       if ($this->spacePHIDs === null) {
         throw new PhabricatorEmptyQueryException(
           pht('You do not have access to any spaces.'));
       } else {
         throw new PhabricatorEmptyQueryException(
           pht(
             'You do not have access to any of the spaces this query '.
             'is constrained to.'));
       }
     }
 
     $alias = $this->getPrimaryTableAlias();
     if ($alias) {
       $col = qsprintf($conn, '%T.spacePHID', $alias);
     } else {
       $col = qsprintf($conn, 'spacePHID');
     }
 
     if ($space_phids && $include_null) {
       return qsprintf(
         $conn,
         '(%Q IN (%Ls) OR %Q IS NULL)',
         $col,
         $space_phids,
         $col);
     } else if ($space_phids) {
       return qsprintf(
         $conn,
         '%Q IN (%Ls)',
         $col,
         $space_phids);
     } else {
       return qsprintf(
         $conn,
         '%Q IS NULL',
         $col);
     }
   }
 
   private function hasFerretOrder() {
     $vector = $this->getOrderVector();
 
     if ($vector->containsKey('rank')) {
       return true;
     }
 
     if ($vector->containsKey('fulltext-created')) {
       return true;
     }
 
     if ($vector->containsKey('fulltext-modified')) {
       return true;
     }
 
     return false;
   }
 
 }