diff --git a/src/applications/config/phid/PhabricatorConfigPHIDTypeConfig.php b/src/applications/config/phid/PhabricatorConfigPHIDTypeConfig.php
index 04234c27b..ae297edbe 100644
--- a/src/applications/config/phid/PhabricatorConfigPHIDTypeConfig.php
+++ b/src/applications/config/phid/PhabricatorConfigPHIDTypeConfig.php
@@ -1,48 +1,49 @@
 <?php
 
 final class PhabricatorConfigPHIDTypeConfig extends PhabricatorPHIDType {
 
   const TYPECONST = 'CONF';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Config');
   }
 
   public function newObject() {
     return new PhabricatorConfigEntry();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorConfigEntryQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $entry = $objects[$phid];
 
       $key = $entry->getConfigKey();
 
       $handle->setName($key);
       $handle->setURI("/config/edit/{$key}/");
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/conpherence/phid/PhabricatorConpherencePHIDTypeThread.php b/src/applications/conpherence/phid/PhabricatorConpherencePHIDTypeThread.php
index 5e360ad64..dba81f264 100644
--- a/src/applications/conpherence/phid/PhabricatorConpherencePHIDTypeThread.php
+++ b/src/applications/conpherence/phid/PhabricatorConpherencePHIDTypeThread.php
@@ -1,49 +1,50 @@
 <?php
 
 /**
  * @group conpherence
  */
 final class PhabricatorConpherencePHIDTypeThread extends PhabricatorPHIDType {
 
   const TYPECONST = 'CONP';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Conpherence Thread');
   }
 
   public function newObject() {
     return new ConpherenceThread();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new ConpherenceThreadQuery())
-      ->withPHIDs($phids)
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
+      ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $thread = $objects[$phid];
       $name = $thread->getTitle();
       if (!strlen($name)) {
         $name = pht('[No Title]');
       }
       $handle->setName($name);
       $handle->setFullName($name);
       $handle->setURI('/conpherence/'.$thread->getID().'/');
     }
   }
 
 }
diff --git a/src/applications/countdown/phid/PhabricatorCountdownPHIDTypeCountdown.php b/src/applications/countdown/phid/PhabricatorCountdownPHIDTypeCountdown.php
index c2661c02a..c816a1054 100644
--- a/src/applications/countdown/phid/PhabricatorCountdownPHIDTypeCountdown.php
+++ b/src/applications/countdown/phid/PhabricatorCountdownPHIDTypeCountdown.php
@@ -1,75 +1,76 @@
 <?php
 
 final class PhabricatorCountdownPHIDTypeCountdown extends PhabricatorPHIDType {
 
   const TYPECONST = 'CDWN';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Countdown');
   }
 
   public function newObject() {
     return new PhabricatorCountdown();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorCountdownQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $countdown = $objects[$phid];
 
       $name = $countdown->getTitle();
       $id = $countdown->getID();
 
       $handle->setName("C{$id}");
       $handle->setFullName("C{$id}: {$name}");
       $handle->setURI("/countdown/{$id}/");
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^C\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PhabricatorCountdownQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/differential/phid/DifferentialPHIDTypeRevision.php b/src/applications/differential/phid/DifferentialPHIDTypeRevision.php
index 3a2ff3647..414afc7d0 100644
--- a/src/applications/differential/phid/DifferentialPHIDTypeRevision.php
+++ b/src/applications/differential/phid/DifferentialPHIDTypeRevision.php
@@ -1,85 +1,86 @@
 <?php
 
 final class DifferentialPHIDTypeRevision extends PhabricatorPHIDType {
 
   const TYPECONST = 'DREV';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Differential Revision');
   }
 
   public function newObject() {
     return new DifferentialRevision();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new DifferentialRevisionQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     static $closed_statuses = array(
       ArcanistDifferentialRevisionStatus::CLOSED => true,
       ArcanistDifferentialRevisionStatus::ABANDONED => true,
     );
 
     foreach ($handles as $phid => $handle) {
       $revision = $objects[$phid];
 
       $title = $revision->getTitle();
       $id = $revision->getID();
       $status = $revision->getStatus();
 
       $handle->setName("D{$id}");
       $handle->setURI("/D{$id}");
       $handle->setFullName("D{$id}: {$title}");
 
       if (isset($closed_statuses[$status])) {
         $handle->setStatus(PhabricatorObjectHandleStatus::STATUS_CLOSED);
       }
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^D\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new DifferentialRevisionQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/diviner/phid/DivinerPHIDTypeAtom.php b/src/applications/diviner/phid/DivinerPHIDTypeAtom.php
index 51f8c472c..a563ec45c 100644
--- a/src/applications/diviner/phid/DivinerPHIDTypeAtom.php
+++ b/src/applications/diviner/phid/DivinerPHIDTypeAtom.php
@@ -1,42 +1,43 @@
 <?php
 
 final class DivinerPHIDTypeAtom extends PhabricatorPHIDType {
 
   const TYPECONST = 'ATOM';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Atom');
   }
 
   public function newObject() {
     return new DivinerLiveSymbol();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new DivinerAtomQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $atom = $objects[$phid];
 
       $handle->setName($atom->getTitle());
       $handle->setURI($atom->getName());
     }
   }
 
 }
diff --git a/src/applications/diviner/phid/DivinerPHIDTypeBook.php b/src/applications/diviner/phid/DivinerPHIDTypeBook.php
index c36bb1249..2d8055537 100644
--- a/src/applications/diviner/phid/DivinerPHIDTypeBook.php
+++ b/src/applications/diviner/phid/DivinerPHIDTypeBook.php
@@ -1,45 +1,46 @@
 <?php
 
 final class DivinerPHIDTypeBook extends PhabricatorPHIDType {
 
   const TYPECONST = 'BOOK';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Book');
   }
 
   public function newObject() {
     return new DivinerLiveBook();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new DivinerBookQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $book = $objects[$phid];
 
       $name = $book->getName();
 
       $handle->setName($book->getShortTitle());
       $handle->setFullName($book->getTitle());
       $handle->setURI("/diviner/book/{$name}/");
     }
   }
 
 }
