Differential D17106 Diff 41165 src/applications/differential/controller/DifferentialRevisionViewController.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/differential/controller/DifferentialRevisionViewController.php
| Show First 20 Lines • Show All 384 Lines • ▼ Show 20 Lines | if ($other_view) { | ||||
| ->appendChild($other_view)); | ->appendChild($other_view)); | ||||
| } | } | ||||
| $tab_view = id(new PHUIObjectBoxView()) | $tab_view = id(new PHUIObjectBoxView()) | ||||
| ->setHeaderText(pht('Revision Contents')) | ->setHeaderText(pht('Revision Contents')) | ||||
| ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) | ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) | ||||
| ->addTabGroup($tab_group); | ->addTabGroup($tab_group); | ||||
| $comment_form = null; | |||||
| if (!$viewer_is_anonymous) { | |||||
| $comment_form = $this->buildCommentForm($revision, $field_list); | |||||
| } | |||||
| $signatures = DifferentialRequiredSignaturesField::loadForRevision( | $signatures = DifferentialRequiredSignaturesField::loadForRevision( | ||||
| $revision); | $revision); | ||||
| $missing_signatures = false; | $missing_signatures = false; | ||||
| foreach ($signatures as $phid => $signed) { | foreach ($signatures as $phid => $signed) { | ||||
| if (!$signed) { | if (!$signed) { | ||||
| $missing_signatures = true; | $missing_signatures = true; | ||||
| } | } | ||||
| } | } | ||||
| Show All 15 Lines | if ($missing_signatures) { | ||||
| $footer[] = array( | $footer[] = array( | ||||
| $anchor, | $anchor, | ||||
| $warning, | $warning, | ||||
| $tab_view, | $tab_view, | ||||
| $changeset_view, | $changeset_view, | ||||
| ); | ); | ||||
| } | } | ||||
| if ($comment_form) { | $footer[] = id(new DifferentialRevisionEditEngine()) | ||||
| $footer[] = $comment_form; | ->setViewer($viewer) | ||||
| } else { | ->buildEditEngineCommentView($revision); | ||||
| // TODO: For now, just use this to get "Login to Comment". | |||||
| $footer[] = id(new PhabricatorApplicationTransactionCommentView()) | |||||
| ->setUser($viewer) | |||||
| ->setRequestURI($request->getRequestURI()); | |||||
| } | |||||
| $object_id = 'D'.$revision->getID(); | $object_id = 'D'.$revision->getID(); | ||||
| $operations_box = $this->buildOperationsBox($revision); | $operations_box = $this->buildOperationsBox($revision); | ||||
| $crumbs = $this->buildApplicationCrumbs(); | $crumbs = $this->buildApplicationCrumbs(); | ||||
| $crumbs->addTextCrumb($object_id, '/'.$object_id); | $crumbs->addTextCrumb($object_id, '/'.$object_id); | ||||
| $crumbs->setBorder(true); | $crumbs->setBorder(true); | ||||
| $filetree_on = $viewer->compareUserSetting( | $filetree_on = $viewer->compareUserSetting( | ||||
| PhabricatorShowFiletreeSetting::SETTINGKEY, | PhabricatorShowFiletreeSetting::SETTINGKEY, | ||||
| PhabricatorShowFiletreeSetting::VALUE_ENABLE_FILETREE); | PhabricatorShowFiletreeSetting::VALUE_ENABLE_FILETREE); | ||||
| $nav = null; | $nav = null; | ||||
| if ($filetree_on) { | if ($filetree_on) { | ||||
| $collapsed_key = PhabricatorFiletreeVisibleSetting::SETTINGKEY; | $collapsed_key = PhabricatorFiletreeVisibleSetting::SETTINGKEY; | ||||
| $collapsed_value = $viewer->getUserSetting($collapsed_key); | $collapsed_value = $viewer->getUserSetting($collapsed_key); | ||||
| $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) | $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) | ||||
| ->setTitle('D'.$revision->getID()) | ->setTitle('D'.$revision->getID()) | ||||
| ->setBaseURI(new PhutilURI('/D'.$revision->getID())) | ->setBaseURI(new PhutilURI('/D'.$revision->getID())) | ||||
| ->setCollapsed((bool)$collapsed_value) | ->setCollapsed((bool)$collapsed_value) | ||||
| ->build($changesets); | ->build($changesets); | ||||
| } | } | ||||
| // Haunt Mode | |||||
| $pane_id = celerity_generate_unique_node_id(); | |||||
| Javelin::initBehavior( | |||||
| 'differential-keyboard-navigation', | |||||
| array( | |||||
| 'haunt' => $pane_id, | |||||
| )); | |||||
| Javelin::initBehavior('differential-user-select'); | Javelin::initBehavior('differential-user-select'); | ||||
| $view = id(new PHUITwoColumnView()) | $view = id(new PHUITwoColumnView()) | ||||
| ->setHeader($header) | ->setHeader($header) | ||||
| ->setSubheader($subheader) | ->setSubheader($subheader) | ||||
| ->setCurtain($curtain) | ->setCurtain($curtain) | ||||
| ->setID($pane_id) | |||||
| ->setMainColumn(array( | ->setMainColumn(array( | ||||
| $operations_box, | $operations_box, | ||||
| $info_view, | $info_view, | ||||
| $details, | $details, | ||||
| $diff_detail_box, | $diff_detail_box, | ||||
| $unit_box, | $unit_box, | ||||
| $comment_view, | $comment_view, | ||||
| $signature_message, | $signature_message, | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | private function buildCurtain(DifferentialRevision $revision) { | ||||
| $relationship_submenu = $relationship_list->newActionMenu(); | $relationship_submenu = $relationship_list->newActionMenu(); | ||||
| if ($relationship_submenu) { | if ($relationship_submenu) { | ||||
| $curtain->addAction($relationship_submenu); | $curtain->addAction($relationship_submenu); | ||||
| } | } | ||||
| return $curtain; | return $curtain; | ||||
| } | } | ||||
| private function buildCommentForm( | |||||
| DifferentialRevision $revision, | |||||
| $field_list) { | |||||
| $viewer = $this->getViewer(); | |||||
| $draft = id(new PhabricatorDraft())->loadOneWhere( | |||||
| 'authorPHID = %s AND draftKey = %s', | |||||
| $viewer->getPHID(), | |||||
| 'differential-comment-'.$revision->getID()); | |||||
| $reviewers = array(); | |||||
| $ccs = array(); | |||||
| if ($draft) { | |||||
| $reviewers = idx($draft->getMetadata(), 'reviewers', array()); | |||||
| $ccs = idx($draft->getMetadata(), 'ccs', array()); | |||||
| if ($reviewers || $ccs) { | |||||
| $handles = $this->loadViewerHandles(array_merge($reviewers, $ccs)); | |||||
| $reviewers = array_select_keys($handles, $reviewers); | |||||
| $ccs = array_select_keys($handles, $ccs); | |||||
| } | |||||
| } | |||||
| $comment_form = id(new DifferentialAddCommentView()) | |||||
| ->setRevision($revision); | |||||
| $review_warnings = array(); | |||||
| foreach ($field_list->getFields() as $field) { | |||||
| $review_warnings[] = $field->getWarningsForDetailView(); | |||||
| } | |||||
| $review_warnings = array_mergev($review_warnings); | |||||
| if ($review_warnings) { | |||||
| $review_warnings_panel = id(new PHUIInfoView()) | |||||
| ->setSeverity(PHUIInfoView::SEVERITY_WARNING) | |||||
| ->setErrors($review_warnings); | |||||
| $comment_form->setInfoView($review_warnings_panel); | |||||
| } | |||||
| $action_uri = $this->getApplicationURI( | |||||
| 'comment/save/'.$revision->getID().'/'); | |||||
| $comment_form->setActions($this->getRevisionCommentActions($revision)) | |||||
| ->setActionURI($action_uri) | |||||
| ->setUser($viewer) | |||||
| ->setDraft($draft) | |||||
| ->setReviewers(mpull($reviewers, 'getFullName', 'getPHID')) | |||||
| ->setCCs(mpull($ccs, 'getFullName', 'getPHID')); | |||||
| // TODO: This just makes the "Z" key work. Generalize this and remove | |||||
| // it at some point. | |||||
| $comment_form = phutil_tag( | |||||
| 'div', | |||||
| array( | |||||
| 'class' => 'differential-add-comment-panel', | |||||
| ), | |||||
| $comment_form); | |||||
| return $comment_form; | |||||
| } | |||||
| private function getRevisionCommentActions(DifferentialRevision $revision) { | |||||
| $actions = array( | |||||
| DifferentialAction::ACTION_COMMENT => true, | |||||
| ); | |||||
| $viewer = $this->getViewer(); | |||||
| $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; | |||||
| } | |||||
| private function loadHistoryDiffStatus(array $diffs) { | private function loadHistoryDiffStatus(array $diffs) { | ||||
| assert_instances_of($diffs, 'DifferentialDiff'); | assert_instances_of($diffs, 'DifferentialDiff'); | ||||
| $diff_phids = mpull($diffs, 'getPHID'); | $diff_phids = mpull($diffs, 'getPHID'); | ||||
| $bad_unit_status = array( | $bad_unit_status = array( | ||||
| ArcanistUnitTestResult::RESULT_FAIL, | ArcanistUnitTestResult::RESULT_FAIL, | ||||
| ArcanistUnitTestResult::RESULT_BROKEN, | ArcanistUnitTestResult::RESULT_BROKEN, | ||||
| ); | ); | ||||
| ▲ Show 20 Lines • Show All 486 Lines • Show Last 20 Lines | |||||