private function handleHovercardEvent($event)
 {
     $viewer = $event->getUser();
     $hovercard = $event->getValue('hovercard');
     $object_handle = $event->getValue('handle');
     $phid = $object_handle->getPHID();
     $rev = $event->getValue('object');
     if (!$rev instanceof DifferentialRevision) {
         return;
     }
     $rev->loadRelationships();
     $reviewer_phids = $rev->getReviewers();
     $e_task = DifferentialRevisionHasTaskEdgeType::EDGECONST;
     $edge_query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($phid))->withEdgeTypes(array($e_task));
     $edge_query->execute();
     $tasks = $edge_query->getDestinationPHIDs();
     $hovercard->setTitle('D' . $rev->getID());
     $hovercard->setDetail($rev->getTitle());
     $hovercard->addField(pht('Author'), $viewer->renderHandle($rev->getAuthorPHID()));
     $hovercard->addField(pht('Reviewers'), $viewer->renderHandleList($reviewer_phids)->setAsInline(true));
     if ($tasks) {
         $hovercard->addField(pht('Tasks'), $viewer->renderHandleList($tasks)->setAsInline(true));
     }
     if ($rev->getSummary()) {
         $hovercard->addField(pht('Summary'), id(new PhutilUTF8StringTruncator())->setMaximumGlyphs(120)->truncateString($rev->getSummary()));
     }
     $hovercard->addTag(DifferentialRevisionDetailView::renderTagForRevision($rev));
     $event->setValue('hovercard', $hovercard);
 }
 private function handleHovercardEvent($event)
 {
     $viewer = $event->getUser();
     $hovercard = $event->getValue('hovercard');
     $object_handle = $event->getValue('handle');
     $phid = $object_handle->getPHID();
     $rev = $event->getValue('object');
     if (!$rev instanceof DifferentialRevision) {
         return;
     }
     $rev->loadRelationships();
     $reviewer_phids = $rev->getReviewers();
     $e_task = DifferentialRevisionHasTaskEdgeType::EDGECONST;
     $edge_query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($phid))->withEdgeTypes(array($e_task));
     $edge_query->execute();
     $tasks = $edge_query->getDestinationPHIDs();
     $phids = array_merge(array($rev->getAuthorPHID()), $reviewer_phids, $tasks);
     $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs($phids)->execute();
     $hovercard->setTitle('D' . $rev->getID());
     $hovercard->setDetail($rev->getTitle());
     $hovercard->addField(pht('Author'), $handles[$rev->getAuthorPHID()]->renderLink());
     $hovercard->addField(pht('Date'), phabricator_datetime($rev->getDateModified(), $viewer));
     $hovercard->addField(pht('Reviewers'), implode_selected_handle_links(', ', $handles, $reviewer_phids));
     if ($tasks) {
         $hovercard->addField(pht('Task(s)', count($tasks)), implode_selected_handle_links(', ', $handles, $tasks));
     }
     if ($rev->getSummary()) {
         $hovercard->addField(pht('Summary'), id(new PhutilUTF8StringTruncator())->setMaximumGlyphs(120)->truncateString($rev->getSummary()));
     }
     $hovercard->addTag(DifferentialRevisionDetailView::renderTagForRevision($rev));
     $event->setValue('hovercard', $hovercard);
 }
 public function renderHovercard(PhabricatorHovercardView $hovercard, PhabricatorObjectHandle $handle, $object, $data)
 {
     $viewer = $this->getViewer();
     $revision = idx($data['revisions'], $object->getPHID());
     if (!$revision) {
         return;
     }
     $hovercard->setTitle('D' . $revision->getID());
     $hovercard->setDetail($revision->getTitle());
     $hovercard->addField(pht('Author'), $viewer->renderHandle($revision->getAuthorPHID()));
     $reviewer_phids = $revision->getReviewerStatus();
     $reviewer_phids = mpull($reviewer_phids, 'getReviewerPHID');
     $hovercard->addField(pht('Reviewers'), $viewer->renderHandleList($reviewer_phids)->setAsInline(true));
     $summary = $revision->getSummary();
     if (strlen($summary)) {
         $summary = id(new PhutilUTF8StringTruncator())->setMaximumGlyphs(120)->truncateString($summary);
         $hovercard->addField(pht('Summary'), $summary);
     }
     $tag = DifferentialRevisionDetailView::renderTagForRevision($revision);
     $hovercard->addTag($tag);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $viewer_is_anonymous = !$user->isLoggedIn();
     $revision = id(new DifferentialRevision())->load($this->revisionID);
     if (!$revision) {
         return new Aphront404Response();
     }
     $revision->loadRelationships();
     $diffs = $revision->loadDiffs();
     if (!$diffs) {
         throw new Exception("This revision has no diffs. Something has gone quite wrong.");
     }
     $diff_vs = $request->getInt('vs');
     $target_id = $request->getInt('id');
     $target = idx($diffs, $target_id, end($diffs));
     $target_manual = $target;
     if (!$target_id) {
         foreach ($diffs as $diff) {
             if ($diff->getCreationMethod() != 'commit') {
                 $target_manual = $diff;
             }
         }
     }
     if (empty($diffs[$diff_vs])) {
         $diff_vs = null;
     }
     $arc_project = $target->loadArcanistProject();
     $repository = $arc_project ? $arc_project->loadRepository() : null;
     list($changesets, $vs_map, $vs_changesets, $rendering_references) = $this->loadChangesetsAndVsMap($target, idx($diffs, $diff_vs), $repository);
     if ($request->getExists('download')) {
         return $this->buildRawDiffResponse($changesets, $vs_changesets, $vs_map, $repository);
     }
     list($aux_fields, $props) = $this->loadAuxiliaryFieldsAndProperties($revision, $target_manual, array('local:commits', 'arc:lint', 'arc:unit'));
     $comments = $revision->loadComments();
     $comments = array_merge($this->getImplicitComments($revision, reset($diffs)), $comments);
     $all_changesets = $changesets;
     $inlines = $this->loadInlineComments($comments, $all_changesets);
     $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $user->getPHID()), mpull($comments, 'getAuthorPHID'));
     foreach ($comments as $comment) {
         $metadata = $comment->getMetadata();
         $added_reviewers = idx($metadata, DifferentialComment::METADATA_ADDED_REVIEWERS);
         if ($added_reviewers) {
             foreach ($added_reviewers as $phid) {
                 $object_phids[] = $phid;
             }
         }
         $added_ccs = idx($metadata, DifferentialComment::METADATA_ADDED_CCS);
         if ($added_ccs) {
             foreach ($added_ccs as $phid) {
                 $object_phids[] = $phid;
             }
         }
     }
     foreach ($revision->getAttached() as $type => $phids) {
         foreach ($phids as $phid => $info) {
             $object_phids[] = $phid;
         }
     }
     $aux_phids = array();
     foreach ($aux_fields as $key => $aux_field) {
         $aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionView();
     }
     $object_phids = array_merge($object_phids, array_mergev($aux_phids));
     $object_phids = array_unique($object_phids);
     $handles = id(new PhabricatorObjectHandleData($object_phids))->loadHandles();
     foreach ($aux_fields as $key => $aux_field) {
         // Make sure each field only has access to handles it specifically
         // requested, not all handles. Otherwise you can get a field which works
         // only in the presence of other fields.
         $aux_field->setHandles(array_select_keys($handles, $aux_phids[$key]));
     }
     $reviewer_warning = null;
     $has_live_reviewer = false;
     foreach ($revision->getReviewers() as $reviewer) {
         if (!$handles[$reviewer]->isDisabled()) {
             $has_live_reviewer = true;
         }
     }
     if (!$has_live_reviewer) {
         $reviewer_warning = new AphrontErrorView();
         $reviewer_warning->setSeverity(AphrontErrorView::SEVERITY_WARNING);
         $reviewer_warning->setTitle('No Active Reviewers');
         if ($revision->getReviewers()) {
             $reviewer_warning->appendChild('<p>All specified reviewers are disabled. You may want to add ' . 'some new reviewers.</p>');
         } else {
             $reviewer_warning->appendChild('<p>This revision has no specified reviewers. You may want to ' . 'add some.</p>');
         }
     }
     $request_uri = $request->getRequestURI();
     $limit = 100;
     $large = $request->getStr('large');
     if (count($changesets) > $limit && !$large) {
         $count = number_format(count($changesets));
         $warning = new AphrontErrorView();
         $warning->setTitle('Very Large Diff');
         $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING);
         $warning->setWidth(AphrontErrorView::WIDTH_WIDE);
         $warning->appendChild("<p>This diff is very large and affects {$count} files. Load " . "each file individually. " . "<strong>" . phutil_render_tag('a', array('href' => $request_uri->alter('large', 'true')->setFragment('toc')), 'Show All Files Inline') . "</strong>");
         $warning = $warning->render();
         $my_inlines = id(new DifferentialInlineComment())->loadAllWhere('revisionID = %d AND commentID IS NULL AND authorPHID = %s AND ' . 'changesetID IN (%Ld)', $this->revisionID, $user->getPHID(), mpull($changesets, 'getID'));
         $visible_changesets = array();
         foreach ($inlines + $my_inlines as $inline) {
             $changeset_id = $inline->getChangesetID();
             if (isset($changesets[$changeset_id])) {
                 $visible_changesets[$changeset_id] = $changesets[$changeset_id];
             }
         }
         if (!empty($props['arc:lint'])) {
             $changeset_paths = mpull($changesets, null, 'getFilename');
             foreach ($props['arc:lint'] as $lint) {
                 $changeset = idx($changeset_paths, $lint['path']);
                 if ($changeset) {
                     $visible_changesets[$changeset->getID()] = $changeset;
                 }
             }
         }
     } else {
         $warning = null;
         $visible_changesets = $changesets;
     }
     $revision_detail = new DifferentialRevisionDetailView();
     $revision_detail->setRevision($revision);
     $revision_detail->setAuxiliaryFields($aux_fields);
     $actions = $this->getRevisionActions($revision);
     $custom_renderer_class = PhabricatorEnv::getEnvConfig('differential.revision-custom-detail-renderer');
     if ($custom_renderer_class) {
         // TODO: build a better version of the action links and deprecate the
         // whole DifferentialRevisionDetailRenderer class.
         $custom_renderer = newv($custom_renderer_class, array());
         $custom_renderer->setDiff($target);
         if ($diff_vs) {
             $custom_renderer->setVSDiff($diffs[$diff_vs]);
         }
         $actions = array_merge($actions, $custom_renderer->generateActionLinks($revision, $target_manual));
     }
     $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_ALL);
     if ($arc_project) {
         list($symbol_indexes, $project_phids) = $this->buildSymbolIndexes($arc_project, $visible_changesets);
     } else {
         $symbol_indexes = array();
         $project_phids = null;
     }
     $revision_detail->setActions($actions);
     $revision_detail->setUser($user);
     $comment_view = new DifferentialRevisionCommentListView();
     $comment_view->setComments($comments);
     $comment_view->setHandles($handles);
     $comment_view->setInlineComments($inlines);
     $comment_view->setChangesets($all_changesets);
     $comment_view->setUser($user);
     $comment_view->setTargetDiff($target);
     $comment_view->setVersusDiffID($diff_vs);
     if ($arc_project) {
         Javelin::initBehavior('repository-crossreference', array('section' => $comment_view->getID(), 'projects' => $project_phids));
     }
     $changeset_view = new DifferentialChangesetListView();
     $changeset_view->setChangesets($changesets);
     $changeset_view->setVisibleChangesets($visible_changesets);
     if (!$viewer_is_anonymous) {
         $changeset_view->setInlineCommentControllerURI('/differential/comment/inline/edit/' . $revision->getID() . '/');
     }
     $changeset_view->setStandaloneURI('/differential/changeset/');
     $changeset_view->setRawFileURIs('/differential/changeset/?view=old', '/differential/changeset/?view=new');
     $changeset_view->setUser($user);
     $changeset_view->setDiff($target);
     $changeset_view->setRenderingReferences($rendering_references);
     $changeset_view->setVsMap($vs_map);
     $changeset_view->setWhitespace($whitespace);
     if ($repository) {
         $changeset_view->setRepository($repository);
     }
     $changeset_view->setSymbolIndexes($symbol_indexes);
     $diff_history = new DifferentialRevisionUpdateHistoryView();
     $diff_history->setDiffs($diffs);
     $diff_history->setSelectedVersusDiffID($diff_vs);
     $diff_history->setSelectedDiffID($target->getID());
     $diff_history->setSelectedWhitespace($whitespace);
     $diff_history->setUser($user);
     $local_view = new DifferentialLocalCommitsView();
     $local_view->setUser($user);
     $local_view->setLocalCommits(idx($props, 'local:commits'));
     if ($repository) {
         $other_revisions = $this->loadOtherRevisions($changesets, $target, $repository);
     } else {
         $other_revisions = array();
     }
     $other_view = null;
     if ($other_revisions) {
         $other_view = $this->renderOtherRevisions($other_revisions);
     }
     $toc_view = new DifferentialDiffTableOfContentsView();
     $toc_view->setChangesets($changesets);
     $toc_view->setVisibleChangesets($visible_changesets);
     $toc_view->setRenderingReferences($rendering_references);
     $toc_view->setUnitTestData(idx($props, 'arc:unit', array()));
     if ($repository) {
         $toc_view->setRepository($repository);
     }
     $toc_view->setDiff($target);
     $toc_view->setUser($user);
     $toc_view->setRevisionID($revision->getID());
     $toc_view->setWhitespace($whitespace);
     $comment_form = null;
     if (!$viewer_is_anonymous) {
         $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID());
         if ($draft) {
             $draft = $draft->getDraft();
         } else {
             $draft = null;
         }
         $comment_form = new DifferentialAddCommentView();
         $comment_form->setRevision($revision);
         $comment_form->setAuxFields($aux_fields);
         $comment_form->setActions($this->getRevisionCommentActions($revision));
         $comment_form->setActionURI('/differential/comment/save/');
         $comment_form->setUser($user);
         $comment_form->setDraft($draft);
     }
     $pane_id = celerity_generate_unique_node_id();
     Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id));
     Javelin::initBehavior('differential-user-select');
     $page_pane = id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets($changesets)->setID($pane_id)->appendChild($comment_view->render() . $diff_history->render() . $warning . $local_view->render() . $toc_view->render() . $other_view . $changeset_view->render());
     if ($comment_form) {
         $page_pane->appendChild($comment_form->render());
     }
     PhabricatorFeedStoryNotification::updateObjectNotificationViews($user, $revision->getPHID());
     $top_anchor = id(new PhabricatorAnchorView())->setAnchorName('top')->setNavigationMarker(true);
     $nav = $this->buildSideNavView($revision, $changesets);
     $nav->selectFilter('');
     $nav->appendChild(array($reviewer_warning, $top_anchor, $revision_detail, $page_pane));
     return $this->buildApplicationPage($nav, array('title' => 'D' . $revision->getID() . ' ' . $revision->getTitle()));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $viewer_is_anonymous = !$user->isLoggedIn();
     $revision = id(new DifferentialRevision())->load($this->revisionID);
     if (!$revision) {
         return new Aphront404Response();
     }
     $revision->loadRelationships();
     $diffs = $revision->loadDiffs();
     if (!$diffs) {
         throw new Exception("This revision has no diffs. Something has gone quite wrong.");
     }
     $diff_vs = $request->getInt('vs');
     $target = end($diffs);
     $target_id = $request->getInt('id');
     if ($target_id) {
         if (isset($diffs[$target_id])) {
             $target = $diffs[$target_id];
         }
     }
     $diffs = mpull($diffs, null, 'getID');
     if (empty($diffs[$diff_vs])) {
         $diff_vs = null;
     }
     list($aux_fields, $props) = $this->loadAuxiliaryFieldsAndProperties($revision, $target, array('local:commits'));
     list($changesets, $vs_map, $rendering_references) = $this->loadChangesetsAndVsMap($diffs, $diff_vs, $target);
     $comments = $revision->loadComments();
     $comments = array_merge($this->getImplicitComments($revision), $comments);
     $all_changesets = $changesets;
     $inlines = $this->loadInlineComments($comments, $all_changesets);
     $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $user->getPHID()), mpull($comments, 'getAuthorPHID'));
     foreach ($comments as $comment) {
         $metadata = $comment->getMetadata();
         $added_reviewers = idx($metadata, DifferentialComment::METADATA_ADDED_REVIEWERS);
         if ($added_reviewers) {
             foreach ($added_reviewers as $phid) {
                 $object_phids[] = $phid;
             }
         }
         $added_ccs = idx($metadata, DifferentialComment::METADATA_ADDED_CCS);
         if ($added_ccs) {
             foreach ($added_ccs as $phid) {
                 $object_phids[] = $phid;
             }
         }
     }
     foreach ($revision->getAttached() as $type => $phids) {
         foreach ($phids as $phid => $info) {
             $object_phids[] = $phid;
         }
     }
     $aux_phids = array();
     foreach ($aux_fields as $key => $aux_field) {
         $aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionView();
     }
     $object_phids = array_merge($object_phids, array_mergev($aux_phids));
     $object_phids = array_unique($object_phids);
     $handles = id(new PhabricatorObjectHandleData($object_phids))->loadHandles();
     foreach ($aux_fields as $key => $aux_field) {
         // Make sure each field only has access to handles it specifically
         // requested, not all handles. Otherwise you can get a field which works
         // only in the presence of other fields.
         $aux_field->setHandles(array_select_keys($handles, $aux_phids[$key]));
     }
     $request_uri = $request->getRequestURI();
     $limit = 100;
     $large = $request->getStr('large');
     if (count($changesets) > $limit && !$large) {
         $count = number_format(count($changesets));
         $warning = new AphrontErrorView();
         $warning->setTitle('Very Large Diff');
         $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING);
         $warning->setWidth(AphrontErrorView::WIDTH_WIDE);
         $warning->appendChild("<p>This diff is very large and affects {$count} files. Use " . "Table of Contents to open files in a standalone view. " . "<strong>" . phutil_render_tag('a', array('href' => $request_uri->alter('large', 'true')), 'Show All Files Inline') . "</strong>");
         $warning = $warning->render();
         $visible_changesets = array();
     } else {
         $warning = null;
         $visible_changesets = $changesets;
     }
     $revision_detail = new DifferentialRevisionDetailView();
     $revision_detail->setRevision($revision);
     $revision_detail->setAuxiliaryFields($aux_fields);
     $actions = $this->getRevisionActions($revision);
     $custom_renderer_class = PhabricatorEnv::getEnvConfig('differential.revision-custom-detail-renderer');
     if ($custom_renderer_class) {
         // TODO: build a better version of the action links and deprecate the
         // whole DifferentialRevisionDetailRenderer class.
         PhutilSymbolLoader::loadClass($custom_renderer_class);
         $custom_renderer = newv($custom_renderer_class, array());
         $actions = array_merge($actions, $custom_renderer->generateActionLinks($revision, $target));
     }
     $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_ALL);
     $arc_project = $target->loadArcanistProject();
     if ($arc_project) {
         $symbol_indexes = $this->buildSymbolIndexes($target, $arc_project, $visible_changesets);
         $repository = $arc_project->loadRepository();
     } else {
         $symbol_indexes = array();
         $repository = null;
     }
     $revision_detail->setActions($actions);
     $revision_detail->setUser($user);
     $comment_view = new DifferentialRevisionCommentListView();
     $comment_view->setComments($comments);
     $comment_view->setHandles($handles);
     $comment_view->setInlineComments($inlines);
     $comment_view->setChangesets($all_changesets);
     $comment_view->setUser($user);
     $comment_view->setTargetDiff($target);
     $comment_view->setVersusDiffID($diff_vs);
     $changeset_view = new DifferentialChangesetListView();
     $changeset_view->setChangesets($visible_changesets);
     $changeset_view->setEditable(!$viewer_is_anonymous);
     $changeset_view->setStandaloneViews(true);
     $changeset_view->setRevision($revision);
     $changeset_view->setDiff($target);
     $changeset_view->setRenderingReferences($rendering_references);
     $changeset_view->setWhitespace($whitespace);
     if ($repository) {
         $changeset_view->setRepository($repository, $target);
     }
     $changeset_view->setSymbolIndexes($symbol_indexes);
     $diff_history = new DifferentialRevisionUpdateHistoryView();
     $diff_history->setDiffs($diffs);
     $diff_history->setSelectedVersusDiffID($diff_vs);
     $diff_history->setSelectedDiffID($target->getID());
     $diff_history->setSelectedWhitespace($whitespace);
     $diff_history->setUser($user);
     $local_view = new DifferentialLocalCommitsView();
     $local_view->setUser($user);
     $local_view->setLocalCommits(idx($props, 'local:commits'));
     $toc_view = new DifferentialDiffTableOfContentsView();
     $toc_view->setChangesets($changesets);
     $toc_view->setStandaloneViewLink(empty($visible_changesets));
     $toc_view->setVsMap($vs_map);
     $toc_view->setRevisionID($revision->getID());
     $toc_view->setWhitespace($whitespace);
     if (!$viewer_is_anonymous) {
         $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID());
         if ($draft) {
             $draft = $draft->getDraft();
         } else {
             $draft = null;
         }
         $comment_form = new DifferentialAddCommentView();
         $comment_form->setRevision($revision);
         $comment_form->setActions($this->getRevisionCommentActions($revision));
         $comment_form->setActionURI('/differential/comment/save/');
         $comment_form->setUser($user);
         $comment_form->setDraft($draft);
     }
     $pane_id = celerity_generate_unique_node_id();
     Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id));
     $page_pane = id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets($changesets)->setID($pane_id)->appendChild($revision_detail->render() . $comment_view->render() . $diff_history->render() . $warning . $local_view->render() . $toc_view->render() . $changeset_view->render());
     if ($comment_form) {
         $page_pane->appendChild($comment_form->render());
     }
     return $this->buildStandardPageResponse($page_pane, array('title' => 'D' . $revision->getID() . ' ' . $revision->getTitle()));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $revision = id(new DifferentialRevision())->load($this->revisionID);
     if (!$revision) {
         return new Aphront404Response();
     }
     $revision->loadRelationships();
     $diffs = $revision->loadDiffs();
     if (!$diffs) {
         throw new Exception("This revision has no diffs. Something has gone quite wrong.");
     }
     $diff_vs = $request->getInt('vs');
     $target = end($diffs);
     $target_id = $request->getInt('id');
     if ($target_id) {
         if (isset($diffs[$target_id])) {
             $target = $diffs[$target_id];
         }
     }
     $diffs = mpull($diffs, null, 'getID');
     if (empty($diffs[$diff_vs])) {
         $diff_vs = null;
     }
     list($changesets, $vs_map, $rendering_references) = $this->loadChangesetsAndVsMap($diffs, $diff_vs, $target);
     $comments = $revision->loadComments();
     $comments = array_merge($this->getImplicitComments($revision), $comments);
     $all_changesets = $changesets;
     $inlines = $this->loadInlineComments($comments, $all_changesets);
     $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $user->getPHID()), mpull($comments, 'getAuthorPHID'));
     foreach ($comments as $comment) {
         $metadata = $comment->getMetadata();
         $added_reviewers = idx($metadata, DifferentialComment::METADATA_ADDED_REVIEWERS);
         if ($added_reviewers) {
             foreach ($added_reviewers as $phid) {
                 $object_phids[] = $phid;
             }
         }
         $added_ccs = idx($metadata, DifferentialComment::METADATA_ADDED_CCS);
         if ($added_ccs) {
             foreach ($added_ccs as $phid) {
                 $object_phids[] = $phid;
             }
         }
     }
     if ($target->getArcanistProjectPHID()) {
         $object_phids[] = $target->getArcanistProjectPHID();
     }
     foreach ($revision->getAttached() as $type => $phids) {
         foreach ($phids as $phid => $info) {
             $object_phids[] = $phid;
         }
     }
     $object_phids = array_unique($object_phids);
     $handles = id(new PhabricatorObjectHandleData($object_phids))->loadHandles();
     $request_uri = $request->getRequestURI();
     $limit = 100;
     $large = $request->getStr('large');
     if (count($changesets) > $limit && !$large) {
         $count = number_format(count($changesets));
         $warning = new AphrontErrorView();
         $warning->setTitle('Very Large Diff');
         $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING);
         $warning->setWidth(AphrontErrorView::WIDTH_WIDE);
         $warning->appendChild("<p>This diff is very large and affects {$count} files. Use " . "Table of Contents to open files in a standalone view. " . "<strong>" . phutil_render_tag('a', array('href' => $request_uri->alter('large', 'true')), 'Show All Files Inline') . "</strong>");
         $warning = $warning->render();
         $visible_changesets = array();
     } else {
         $warning = null;
         $visible_changesets = $changesets;
     }
     $diff_properties = id(new DifferentialDiffProperty())->loadAllWhere('diffID = %d AND name IN (%Ls)', $target->getID(), array('arc:lint', 'arc:unit'));
     $diff_properties = mpull($diff_properties, 'getData', 'getName');
     $revision_detail = new DifferentialRevisionDetailView();
     $revision_detail->setRevision($revision);
     $custom_renderer_class = PhabricatorEnv::getEnvConfig('differential.revision-custom-detail-renderer');
     if ($custom_renderer_class) {
         PhutilSymbolLoader::loadClass($custom_renderer_class);
         $custom_renderer = newv($custom_renderer_class, array());
     } else {
         $custom_renderer = null;
     }
     $properties = $this->getRevisionProperties($revision, $target, $handles, $diff_properties);
     if ($custom_renderer) {
         $properties = array_merge($properties, $custom_renderer->generateProperties($revision, $target));
     }
     $revision_detail->setProperties($properties);
     $actions = $this->getRevisionActions($revision);
     if ($custom_renderer) {
         $actions = array_merge($actions, $custom_renderer->generateActionLinks($revision, $target));
     }
     $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_ALL);
     $revision_detail->setActions($actions);
     $revision_detail->setUser($user);
     $comment_view = new DifferentialRevisionCommentListView();
     $comment_view->setComments($comments);
     $comment_view->setHandles($handles);
     $comment_view->setInlineComments($inlines);
     $comment_view->setChangesets($all_changesets);
     $comment_view->setUser($user);
     $comment_view->setTargetDiff($target);
     $changeset_view = new DifferentialChangesetListView();
     $changeset_view->setChangesets($visible_changesets);
     $changeset_view->setEditable(true);
     $changeset_view->setStandaloneViews(true);
     $changeset_view->setRevision($revision);
     $changeset_view->setRenderingReferences($rendering_references);
     $changeset_view->setWhitespace($whitespace);
     $diff_history = new DifferentialRevisionUpdateHistoryView();
     $diff_history->setDiffs($diffs);
     $diff_history->setSelectedVersusDiffID($diff_vs);
     $diff_history->setSelectedDiffID($target->getID());
     $diff_history->setSelectedWhitespace($whitespace);
     $toc_view = new DifferentialDiffTableOfContentsView();
     $toc_view->setChangesets($changesets);
     $toc_view->setStandaloneViewLink(empty($visible_changesets));
     $toc_view->setVsMap($vs_map);
     $toc_view->setRevisionID($revision->getID());
     $toc_view->setWhitespace($whitespace);
     $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID());
     if ($draft) {
         $draft = $draft->getDraft();
     } else {
         $draft = null;
     }
     $comment_form = new DifferentialAddCommentView();
     $comment_form->setRevision($revision);
     $comment_form->setActions($this->getRevisionCommentActions($revision));
     $comment_form->setActionURI('/differential/comment/save/');
     $comment_form->setUser($user);
     $comment_form->setDraft($draft);
     $this->updateViewTime($user->getPHID(), $revision->getPHID());
     $pane_id = celerity_generate_unique_node_id();
     Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id));
     return $this->buildStandardPageResponse(id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets($changesets)->setID($pane_id)->appendChild($revision_detail->render() . $comment_view->render() . $diff_history->render() . $warning . $toc_view->render() . $changeset_view->render() . $comment_form->render()), array('title' => 'D' . $revision->getID() . ' ' . $revision->getTitle()));
 }