diff --git a/src/applications/files/phid/PhabricatorFilePHIDTypeFile.php b/src/applications/files/phid/PhabricatorFilePHIDTypeFile.php
index 04c11128e..50586bee7 100644
--- a/src/applications/files/phid/PhabricatorFilePHIDTypeFile.php
+++ b/src/applications/files/phid/PhabricatorFilePHIDTypeFile.php
@@ -1,76 +1,77 @@
 <?php
 
 final class PhabricatorFilePHIDTypeFile extends PhabricatorPHIDType {
 
   const TYPECONST = 'FILE';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('File');
   }
 
   public function newObject() {
     return new PhabricatorFile();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorFileQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $file = $objects[$phid];
 
       $id = $file->getID();
       $name = $file->getName();
       $uri = $file->getBestURI();
 
       $handle->setName("F{$id}");
       $handle->setFullName("F{$id}: {$name}");
       $handle->setURI($uri);
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^F\d*[1-9]\d*$/', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PhabricatorFileQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/herald/phid/HeraldPHIDTypeRule.php b/src/applications/herald/phid/HeraldPHIDTypeRule.php
index 9e517cf61..1c408cbb4 100644
--- a/src/applications/herald/phid/HeraldPHIDTypeRule.php
+++ b/src/applications/herald/phid/HeraldPHIDTypeRule.php
@@ -1,45 +1,46 @@
 <?php
 
 final class HeraldPHIDTypeRule extends PhabricatorPHIDType {
 
   const TYPECONST = 'HRUL';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Herald Rule');
   }
 
   public function newObject() {
     return new HeraldRule();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new HeraldRuleQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $rule = $objects[$phid];
 
       $id = $rule->getID();
       $name = $rule->getName();
 
       $handle->setName($name);
       $handle->setURI("/herald/rule/{$id}/");
     }
   }
 
 }
diff --git a/src/applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php b/src/applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php
index 345c8252e..d1e1fcc8c 100644
--- a/src/applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php
+++ b/src/applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php
@@ -1,76 +1,77 @@
 <?php
 
 /**
  * @group legalpad
  */
 final class PhabricatorLegalpadPHIDTypeDocument extends PhabricatorPHIDType {
 
   const TYPECONST = 'LEGD';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Legalpad Document');
   }
 
   public function newObject() {
     return new LegalpadDocument();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new LegalpadDocumentQuery())
-      ->needDocumentBodies(true)
-      ->withPHIDs($phids)
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
+      ->withPHIDs($phids)
+      ->needDocumentBodies(true)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $document = $objects[$phid];
       $name = $document->getDocumentBody()->getTitle();
       $handle->setName($name);
       $handle->setFullName($name);
       $handle->setURI('/legalpad/view/'.$document->getID().'/');
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^L\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new LegalpadDocumentQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/macro/phid/PhabricatorMacroPHIDTypeMacro.php b/src/applications/macro/phid/PhabricatorMacroPHIDTypeMacro.php
index 906ddcfaf..bc9b7a8d6 100644
--- a/src/applications/macro/phid/PhabricatorMacroPHIDTypeMacro.php
+++ b/src/applications/macro/phid/PhabricatorMacroPHIDTypeMacro.php
@@ -1,50 +1,51 @@
 <?php
 
 final class PhabricatorMacroPHIDTypeMacro extends PhabricatorPHIDType {
 
   const TYPECONST = 'MCRO';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Image Macro');
   }
 
   public function newObject() {
     return new PhabricatorFileImageMacro();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorMacroQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $macro = $objects[$phid];
 
       $id = $macro->getID();
       $name = $macro->getName();
 
       $handle->setName($name);
       $handle->setFullName(pht('Image Macro "%s"', $name));
       $handle->setURI("/macro/view/{$id}/");
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php b/src/applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php
index ec9462d97..eee01d277 100644
--- a/src/applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php
+++ b/src/applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php
@@ -1,46 +1,47 @@
 <?php
 
 final class PhabricatorMailingListPHIDTypeList extends PhabricatorPHIDType {
 
   const TYPECONST = 'MLST';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Mailing List');
   }
 
   public function newObject() {
     return new PhabricatorMetaMTAMailingList();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorMailingListQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $list = $objects[$phid];
 
       $handle->setName($list->getName());
       $handle->setURI($list->getURI());
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/maniphest/phid/ManiphestPHIDTypeTask.php b/src/applications/maniphest/phid/ManiphestPHIDTypeTask.php
index b81bc354c..dd076bc51 100644
--- a/src/applications/maniphest/phid/ManiphestPHIDTypeTask.php
+++ b/src/applications/maniphest/phid/ManiphestPHIDTypeTask.php
@@ -1,78 +1,79 @@
 <?php
 
 final class ManiphestPHIDTypeTask extends PhabricatorPHIDType {
 
   const TYPECONST = 'TASK';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Task');
   }
 
   public function newObject() {
     return new ManiphestTask();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new ManiphestTaskQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $task = $objects[$phid];
       $id = $task->getID();
       $title = $task->getTitle();
 
       $handle->setName("T{$id}");
       $handle->setFullName("T{$id}: {$title}");
       $handle->setURI("/T{$id}");
 
       if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) {
         $handle->setStatus(PhabricatorObjectHandleStatus::STATUS_CLOSED);
       }
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^T\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new ManiphestTaskQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/owners/phid/PhabricatorOwnersPHIDTypePackage.php b/src/applications/owners/phid/PhabricatorOwnersPHIDTypePackage.php
index cf8ce0b66..af7976aad 100644
--- a/src/applications/owners/phid/PhabricatorOwnersPHIDTypePackage.php
+++ b/src/applications/owners/phid/PhabricatorOwnersPHIDTypePackage.php
@@ -1,45 +1,46 @@
 <?php
 
 final class PhabricatorOwnersPHIDTypePackage extends PhabricatorPHIDType {
 
   const TYPECONST = 'OPKG';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Owners Package');
   }
 
   public function newObject() {
     return new PhabricatorOwnersPackage();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorOwnersPackageQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $package = $objects[$phid];
 
       $name = $package->getName();
       $id = $package->getID();
 
       $handle->setName($name);
       $handle->setURI("/owners/package/{$id}/");
     }
   }
 
 }
