protected function buildResultGroups(PhabricatorSavedQuery $query, array $objects)
 {
     $this->objects = $objects;
     $phids = $query->getEvaluatedParameter('responsiblePHIDs', array());
     if (!$phids) {
         throw new Exception(pht('You can not bucket results by required action without ' . 'specifying "Responsible Users".'));
     }
     $phids = array_fuse($phids);
     $groups = array();
     $groups[] = $this->newGroup()->setName(pht('Must Review'))->setKey(self::KEY_MUSTREVIEW)->setNoDataString(pht('No revisions are blocked on your review.'))->setObjects($this->filterMustReview($phids));
     $groups[] = $this->newGroup()->setName(pht('Ready to Review'))->setKey(self::KEY_SHOULDREVIEW)->setNoDataString(pht('No revisions are waiting on you to review them.'))->setObjects($this->filterShouldReview($phids));
     $groups[] = $this->newGroup()->setName(pht('Ready to Land'))->setNoDataString(pht('No revisions are ready to land.'))->setObjects($this->filterShouldLand($phids));
     $groups[] = $this->newGroup()->setName(pht('Ready to Update'))->setNoDataString(pht('No revisions are waiting for updates.'))->setObjects($this->filterShouldUpdate($phids));
     $groups[] = $this->newGroup()->setName(pht('Waiting on Review'))->setNoDataString(pht('None of your revisions are waiting on review.'))->setObjects($this->filterWaitingForReview($phids));
     $groups[] = $this->newGroup()->setName(pht('Waiting on Authors'))->setNoDataString(pht('No revisions are waiting on author action.'))->setObjects($this->filterWaitingOnAuthors($phids));
     // Because you can apply these buckets to queries which include revisions
     // that have been closed, add an "Other" bucket if we still have stuff
     // that didn't get filtered into any of the previous buckets.
     if ($this->objects) {
         $groups[] = $this->newGroup()->setName(pht('Other Revisions'))->setObjects($this->objects);
     }
     return $groups;
 }