public static function indexRevision(DifferentialRevision $rev)
 {
     $doc = new PhabricatorSearchAbstractDocument();
     $doc->setPHID($rev->getPHID());
     $doc->setDocumentType(PhabricatorPHIDConstants::PHID_TYPE_DREV);
     $doc->setDocumentTitle($rev->getTitle());
     $doc->setDocumentCreated($rev->getDateCreated());
     $doc->setDocumentModified($rev->getDateModified());
     $doc->addField(PhabricatorSearchField::FIELD_BODY, $rev->getSummary());
     $doc->addField(PhabricatorSearchField::FIELD_TEST_PLAN, $rev->getTestPlan());
     $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated());
     if ($rev->getStatus() != ArcanistDifferentialRevisionStatus::CLOSED && $rev->getStatus() != ArcanistDifferentialRevisionStatus::ABANDONED) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OPEN, $rev->getPHID(), PhabricatorPHIDConstants::PHID_TYPE_DREV, time());
     }
     $comments = id(new DifferentialComment())->loadAllWhere('revisionID = %d', $rev->getID());
     $inlines = id(new DifferentialInlineComment())->loadAllWhere('revisionID = %d AND commentID IS NOT NULL', $rev->getID());
     $touches = array();
     foreach (array_merge($comments, $inlines) as $comment) {
         if (strlen($comment->getContent())) {
             $doc->addField(PhabricatorSearchField::FIELD_COMMENT, $comment->getContent());
         }
         $author = $comment->getAuthorPHID();
         $touches[$author] = $comment->getDateCreated();
     }
     foreach ($touches as $touch => $time) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_TOUCH, $touch, PhabricatorPHIDConstants::PHID_TYPE_USER, $time);
     }
     $rev->loadRelationships();
     // If a revision needs review, the owners are the reviewers. Otherwise, the
     // owner is the author (e.g., accepted, rejected, closed).
     if ($rev->getStatus() == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
         foreach ($rev->getReviewers() as $phid) {
             $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $phid, PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateModified());
             // Bogus timestamp.
         }
     } else {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated());
     }
     $ccphids = $rev->getCCPHIDs();
     $handles = id(new PhabricatorObjectHandleData($ccphids))->loadHandles();
     foreach ($handles as $phid => $handle) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_SUBSCRIBER, $phid, $handle->getType(), $rev->getDateModified());
         // Bogus timestamp.
     }
     self::reindexAbstractDocument($doc);
 }
 private function getRevisionCommentActions(DifferentialRevision $revision)
 {
     $actions = array(DifferentialAction::ACTION_COMMENT => true);
     $viewer = $this->getRequest()->getUser();
     $viewer_phid = $viewer->getPHID();
     $viewer_is_owner = $viewer_phid == $revision->getAuthorPHID();
     $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers());
     $status = $revision->getStatus();
     $viewer_has_accepted = false;
     $viewer_has_rejected = false;
     $status_accepted = DifferentialReviewerStatus::STATUS_ACCEPTED;
     $status_rejected = DifferentialReviewerStatus::STATUS_REJECTED;
     foreach ($revision->getReviewerStatus() as $reviewer) {
         if ($reviewer->getReviewerPHID() == $viewer_phid) {
             if ($reviewer->getStatus() == $status_accepted) {
                 $viewer_has_accepted = true;
             }
             if ($reviewer->getStatus() == $status_rejected) {
                 $viewer_has_rejected = true;
             }
             break;
         }
     }
     $allow_self_accept = PhabricatorEnv::getEnvConfig('differential.allow-self-accept');
     $always_allow_abandon = PhabricatorEnv::getEnvConfig('differential.always-allow-abandon');
     $always_allow_close = PhabricatorEnv::getEnvConfig('differential.always-allow-close');
     $allow_reopen = PhabricatorEnv::getEnvConfig('differential.allow-reopen');
     if ($viewer_is_owner) {
         switch ($status) {
             case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ACCEPT] = $allow_self_accept;
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 break;
             case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
             case ArcanistDifferentialRevisionStatus::CHANGES_PLANNED:
                 $actions[DifferentialAction::ACTION_ACCEPT] = $allow_self_accept;
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 break;
             case ArcanistDifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 $actions[DifferentialAction::ACTION_CLOSE] = true;
                 break;
             case ArcanistDifferentialRevisionStatus::CLOSED:
                 break;
             case ArcanistDifferentialRevisionStatus::ABANDONED:
                 $actions[DifferentialAction::ACTION_RECLAIM] = true;
                 break;
         }
     } else {
         switch ($status) {
             case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ABANDON] = $always_allow_abandon;
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
             case ArcanistDifferentialRevisionStatus::CHANGES_PLANNED:
                 $actions[DifferentialAction::ACTION_ABANDON] = $always_allow_abandon;
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_REJECT] = !$viewer_has_rejected;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case ArcanistDifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_ABANDON] = $always_allow_abandon;
                 $actions[DifferentialAction::ACTION_ACCEPT] = !$viewer_has_accepted;
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case ArcanistDifferentialRevisionStatus::CLOSED:
             case ArcanistDifferentialRevisionStatus::ABANDONED:
                 break;
         }
         if ($status != ArcanistDifferentialRevisionStatus::CLOSED) {
             $actions[DifferentialAction::ACTION_CLAIM] = true;
             $actions[DifferentialAction::ACTION_CLOSE] = $always_allow_close;
         }
     }
     $actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
     $actions[DifferentialAction::ACTION_ADDCCS] = true;
     $actions[DifferentialAction::ACTION_REOPEN] = $allow_reopen && $status == ArcanistDifferentialRevisionStatus::CLOSED;
     $actions = array_keys(array_filter($actions));
     $actions_dict = array();
     foreach ($actions as $action) {
         $actions_dict[$action] = DifferentialAction::getActionVerb($action);
     }
     return $actions_dict;
 }
 public function getRequiredHandlePHIDsForRevisionList(DifferentialRevision $revision)
 {
     return $revision->getReviewers();
 }
 private function getRevisionCommentActions(DifferentialRevision $revision)
 {
     $actions = array(DifferentialAction::ACTION_COMMENT => true);
     $viewer = $this->getRequest()->getUser();
     $viewer_phid = $viewer->getPHID();
     $viewer_is_owner = $viewer_phid == $revision->getAuthorPHID();
     $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers());
     $viewer_did_accept = $viewer_phid === $revision->loadReviewedBy();
     $status = $revision->getStatus();
     $allow_self_accept = PhabricatorEnv::getEnvConfig('differential.allow-self-accept', false);
     if ($viewer_is_owner) {
         switch ($status) {
             case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ACCEPT] = $allow_self_accept;
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 break;
             case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
                 $actions[DifferentialAction::ACTION_ACCEPT] = $allow_self_accept;
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 break;
             case ArcanistDifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 $actions[DifferentialAction::ACTION_CLOSE] = true;
                 break;
             case ArcanistDifferentialRevisionStatus::CLOSED:
                 break;
             case ArcanistDifferentialRevisionStatus::ABANDONED:
                 $actions[DifferentialAction::ACTION_RECLAIM] = true;
                 break;
         }
     } else {
         switch ($status) {
             case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case ArcanistDifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer && !$viewer_did_accept;
                 break;
             case ArcanistDifferentialRevisionStatus::CLOSED:
             case ArcanistDifferentialRevisionStatus::ABANDONED:
                 break;
         }
         if ($status != ArcanistDifferentialRevisionStatus::CLOSED) {
             $actions[DifferentialAction::ACTION_CLAIM] = true;
         }
     }
     $actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
     $actions[DifferentialAction::ACTION_ADDCCS] = true;
     $actions = array_keys(array_filter($actions));
     $actions_dict = array();
     foreach ($actions as $action) {
         $actions_dict[$action] = DifferentialAction::getActionVerb($action);
     }
     return $actions_dict;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     if (!$this->id) {
         $this->id = $request->getInt('revisionID');
     }
     if ($this->id) {
         $revision = id(new DifferentialRevision())->load($this->id);
         if (!$revision) {
             return new Aphront404Response();
         }
     } else {
         $revision = new DifferentialRevision();
     }
     $diff_id = $request->getInt('diffID');
     if ($diff_id) {
         $diff = id(new DifferentialDiff())->load($diff_id);
         if (!$diff) {
             return new Aphront404Response();
         }
         if ($diff->getRevisionID()) {
             // TODO: Redirect?
             throw new Exception("This diff is already attached to a revision!");
         }
     } else {
         $diff = null;
     }
     $e_title = true;
     $e_testplan = true;
     $e_reviewers = null;
     $errors = array();
     $revision->loadRelationships();
     if ($request->isFormPost() && !$request->getStr('viaDiffView')) {
         $revision->setTitle($request->getStr('title'));
         $revision->setSummary($request->getStr('summary'));
         $revision->setTestPlan($request->getStr('testplan'));
         $revision->setBlameRevision($request->getStr('blame'));
         $revision->setRevertPlan($request->getStr('revert'));
         if (!strlen(trim($revision->getTitle()))) {
             $errors[] = 'You must provide a title.';
             $e_title = 'Required';
         } else {
             $e_title = null;
         }
         if (!strlen(trim($revision->getTestPlan()))) {
             $errors[] = 'You must provide a test plan.';
             $e_testplan = 'Required';
         } else {
             $e_testplan = null;
         }
         $user_phid = $request->getUser()->getPHID();
         if (in_array($user_phid, $request->getArr('reviewers'))) {
             $errors[] = 'You may not review your own revision.';
             $e_reviewers = 'Invalid';
         }
         if (!$errors) {
             $editor = new DifferentialRevisionEditor($revision, $user_phid);
             if ($diff) {
                 $editor->addDiff($diff, $request->getStr('comments'));
             }
             $editor->setCCPHIDs($request->getArr('cc'));
             $editor->setReviewers($request->getArr('reviewers'));
             $editor->save();
             return id(new AphrontRedirectResponse())->setURI('/D' . $revision->getID());
         }
         $reviewer_phids = $request->getArr('reviewers');
         $cc_phids = $request->getArr('cc');
     } else {
         $reviewer_phids = $revision->getReviewers();
         $cc_phids = $revision->getCCPHIDs();
     }
     $phids = array_merge($reviewer_phids, $cc_phids);
     $phids = array_unique($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $handles = mpull($handles, 'getFullName', 'getPHID');
     $reviewer_map = array_select_keys($handles, $reviewer_phids);
     $cc_map = array_select_keys($handles, $cc_phids);
     $form = new AphrontFormView();
     $form->setUser($request->getUser());
     if ($diff) {
         $form->addHiddenInput('diffID', $diff->getID());
     }
     if ($revision->getID()) {
         $form->setAction('/differential/revision/edit/' . $revision->getID() . '/');
     } else {
         $form->setAction('/differential/revision/edit/');
     }
     $error_view = null;
     if ($errors) {
         $error_view = id(new AphrontErrorView())->setTitle('Form Errors')->setErrors($errors);
     }
     if ($diff && $revision->getID()) {
         $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Comments')->setName('comments')->setCaption("Explain what's new in this diff.")->setValue($request->getStr('comments')))->appendChild(id(new AphrontFormSubmitControl())->setValue('Save'))->appendChild(id(new AphrontFormDividerControl()));
     }
     $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Title')->setName('title')->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)->setValue($revision->getTitle())->setError($e_title))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Summary')->setName('summary')->setValue($revision->getSummary()))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Test Plan')->setName('testplan')->setValue($revision->getTestPlan())->setError($e_testplan))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Reviewers')->setName('reviewers')->setDatasource('/typeahead/common/users/')->setError($e_reviewers)->setValue($reviewer_map))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('CC')->setName('cc')->setDatasource('/typeahead/common/mailable/')->setValue($cc_map))->appendChild(id(new AphrontFormTextControl())->setLabel('Blame Revision')->setName('blame')->setValue($revision->getBlameRevision())->setCaption('Revision which broke the stuff which this ' . 'change fixes.'))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Revert Plan')->setName('revert')->setValue($revision->getRevertPlan())->setCaption('Special steps required to safely revert this change.'));
     $submit = id(new AphrontFormSubmitControl())->setValue('Save');
     if ($diff) {
         $submit->addCancelButton('/differential/diff/' . $diff->getID() . '/');
     } else {
         $submit->addCancelButton('/D' . $revision->getID());
     }
     $form->appendChild($submit);
     $panel = new AphrontPanelView();
     if ($revision->getID()) {
         if ($diff) {
             $panel->setHeader('Update Differential Revision');
         } else {
             $panel->setHeader('Edit Differential Revision');
         }
     } else {
         $panel->setHeader('Create New Differential Revision');
     }
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Edit Differential Revision'));
 }
 private static function getImpliedCCs(DifferentialRevision $revision)
 {
     return array_merge($revision->getReviewers(), array($revision->getAuthorPHID()));
 }
 /**
  * @return array($reviewed, $not_reviewed)
  */
 public function computeTimes(DifferentialRevision $revision, array $comments)
 {
     assert_instances_of($comments, 'DifferentialComment');
     $add_rev = DifferentialComment::METADATA_ADDED_REVIEWERS;
     $rem_rev = DifferentialComment::METADATA_REMOVED_REVIEWERS;
     $date = $revision->getDateCreated();
     // Find out original reviewers.
     $reviewers = array_fill_keys($revision->getReviewers(), $date);
     foreach (array_reverse($comments) as $comment) {
         $metadata = $comment->getMetadata();
         foreach (idx($metadata, $add_rev, array()) as $phid) {
             unset($reviewers[$phid]);
         }
         foreach (idx($metadata, $rem_rev, array()) as $phid) {
             $reviewers[$phid] = $date;
         }
     }
     $reviewed = array();
     $not_reviewed = array();
     $status = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
     foreach ($comments as $comment) {
         $date = $comment->getDateCreated();
         $old_status = $status;
         switch ($comment->getAction()) {
             case DifferentialAction::ACTION_UPDATE:
                 if ($status != ArcanistDifferentialRevisionStatus::CLOSED && $status != ArcanistDifferentialRevisionStatus::ACCEPTED) {
                     $status = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
                 }
                 break;
             case DifferentialAction::ACTION_REQUEST:
             case DifferentialAction::ACTION_RECLAIM:
                 $status = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
                 break;
             case DifferentialAction::ACTION_REJECT:
             case DifferentialAction::ACTION_RETHINK:
                 $status = ArcanistDifferentialRevisionStatus::NEEDS_REVISION;
                 break;
             case DifferentialAction::ACTION_ACCEPT:
                 $status = ArcanistDifferentialRevisionStatus::ACCEPTED;
                 break;
             case DifferentialAction::ACTION_CLOSE:
                 $status = ArcanistDifferentialRevisionStatus::CLOSED;
                 break;
             case DifferentialAction::ACTION_ABANDON:
                 $status = ArcanistDifferentialRevisionStatus::ABANDONED;
                 break;
         }
         // Update current reviewers.
         $metadata = $comment->getMetadata();
         foreach (idx($metadata, $add_rev, array()) as $phid) {
             // If someone reviewed a revision without being its reviewer then give
             // him zero response time.
             $reviewers[$phid] = $date;
         }
         foreach (idx($metadata, $rem_rev, array()) as $phid) {
             $start = idx($reviewers, $phid);
             if ($start !== null) {
                 if ($date >= $this->since) {
                     $reviewed[$phid][] = $date - $start;
                 }
                 unset($reviewers[$phid]);
             }
         }
         // TODO: Respect workdays and status away.
         if ($old_status != $status) {
             if ($status == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
                 $reviewers = array_fill_keys(array_keys($reviewers), $date);
             } else {
                 if ($date >= $this->since) {
                     if ($old_status == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
                         foreach ($reviewers as $phid => $start) {
                             if ($phid == $comment->getAuthorPHID()) {
                                 $reviewed[$phid][] = $date - $start;
                             } else {
                                 $not_reviewed[$phid][] = $date - $start;
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($status == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
         $date = $this->until !== null ? $this->until : time();
         if ($date >= $this->since) {
             foreach ($reviewers as $phid => $start) {
                 $not_reviewed[$phid][] = $date - $start;
             }
         }
     }
     return array($reviewed, $not_reviewed);
 }
 private function getRevisionCommentActions(DifferentialRevision $revision)
 {
     $actions = array(DifferentialAction::ACTION_COMMENT => true);
     $admin_actions = array();
     $viewer = $this->getRequest()->getUser();
     $viewer_phid = $viewer->getPHID();
     $viewer_is_admin = $viewer->getIsAdmin();
     $viewer_is_owner = $viewer_phid == $revision->getAuthorPHID();
     $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers());
     $viewer_did_accept = $viewer_phid === $revision->loadReviewedBy();
     if ($viewer_is_owner) {
         switch ($revision->getStatus()) {
             case DifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 break;
             case DifferentialRevisionStatus::NEEDS_REVISION:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 break;
             case DifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 break;
             case DifferentialRevisionStatus::COMMITTED:
                 break;
             case DifferentialRevisionStatus::ABANDONED:
                 $actions[DifferentialAction::ACTION_RECLAIM] = true;
                 break;
         }
     } else {
         switch ($revision->getStatus()) {
             case DifferentialRevisionStatus::NEEDS_REVIEW:
                 $admin_actions[DifferentialAction::ACTION_ABANDON] = $viewer_is_admin;
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case DifferentialRevisionStatus::NEEDS_REVISION:
                 $admin_actions[DifferentialAction::ACTION_ABANDON] = $viewer_is_admin;
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case DifferentialRevisionStatus::ACCEPTED:
                 $admin_actions[DifferentialAction::ACTION_ABANDON] = $viewer_is_admin;
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer && !$viewer_did_accept;
                 break;
             case DifferentialRevisionStatus::COMMITTED:
             case DifferentialRevisionStatus::ABANDONED:
                 break;
         }
     }
     $actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
     $actions[DifferentialAction::ACTION_ADDCCS] = true;
     $actions = array_keys(array_filter($actions));
     $admin_actions = array_keys(array_filter($admin_actions));
     $actions_dict = array();
     foreach ($actions as $action) {
         $actions_dict[$action] = DifferentialAction::getActionVerb($action);
     }
     foreach ($admin_actions as $action) {
         $actions_dict[$action] = '(Admin) ' . DifferentialAction::getActionVerb($action);
     }
     return $actions_dict;
 }
 public function renderValueForRevisionList(DifferentialRevision $revision)
 {
     $primary_reviewer = $revision->getPrimaryReviewer();
     if ($primary_reviewer) {
         $other_reviewers = array_flip($revision->getReviewers());
         unset($other_reviewers[$primary_reviewer]);
         if ($other_reviewers) {
             $suffix = ' (+' . count($other_reviewers) . ')';
         } else {
             $suffix = null;
         }
         return $this->getHandle($primary_reviewer)->renderLink() . $suffix;
     } else {
         return '<em>None</em>';
     }
 }
 private function getRevisionCommentActions(DifferentialRevision $revision)
 {
     $actions = array(DifferentialAction::ACTION_COMMENT => true);
     $viewer_phid = $this->getRequest()->getUser()->getPHID();
     $viewer_is_owner = $viewer_phid == $revision->getAuthorPHID();
     $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers());
     if ($viewer_is_owner) {
         switch ($revision->getStatus()) {
             case DifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 break;
             case DifferentialRevisionStatus::NEEDS_REVISION:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 break;
             case DifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_ABANDON] = true;
                 $actions[DifferentialAction::ACTION_REQUEST] = true;
                 $actions[DifferentialAction::ACTION_RETHINK] = true;
                 break;
             case DifferentialRevisionStatus::COMMITTED:
                 break;
             case DifferentialRevisionStatus::ABANDONED:
                 $actions[DifferentialAction::ACTION_RECLAIM] = true;
                 break;
         }
     } else {
         switch ($revision->getStatus()) {
             case DifferentialRevisionStatus::NEEDS_REVIEW:
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case DifferentialRevisionStatus::NEEDS_REVISION:
                 $actions[DifferentialAction::ACTION_ACCEPT] = true;
                 $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
                 break;
             case DifferentialRevisionStatus::ACCEPTED:
                 $actions[DifferentialAction::ACTION_REJECT] = true;
                 break;
             case DifferentialRevisionStatus::COMMITTED:
             case DifferentialRevisionStatus::ABANDONED:
                 break;
         }
     }
     $actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
     $actions[DifferentialAction::ACTION_ADDCCS] = true;
     return array_keys(array_filter($actions));
 }
 private function getPrimaryReviewer(DifferentialRevision $revision)
 {
     $primary_reviewer = $revision->getLastReviewerPHID();
     if (!$primary_reviewer) {
         $primary_reviewer = head($revision->getReviewers());
     }
     return $primary_reviewer;
 }