diff --git a/src/applications/paste/phid/PhabricatorPastePHIDTypePaste.php b/src/applications/paste/phid/PhabricatorPastePHIDTypePaste.php
index 8e068f23c..024cdd9f1 100644
--- a/src/applications/paste/phid/PhabricatorPastePHIDTypePaste.php
+++ b/src/applications/paste/phid/PhabricatorPastePHIDTypePaste.php
@@ -1,75 +1,76 @@
 <?php
 
 final class PhabricatorPastePHIDTypePaste extends PhabricatorPHIDType {
 
   const TYPECONST = 'PSTE';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Paste');
   }
 
   public function newObject() {
     return new PhabricatorPaste();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorPasteQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $paste = $objects[$phid];
 
       $id = $paste->getID();
       $name = $paste->getFullName();
 
       $handle->setName("P{$id}");
       $handle->setFullName($name);
       $handle->setURI("/P{$id}");
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^P\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PhabricatorPasteQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/people/phid/PhabricatorPeoplePHIDTypeExternal.php b/src/applications/people/phid/PhabricatorPeoplePHIDTypeExternal.php
index 433226003..b3c0044e6 100644
--- a/src/applications/people/phid/PhabricatorPeoplePHIDTypeExternal.php
+++ b/src/applications/people/phid/PhabricatorPeoplePHIDTypeExternal.php
@@ -1,46 +1,47 @@
 <?php
 
 final class PhabricatorPeoplePHIDTypeExternal extends PhabricatorPHIDType {
 
   const TYPECONST = 'XUSR';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('External Account');
   }
 
   public function newObject() {
     return new PhabricatorExternalAccount();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorExternalAccountQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $account = $objects[$phid];
 
       $display_name = $account->getDisplayName();
       $handle->setName($display_name);
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php b/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php
index b9dbc5142..4cf6e21f3 100644
--- a/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php
+++ b/src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php
@@ -1,53 +1,54 @@
 <?php
 
 final class PhabricatorPeoplePHIDTypeUser extends PhabricatorPHIDType {
 
   const TYPECONST = 'USER';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Phabricator User');
   }
 
   public function newObject() {
     return new PhabricatorUser();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorPeopleQuery())
-      ->needProfileImage(true)
-      ->needStatus(true)
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
+      ->needProfileImage(true)
+      ->needStatus(true)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $user = $objects[$phid];
       $handle->setName($user->getUsername());
       $handle->setURI('/p/'.$user->getUsername().'/');
       $handle->setFullName(
         $user->getUsername().' ('.$user->getRealName().')');
       $handle->setImageURI($user->loadProfileImageURI());
       $handle->setDisabled($user->getIsDisabled());
       if ($user->hasStatus()) {
         $status = $user->getStatus();
         $handle->setStatus($status->getTextStatus());
         $handle->setTitle($status->getTerseSummary($query->getViewer()));
       }
     }
 
   }
 
 }
diff --git a/src/applications/phame/phid/PhabricatorPhamePHIDTypeBlog.php b/src/applications/phame/phid/PhabricatorPhamePHIDTypeBlog.php
index e13d378a7..fe24e757b 100644
--- a/src/applications/phame/phid/PhabricatorPhamePHIDTypeBlog.php
+++ b/src/applications/phame/phid/PhabricatorPhamePHIDTypeBlog.php
@@ -1,45 +1,46 @@
 <?php
 
 /**
  * @group phame
  */
 final class PhabricatorPhamePHIDTypeBlog extends PhabricatorPHIDType {
 
   const TYPECONST = 'BLOG';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Phame Blog');
   }
 
   public function newObject() {
     return new PhameBlog();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhameBlogQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $blog = $objects[$phid];
       $handle->setName($blog->getName());
       $handle->setFullName($blog->getName());
       $handle->setURI('/phame/blog/view/'.$blog->getID().'/');
     }
   }
 
 }
diff --git a/src/applications/phame/phid/PhabricatorPhamePHIDTypePost.php b/src/applications/phame/phid/PhabricatorPhamePHIDTypePost.php
index c9556c538..790b1084f 100644
--- a/src/applications/phame/phid/PhabricatorPhamePHIDTypePost.php
+++ b/src/applications/phame/phid/PhabricatorPhamePHIDTypePost.php
@@ -1,45 +1,46 @@
 <?php
 
 /**
  * @group phame
  */
 final class PhabricatorPhamePHIDTypePost extends PhabricatorPHIDType {
 
   const TYPECONST = 'POST';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Phame Post');
   }
 
   public function newObject() {
     return new PhamePost();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhamePostQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $post = $objects[$phid];
       $handle->setName($post->getTitle());
       $handle->setFullName($post->getTitle());
       $handle->setURI('/phame/post/view/'.$post->getID().'/');
     }
   }
 
 }
diff --git a/src/applications/phlux/phid/PhluxPHIDTypeVariable.php b/src/applications/phlux/phid/PhluxPHIDTypeVariable.php
index cfb479c32..e6dc1a5f6 100644
--- a/src/applications/phlux/phid/PhluxPHIDTypeVariable.php
+++ b/src/applications/phlux/phid/PhluxPHIDTypeVariable.php
@@ -1,49 +1,50 @@
 <?php
 
 final class PhluxPHIDTypeVariable extends PhabricatorPHIDType {
 
   const TYPECONST = 'PVAR';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Variable');
   }
 
   public function newObject() {
     return new PhluxVariable();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhluxVariableQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $variable = $objects[$phid];
 
       $key = $variable->getVariableKey();
 
       $handle->setName($key);
       $handle->setFullName(pht('Variable "%s"', $key));
       $handle->setURI("/phlux/view/{$key}/");
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/pholio/phid/PholioPHIDTypeImage.php b/src/applications/pholio/phid/PholioPHIDTypeImage.php
index a9696803b..87c5dadf4 100644
--- a/src/applications/pholio/phid/PholioPHIDTypeImage.php
+++ b/src/applications/pholio/phid/PholioPHIDTypeImage.php
@@ -1,47 +1,48 @@
 <?php
 
 final class PholioPHIDTypeImage extends PhabricatorPHIDType {
 
   const TYPECONST = 'PIMG';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Image');
   }
 
   public function newObject() {
     return new PholioImage();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PholioImageQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $image = $objects[$phid];
 
       $id = $image->getID();
       $mock_id = $image->getMockID();
       $name = $image->getName();
 
       $handle->setURI("/M{$mock_id}/{$id}/");
       $handle->setName($name);
       $handle->setFullName($name);
     }
   }
 
 }
diff --git a/src/applications/pholio/phid/PholioPHIDTypeMock.php b/src/applications/pholio/phid/PholioPHIDTypeMock.php
index dfc446768..ced9f5e9c 100644
--- a/src/applications/pholio/phid/PholioPHIDTypeMock.php
+++ b/src/applications/pholio/phid/PholioPHIDTypeMock.php
@@ -1,75 +1,76 @@
 <?php
 
 final class PholioPHIDTypeMock extends PhabricatorPHIDType {
 
   const TYPECONST = 'MOCK';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Mock');
   }
 
   public function newObject() {
     return new PholioMock();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PholioMockQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $mock = $objects[$phid];
 
       $id = $mock->getID();
       $name = $mock->getName();
 
       $handle->setURI("/M{$id}");
       $handle->setName("M{$id}");
       $handle->setFullName("M{$id}: {$name}");
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^M\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PholioMockQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php b/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
index 3f357d9f6..554457bba 100644
--- a/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
+++ b/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
@@ -1,55 +1,56 @@
 <?php
 
 final class PhrictionPHIDTypeDocument extends PhabricatorPHIDType {
 
   const TYPECONST = 'WIKI';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Wiki Document');
   }
 
   public function newObject() {
     return new PhrictionDocument();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhrictionDocumentQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $document = $objects[$phid];
       $content = $document->getContent();
 
       $title = $content->getTitle();
       $slug = $document->getSlug();
       $status = $document->getStatus();
 
       $handle->setName($title);
       $handle->setURI(PhrictionDocument::getSlugURI($slug));
 
       if ($status != PhrictionDocumentStatus::STATUS_EXISTS) {
         $handle->setStatus(PhabricatorObjectHandleStatus::STATUS_CLOSED);
       }
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/ponder/phid/PonderPHIDTypeAnswer.php b/src/applications/ponder/phid/PonderPHIDTypeAnswer.php
index 388677e15..b6d10c2d7 100644
--- a/src/applications/ponder/phid/PonderPHIDTypeAnswer.php
+++ b/src/applications/ponder/phid/PonderPHIDTypeAnswer.php
@@ -1,45 +1,46 @@
 <?php
 
 final class PonderPHIDTypeAnswer extends PhabricatorPHIDType {
 
   const TYPECONST = 'ANSW';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Answer');
   }
 
   public function newObject() {
     return new PonderAnswer();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PonderAnswerQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $answer = $objects[$phid];
 
       $id = $answer->getID();
       $qid = $answer->getQuestionID();
 
       $handle->setName("Answer {$id}");
       $handle->setURI("/Q{$qid}#A{$id}");
     }
   }
 
 }
diff --git a/src/applications/ponder/phid/PonderPHIDTypeQuestion.php b/src/applications/ponder/phid/PonderPHIDTypeQuestion.php
index aba99a254..32a81a5d2 100644
--- a/src/applications/ponder/phid/PonderPHIDTypeQuestion.php
+++ b/src/applications/ponder/phid/PonderPHIDTypeQuestion.php
@@ -1,75 +1,76 @@
 <?php
 
 final class PonderPHIDTypeQuestion extends PhabricatorPHIDType {
 
   const TYPECONST = 'QUES';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Question');
   }
 
   public function newObject() {
     return new PonderQuestion();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PonderQuestionQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $question = $objects[$phid];
 
       $id = $question->getID();
       $title = $question->getTitle();
 
       $handle->setName("Q{$id}");
       $handle->setURI("/Q{$id}");
       $handle->setFullName("Q{$id}: {$title}");
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^Q\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PonderQuestionQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php b/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
index 82b693634..e160caebc 100644
--- a/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
+++ b/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
@@ -1,50 +1,51 @@
 <?php
 
 final class PhabricatorProjectPHIDTypeProject extends PhabricatorPHIDType {
 
   const TYPECONST = 'PROJ';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Project');
   }
 
   public function newObject() {
     return new PhabricatorProject();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorProjectQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $project = $objects[$phid];
 
       $name = $project->getName();
       $id = $project->getID();
 
       $handle->setName($name);
       $handle->setURI("/project/view/{$id}/");
     }
   }
 
   public function canLoadNamedObject($name) {
     // TODO: We should be able to load named projects by hashtag, e.g. "#yolo".
     return false;
   }
 
 }
diff --git a/src/applications/releeph/phid/ReleephPHIDTypeBranch.php b/src/applications/releeph/phid/ReleephPHIDTypeBranch.php
index b4a51a139..7106dfc9a 100644
--- a/src/applications/releeph/phid/ReleephPHIDTypeBranch.php
+++ b/src/applications/releeph/phid/ReleephPHIDTypeBranch.php
@@ -1,47 +1,48 @@
 <?php
 
 final class ReleephPHIDTypeBranch extends PhabricatorPHIDType {
 
   const TYPECONST = 'REBR';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Releeph Branch');
   }
 
   public function newObject() {
     return new ReleephBranch();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new ReleephBranchQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $branch = $objects[$phid];
 
       $handle->setURI($branch->getURI());
       $handle->setName($branch->getBasename());
       $handle->setFullName($branch->getName());
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/releeph/phid/ReleephPHIDTypeProject.php b/src/applications/releeph/phid/ReleephPHIDTypeProject.php
index 753dff031..f127b7584 100644
--- a/src/applications/releeph/phid/ReleephPHIDTypeProject.php
+++ b/src/applications/releeph/phid/ReleephPHIDTypeProject.php
@@ -1,46 +1,47 @@
 <?php
 
 final class ReleephPHIDTypeProject extends PhabricatorPHIDType {
 
   const TYPECONST = 'REPR';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Releeph Project');
   }
 
   public function newObject() {
     return new ReleephProject();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new ReleephProjectQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $project = $objects[$phid];
 
       $handle->setName($project->getName());
       $handle->setURI($project->getURI());
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/releeph/phid/ReleephPHIDTypeRequest.php b/src/applications/releeph/phid/ReleephPHIDTypeRequest.php
index 116cda950..a3529a612 100644
--- a/src/applications/releeph/phid/ReleephPHIDTypeRequest.php
+++ b/src/applications/releeph/phid/ReleephPHIDTypeRequest.php
@@ -1,50 +1,51 @@
 <?php
 
 final class ReleephPHIDTypeRequest extends PhabricatorPHIDType {
 
   const TYPECONST = 'RERQ';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Releeph Request');
   }
 
   public function newObject() {
     return new ReleephRequest();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new ReleephRequestQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $request = $objects[$phid];
 
       $id = $request->getID();
       $title = $request->getSummaryForDisplay();
 
       $handle->setURI("/RQ{$id}");
       $handle->setName($title);
       $handle->setFullName("RQ{$id}: {$title}");
     }
   }
 
   public function canLoadNamedObject($name) {
     return false;
   }
 
 }
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php
index 47f7df3f9..49f24131a 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php
@@ -1,43 +1,45 @@
 <?php
 
 /**
  * @group repository
  */
 final class PhabricatorRepositoryPHIDTypeArcanistProject
   extends PhabricatorPHIDType {
 
   const TYPECONST = 'APRJ';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Arcanist Project');
   }
 
   public function newObject() {
     return new PhabricatorRepositoryArcanistProject();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
+
     return id(new PhabricatorRepositoryArcanistProjectQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $project = $objects[$phid];
       $handle->setName($project->getName());
     }
   }
 
 }
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php
index 72ed350e2..34f4c4be5 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php
@@ -1,86 +1,87 @@
 <?php
 
 final class PhabricatorRepositoryPHIDTypeCommit extends PhabricatorPHIDType {
 
   const TYPECONST = 'CMIT';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Commit');
   }
 
   public function newObject() {
     return new PhabricatorRepositoryCommit();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new DiffusionCommitQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $commit = $objects[$phid];
       $repository = $commit->getRepository();
       $callsign = $repository->getCallsign();
       $commit_identifier = $commit->getCommitIdentifier();
 
       $name = $repository->formatCommitName($commit_identifier);
       $summary = $commit->getSummary();
       if (strlen($summary)) {
         $full_name = $name.': '.$summary;
       } else {
         $full_name = $name;
       }
 
       $handle->setName($name);
       $handle->setFullName($full_name);
       $handle->setURI('/r'.$callsign.$commit_identifier);
       $handle->setTimestamp($commit->getEpoch());
     }
   }
 
   public static function getCommitObjectNamePattern() {
     $min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
     $min_qualified   = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
 
     return
       'r[A-Z]+[1-9]\d*'.
       '|'.
       'r[A-Z]+[a-f0-9]{'.$min_qualified.',40}'.
       '|'.
       '[a-f0-9]{'.$min_unqualified.',40}';
   }
 
 
   public function canLoadNamedObject($name) {
     $pattern = self::getCommitObjectNamePattern();
     return preg_match('(^'.$pattern.'$)', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $query = id(new DiffusionCommitQuery())
       ->setViewer($query->getViewer())
       ->withIdentifiers($names);
 
     $query->execute();
 
     return $query->getIdentifierMap();
   }
 
 }
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeRepository.php b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeRepository.php
index cfda831fd..70e4c8bf4 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeRepository.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeRepository.php
@@ -1,77 +1,78 @@
 <?php
 
 final class PhabricatorRepositoryPHIDTypeRepository
   extends PhabricatorPHIDType {
 
   const TYPECONST = 'REPO';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Repository');
   }
 
   public function newObject() {
     return new PhabricatorRepository();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorRepositoryQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $repository = $objects[$phid];
 
       $callsign = $repository->getCallsign();
       $name = $repository->getName();
 
       $handle->setName("r{$callsign}");
       $handle->setFullName("r{$callsign} ({$name})");
       $handle->setURI("/diffusion/{$callsign}/");
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^r[A-Z]+$/', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PhabricatorRepositoryQuery())
       ->setViewer($query->getViewer())
       ->withCallsigns(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $object) {
       $callsign = $object->getCallsign();
       foreach (idx($id_map, $callsign, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/slowvote/phid/PhabricatorSlowvotePHIDTypePoll.php b/src/applications/slowvote/phid/PhabricatorSlowvotePHIDTypePoll.php
index 6eaf8d323..7f40a8a7a 100644
--- a/src/applications/slowvote/phid/PhabricatorSlowvotePHIDTypePoll.php
+++ b/src/applications/slowvote/phid/PhabricatorSlowvotePHIDTypePoll.php
@@ -1,72 +1,73 @@
 <?php
 
 final class PhabricatorSlowvotePHIDTypePoll extends PhabricatorPHIDType {
 
   const TYPECONST = 'POLL';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Slowvote Poll');
   }
 
   public function newObject() {
     return new PhabricatorSlowvotePoll();
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $query,
     array $phids) {
 
     return id(new PhabricatorSlowvoteQuery())
       ->setViewer($query->getViewer())
+      ->setParentQuery($query)
       ->withPHIDs($phids)
       ->execute();
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     foreach ($handles as $phid => $handle) {
       $poll = $objects[$phid];
 
       $handle->setName('V'.$poll->getID());
       $handle->setFullName('V'.$poll->getID().': '.$poll->getQuestion());
       $handle->setURI('/V'.$poll->getID());
     }
   }
 
   public function canLoadNamedObject($name) {
     return preg_match('/^V\d*[1-9]\d*$/i', $name);
   }
 
   public function loadNamedObjects(
     PhabricatorObjectQuery $query,
     array $names) {
 
     $id_map = array();
     foreach ($names as $name) {
       $id = (int)substr($name, 1);
       $id_map[$id][] = $name;
     }
 
     $objects = id(new PhabricatorSlowvoteQuery())
       ->setViewer($query->getViewer())
       ->withIDs(array_keys($id_map))
       ->execute();
 
     $results = array();
     foreach ($objects as $id => $object) {
       foreach (idx($id_map, $id, array()) as $name) {
         $results[$name] = $object;
       }
     }
 
     return $results;
   }
 
 }
diff --git a/src/applications/transactions/phid/PhabricatorApplicationTransactionPHIDTypeTransaction.php b/src/applications/transactions/phid/PhabricatorApplicationTransactionPHIDTypeTransaction.php
index 4e59f7ce2..d818dad22 100644
--- a/src/applications/transactions/phid/PhabricatorApplicationTransactionPHIDTypeTransaction.php
+++ b/src/applications/transactions/phid/PhabricatorApplicationTransactionPHIDTypeTransaction.php
@@ -1,79 +1,80 @@
 <?php
 
 final class PhabricatorApplicationTransactionPHIDTypeTransaction
   extends PhabricatorPHIDType {
 
   const TYPECONST = 'XACT';
 
   public function getTypeConstant() {
     return self::TYPECONST;
   }
 
   public function getTypeName() {
     return pht('Transaction');
   }
 
   public function newObject() {
     // NOTE: We could produce an object here, but we'd need to take a PHID type
     // and subtype to do so. Currently, we never write edges to transactions,
     // so leave this unimplemented for the moment.
     return null;
   }
 
   public function loadObjects(
     PhabricatorObjectQuery $object_query,
     array $phids) {
 
     static $queries;
     if ($queries === null) {
       $objects = id(new PhutilSymbolLoader())
         ->setAncestorClass('PhabricatorApplicationTransactionQuery')
         ->loadObjects();
 
       $queries = array();
       foreach ($objects as $object) {
         $type = $object
           ->getTemplateApplicationTransaction()
           ->getApplicationTransactionType();
 
         $queries[$type] = $object;
       }
     }
 
     $phid_subtypes = array();
     foreach ($phids as $phid) {
       $subtype = phid_get_subtype($phid);
       if ($subtype) {
         $phid_subtypes[$subtype][] = $phid;
       }
     }
 
     $results = array();
     foreach ($phid_subtypes as $subtype => $subtype_phids) {
       $query = idx($queries, $subtype);
       if (!$query) {
         continue;
       }
 
       $xactions = id(clone $query)
         ->setViewer($object_query->getViewer())
+        ->setParentQuery($object_query)
         ->withPHIDs($subtype_phids)
         ->execute();
 
       $results += mpull($xactions, null, 'getPHID');
     }
 
     return $results;
   }
 
   public function loadHandles(
     PhabricatorHandleQuery $query,
     array $handles,
     array $objects) {
 
     // NOTE: We don't produce meaningful handles here because they're
     // impractical to produce and no application uses them.
 
   }
 
 }
diff --git a/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
index b16a47db7..a5e74c6a2 100644
--- a/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
+++ b/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
@@ -1,349 +1,401 @@
 <?php
 
 /**
  * A @{class:PhabricatorQuery} which filters results according to visibility
  * policies for the querying user. Broadly, this class allows you to implement
  * a query that returns only objects the user is allowed to see.
  *
  *   $results = id(new ExampleQuery())
  *     ->setViewer($user)
  *     ->withConstraint($example)
  *     ->execute();
  *
  * Normally, you should extend @{class:PhabricatorCursorPagedPolicyAwareQuery},
  * not this class. @{class:PhabricatorCursorPagedPolicyAwareQuery} provides a
  * more practical interface for building usable queries against most object
  * types.
  *
  * NOTE: Although this class extends @{class:PhabricatorOffsetPagedQuery},
  * offset paging with policy filtering is not efficient. All results must be
  * loaded into the application and filtered here: skipping `N` rows via offset
  * is an `O(N)` operation with a large constant. Prefer cursor-based paging
  * with @{class:PhabricatorCursorPagedPolicyAwareQuery}, which can filter far
  * more efficiently in MySQL.
  *
  * @task config     Query Configuration
  * @task exec       Executing Queries
  * @task policyimpl Policy Query Implementation
  */
 abstract class PhabricatorPolicyAwareQuery extends PhabricatorOffsetPagedQuery {
 
   private $viewer;
   private $raisePolicyExceptions;
+  private $parentQuery;
   private $rawResultLimit;
   private $capabilities;
 
 
 /* -(  Query Configuration  )------------------------------------------------ */
 
 
   /**
    * Set the viewer who is executing the query. Results will be filtered
    * according to the viewer's capabilities. You must set a viewer to execute
    * a policy query.
    *
    * @param PhabricatorUser The viewing user.
    * @return this
    * @task config
    */
   final public function setViewer(PhabricatorUser $viewer) {
     $this->viewer = $viewer;
     return $this;
   }
 
 
   /**
    * Get the query's viewer.
    *
    * @return PhabricatorUser The viewing user.
    * @task config
    */
   final public function getViewer() {
     return $this->viewer;
   }
 
 
+  /**
+   * Set the parent query of this query. This is useful for nested queries so
+   * that configuration like whether or not to raise policy exceptions is
+   * seamlessly passed along to child queries.
+   *
+   * @return this
+   * @task config
+   */
+  final public function setParentQuery(PhabricatorPolicyAwareQuery $query) {
+    $this->parentQuery = $query;
+    return $this;
+  }
+
+
+  /**
+   * Get the parent query. See @{method:setParentQuery} for discussion.
+   *
+   * @return PhabricatorPolicyAwareQuery The parent query.
+   * @task config
+   */
+  final public function getParentQuery() {
+    return $this->parentQuery;
+  }
+
+
+  /**
+   * Hook to configure whether this query should raise policy exceptions.
+   *
+   * @return this
+   * @task config
+   */
+  final public function setRaisePolicyExceptions($bool) {
+    $this->raisePolicyExceptions = $bool;
+    return $this;
+  }
+
+
+  /**
+   * @return bool
+   * @task config
+   */
+  final public function shouldRaisePolicyExceptions() {
+    return (bool) $this->raisePolicyExceptions;
+  }
+
+
   /**
    * @task config
    */
   final public function requireCapabilities(array $capabilities) {
     $this->capabilities = $capabilities;
     return $this;
   }
 
 
 /* -(  Query Execution  )---------------------------------------------------- */
 
 
   /**
    * Execute the query, expecting a single result. This method simplifies
    * loading objects for detail pages or edit views.
    *
    *   // Load one result by ID.
    *   $obj = id(new ExampleQuery())
    *     ->setViewer($user)
    *     ->withIDs(array($id))
    *     ->executeOne();
    *   if (!$obj) {
    *     return new Aphront404Response();
    *   }
    *
    * If zero results match the query, this method returns `null`.
-   *
    * If one result matches the query, this method returns that result.
    *
    * If two or more results match the query, this method throws an exception.
    * You should use this method only when the query constraints guarantee at
    * most one match (e.g., selecting a specific ID or PHID).
    *
    * If one result matches the query but it is caught by the policy filter (for
    * example, the user is trying to view or edit an object which exists but
    * which they do not have permission to see) a policy exception is thrown.
    *
    * @return mixed Single result, or null.
    * @task exec
    */
   final public function executeOne() {
 
-    $this->raisePolicyExceptions = true;
+    $this->setRaisePolicyExceptions(true);
     try {
       $results = $this->execute();
     } catch (Exception $ex) {
-      $this->raisePolicyExceptions = false;
+      $this->setRaisePolicyExceptions(false);
       throw $ex;
     }
 
     if (count($results) > 1) {
       throw new Exception("Expected a single result!");
     }
 
     if (!$results) {
       return null;
     }
 
     return head($results);
   }
 
 
   /**
    * Execute the query, loading all visible results.
    *
    * @return list<PhabricatorPolicyInterface> Result objects.
    * @task exec
    */
   final public function execute() {
     if (!$this->viewer) {
       throw new Exception("Call setViewer() before execute()!");
     }
 
+    $parent_query = $this->getParentQuery();
+    if ($parent_query) {
+      $this->setRaisePolicyExceptions(
+        $parent_query->shouldRaisePolicyExceptions());
+    }
+
     $results = array();
 
     $filter = new PhabricatorPolicyFilter();
     $filter->setViewer($this->viewer);
 
     if (!$this->capabilities) {
       $capabilities = array(
         PhabricatorPolicyCapability::CAN_VIEW,
       );
     } else {
       $capabilities = $this->capabilities;
     }
     $filter->requireCapabilities($capabilities);
-    $filter->raisePolicyExceptions($this->raisePolicyExceptions);
+    $filter->raisePolicyExceptions($this->shouldRaisePolicyExceptions());
 
     $offset = (int)$this->getOffset();
     $limit  = (int)$this->getLimit();
     $count  = 0;
 
     if ($limit) {
       $need = $offset + $limit;
     } else {
       $need = 0;
     }
 
     $this->willExecute();
 
     do {
       if ($need) {
         $this->rawResultLimit = min($need - $count, 1024);
       } else {
         $this->rawResultLimit = 0;
       }
 
       try {
         $page = $this->loadPage();
       } catch (PhabricatorEmptyQueryException $ex) {
         $page = array();
       }
 
       if ($page) {
         $maybe_visible = $this->willFilterPage($page);
       } else {
         $maybe_visible = array();
       }
 
       if ($this->shouldDisablePolicyFiltering()) {
         $visible = $maybe_visible;
       } else {
         $visible = $filter->apply($maybe_visible);
       }
 
       $removed = array();
       foreach ($maybe_visible as $key => $object) {
         if (empty($visible[$key])) {
           $removed[$key] = $object;
         }
       }
 
       $this->didFilterResults($removed);
 
       foreach ($visible as $key => $result) {
         ++$count;
 
         // If we have an offset, we just ignore that many results and start
         // storing them only once we've hit the offset. This reduces memory
         // requirements for large offsets, compared to storing them all and
         // slicing them away later.
         if ($count > $offset) {
           $results[$key] = $result;
         }
 
         if ($need && ($count >= $need)) {
           // If we have all the rows we need, break out of the paging query.
           break 2;
         }
       }
 
       if (!$this->rawResultLimit) {
         // If we don't have a load count, we loaded all the results. We do
         // not need to load another page.
         break;
       }
 
       if (count($page) < $this->rawResultLimit) {
         // If we have a load count but the unfiltered results contained fewer
         // objects, we know this was the last page of objects; we do not need
         // to load another page because we can deduce it would be empty.
         break;
       }
 
       $this->nextPage($page);
     } while (true);
 
     $results = $this->didLoadResults($results);
 
     return $results;
   }
 
 
 /* -(  Policy Query Implementation  )---------------------------------------- */
 
 
   /**
    * Get the number of results @{method:loadPage} should load. If the value is
    * 0, @{method:loadPage} should load all available results.
    *
    * @return int The number of results to load, or 0 for all results.
    * @task policyimpl
    */
   final protected function getRawResultLimit() {
     return $this->rawResultLimit;
   }
 
 
   /**
    * Hook invoked before query execution. Generally, implementations should
    * reset any internal cursors.
    *
    * @return void
    * @task policyimpl
    */
   protected function willExecute() {
     return;
   }
 
 
   /**
    * Load a raw page of results. Generally, implementations should load objects
    * from the database. They should attempt to return the number of results
    * hinted by @{method:getRawResultLimit}.
    *
    * @return list<PhabricatorPolicyInterface> List of filterable policy objects.
    * @task policyimpl
    */
   abstract protected function loadPage();
 
 
   /**
    * Update internal state so that the next call to @{method:loadPage} will
    * return new results. Generally, you should adjust a cursor position based
    * on the provided result page.
    *
    * @param list<PhabricatorPolicyInterface> The current page of results.
    * @return void
    * @task policyimpl
    */
   abstract protected function nextPage(array $page);
 
 
   /**
    * Hook for applying a page filter prior to the privacy filter. This allows
    * you to drop some items from the result set without creating problems with
    * pagination or cursor updates.
    *
    * This method will only be called if data is available. Implementations
    * do not need to handle the case of no results specially.
    *
    * @param   list<wild>  Results from `loadPage()`.
    * @return  list<PhabricatorPolicyInterface> Objects for policy filtering.
    * @task policyimpl
    */
   protected function willFilterPage(array $page) {
     return $page;
   }
 
 
   /**
    * Hook for removing filtered results from alternate result sets. This
    * hook will be called with any objects which were returned by the query but
    * filtered for policy reasons. The query should remove them from any cached
    * or partial result sets.
    *
    * @param list<wild>  List of objects that should not be returned by alternate
    *                    result mechanisms.
    * @return void
    * @task policyimpl
    */
   protected function didFilterResults(array $results) {
     return;
   }
 
 
   /**
    * Hook for applying final adjustments before results are returned. This is
    * used by @{class:PhabricatorCursorPagedPolicyAwareQuery} to reverse results
    * that are queried during reverse paging.
    *
    * @param   list<PhabricatorPolicyInterface> Query results.
    * @return  list<PhabricatorPolicyInterface> Final results.
    * @task policyimpl
    */
   protected function didLoadResults(array $results) {
     return $results;
   }
 
 
   /**
    * Allows a subclass to disable policy filtering. This method is dangerous.
    * It should be used only if the query loads data which has already been
    * filtered (for example, because it wraps some other query which uses
    * normal policy filtering).
    *
    * @return bool True to disable all policy filtering.
    * @task policyimpl
    */
   protected function shouldDisablePolicyFiltering() {
     return false;
   }
 
 }