public function render()
 {
     $viewer = $this->getViewer();
     $this->requireResource('differential-revision-add-comment-css');
     $revision = $this->revision;
     $action = null;
     if ($this->draft) {
         $action = idx($this->draft->getMetadata(), 'action');
     }
     $enable_reviewers = DifferentialAction::allowReviewers($action);
     $enable_ccs = $action == DifferentialAction::ACTION_ADDCCS;
     $add_reviewers_labels = array('add_reviewers' => pht('Add Reviewers'), 'request_review' => pht('Add Reviewers'), 'resign' => pht('Suggest Reviewers'));
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     // TODO: This should be a reviewers datasource, but it's a mess.
     $reviewer_source = new PhabricatorMetaMTAMailableDatasource();
     $form = new AphrontFormView();
     $form->setWorkflow(true)->setViewer($viewer)->setAction($this->actionURI)->addHiddenInput('revision_id', $revision->getID())->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Action'))->setName('action')->setValue($action)->setID('comment-action')->setOptions($this->actions))->appendControl(id(new AphrontFormTokenizerControl())->setLabel($enable_reviewers ? $add_reviewers_labels[$action] : $add_reviewers_labels['add_reviewers'])->setName('reviewers')->setControlID('add-reviewers')->setControlStyle($enable_reviewers ? null : 'display: none')->setID('add-reviewers-tokenizer')->setDisableBehavior(true)->setDatasource($reviewer_source))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Add Subscribers'))->setName('ccs')->setControlID('add-ccs')->setControlStyle($enable_ccs ? null : 'display: none')->setID('add-ccs-tokenizer')->setDisableBehavior(true)->setDatasource($mailable_source))->appendChild(id(new PhabricatorRemarkupControl())->setName('comment')->setID('comment-content')->setLabel(pht('Comment'))->setValue($this->draft ? $this->draft->getDraft() : null)->setViewer($viewer))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Submit')));
     Javelin::initBehavior('differential-add-reviewers-and-ccs', array('dynamic' => array('add-reviewers-tokenizer' => array('actions' => array('request_review' => 1, 'add_reviewers' => 1, 'resign' => 1), 'src' => $reviewer_source->getDatasourceURI(), 'value' => $this->reviewers, 'row' => 'add-reviewers', 'labels' => $add_reviewers_labels, 'placeholder' => $reviewer_source->getPlaceholderText()), 'add-ccs-tokenizer' => array('actions' => array('add_ccs' => 1), 'src' => $mailable_source->getDatasourceURI(), 'value' => $this->ccs, 'row' => 'add-ccs', 'placeholder' => $mailable_source->getPlaceholderText())), 'select' => 'comment-action'));
     $diff = $revision->loadActiveDiff();
     $rev_id = $revision->getID();
     Javelin::initBehavior('differential-feedback-preview', array('uri' => '/differential/comment/preview/' . $rev_id . '/', 'preview' => 'comment-preview', 'action' => 'comment-action', 'content' => 'comment-content', 'previewTokenizers' => array('reviewers' => 'add-reviewers-tokenizer', 'ccs' => 'add-ccs-tokenizer'), 'inlineuri' => '/differential/comment/inline/preview/' . $rev_id . '/', 'inline' => 'inline-comment-preview'));
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     $header_text = $is_serious ? pht('Add Comment') : pht('Leap Into Action!');
     $header = id(new PHUIHeaderView())->setHeader($header_text);
     $anchor = id(new PhabricatorAnchorView())->setAnchorName('comment')->setNavigationMarker(true);
     $loading = phutil_tag('span', array('class' => 'aphront-panel-preview-loading-text'), pht('Loading comment preview...'));
     $preview = phutil_tag_div('aphront-panel-preview aphront-panel-flush', array(phutil_tag('div', array('id' => 'comment-preview'), $loading), phutil_tag('div', array('id' => 'inline-comment-preview'))));
     $comment_box = id(new PHUIObjectBoxView())->setHeader($header)->appendChild($anchor)->appendChild($form);
     if ($this->errorView) {
         $comment_box->setInfoView($this->errorView);
     }
     return array($comment_box, $preview);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $author_phid = $request->getUser()->getPHID();
     $action = $request->getStr('action');
     $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
     $comment = new DifferentialComment();
     $comment->setContent($request->getStr('content'));
     $comment->setAction($action);
     $comment->setAuthorPHID($author_phid);
     $handles = array($author_phid);
     $reviewers = $request->getStrList('reviewers');
     if (DifferentialAction::allowReviewers($action) && $reviewers) {
         $comment->setMetadata(array(DifferentialComment::METADATA_ADDED_REVIEWERS => $reviewers));
         $handles = array_merge($handles, $reviewers);
     }
     $ccs = $request->getStrList('ccs');
     if ($action == DifferentialAction::ACTION_ADDCCS && $ccs) {
         $comment->setMetadata(array(DifferentialComment::METADATA_ADDED_CCS => $ccs));
         $handles = array_merge($handles, $ccs);
     }
     $handles = $this->loadViewerHandles($handles);
     $view = new DifferentialRevisionCommentView();
     $view->setUser($request->getUser());
     $view->setComment($comment);
     $view->setHandles($handles);
     $view->setMarkupEngine($engine);
     $view->setPreview(true);
     $view->setTargetDiff(null);
     $metadata = array('reviewers' => $reviewers, 'ccs' => $ccs);
     if ($action != DifferentialAction::ACTION_COMMENT) {
         $metadata['action'] = $action;
     }
     id(new PhabricatorDraft())->setAuthorPHID($author_phid)->setDraftKey('differential-comment-' . $this->id)->setDraft($comment->getContent())->setMetadata($metadata)->replaceOrDelete();
     return id(new AphrontAjaxResponse())->setContent($view->render());
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$revision) {
         return new Aphront404Response();
     }
     $type_comment = PhabricatorTransactions::TYPE_COMMENT;
     $type_action = DifferentialTransaction::TYPE_ACTION;
     $type_edge = PhabricatorTransactions::TYPE_EDGE;
     $type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS;
     $xactions = array();
     $action = $request->getStr('action');
     switch ($action) {
         case DifferentialAction::ACTION_COMMENT:
         case DifferentialAction::ACTION_ADDREVIEWERS:
         case DifferentialAction::ACTION_ADDCCS:
             break;
         default:
             $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_action)->setNewValue($action);
             break;
     }
     $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
     $reviewers = $request->getStrList('reviewers');
     if (DifferentialAction::allowReviewers($action) && $reviewers) {
         $faux_edges = array();
         foreach ($reviewers as $phid) {
             $faux_edges[$phid] = array('src' => $revision->getPHID(), 'type' => $edge_reviewer, 'dst' => $phid);
         }
         $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_edge)->setMetadataValue('edge:type', $edge_reviewer)->setOldValue(array())->setNewValue($faux_edges);
     }
     $ccs = $request->getStrList('ccs');
     if ($ccs) {
         $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_subscribers)->setOldValue(array())->setNewValue(array_fuse($ccs));
     }
     // Add a comment transaction if there's nothing, so we'll generate a
     // nonempty result.
     if (strlen($request->getStr('content')) || !$xactions) {
         $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_comment)->attachComment(id(new ManiphestTransactionComment())->setContent($request->getStr('content')));
     }
     foreach ($xactions as $xaction) {
         $xaction->setAuthorPHID($viewer->getPHID());
     }
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($request->getUser());
     foreach ($xactions as $xaction) {
         if ($xaction->hasComment()) {
             $engine->addObject($xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
         }
     }
     $engine->process();
     $phids = mpull($xactions, 'getRequiredHandlePHIDs');
     $phids = array_mergev($phids);
     $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs($phids)->execute();
     foreach ($xactions as $xaction) {
         $xaction->setHandles($handles);
     }
     $view = id(new DifferentialTransactionView())->setUser($viewer)->setTransactions($xactions)->setIsPreview(true);
     $metadata = array('reviewers' => $reviewers, 'ccs' => $ccs);
     if ($action != DifferentialAction::ACTION_COMMENT) {
         $metadata['action'] = $action;
     }
     $draft_key = 'differential-comment-' . $id;
     $draft = id(new PhabricatorDraft())->setAuthorPHID($viewer->getPHID())->setDraftKey($draft_key)->setDraft($request->getStr('content'))->setMetadata($metadata)->replaceOrDelete();
     if ($draft->isDeleted()) {
         DifferentialDraft::deleteHasDraft($viewer->getPHID(), $revision->getPHID(), $draft_key);
     } else {
         DifferentialDraft::markHasDraft($viewer->getPHID(), $revision->getPHID(), $draft_key);
     }
     return id(new AphrontAjaxResponse())->setContent((string) phutil_implode_html('', $view->buildEvents()));
 }
 public function render()
 {
     require_celerity_resource('differential-revision-add-comment-css');
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     $revision = $this->revision;
     $action = null;
     if ($this->draft) {
         $action = idx($this->draft->getMetadata(), 'action');
     }
     $enable_reviewers = DifferentialAction::allowReviewers($action);
     $enable_ccs = $action == DifferentialAction::ACTION_ADDCCS;
     $form = new AphrontFormView();
     $form->setWorkflow(true)->setUser($this->user)->setAction($this->actionURI)->addHiddenInput('revision_id', $revision->getID())->appendChild(id(new AphrontFormSelectControl())->setLabel('Action')->setName('action')->setValue($action)->setID('comment-action')->setOptions($this->actions))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Add Reviewers')->setName('reviewers')->setControlID('add-reviewers')->setControlStyle($enable_reviewers ? null : 'display: none')->setID('add-reviewers-tokenizer')->setDisableBehavior(true))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Add CCs')->setName('ccs')->setControlID('add-ccs')->setControlStyle($enable_ccs ? null : 'display: none')->setID('add-ccs-tokenizer')->setDisableBehavior(true))->appendChild(id(new PhabricatorRemarkupControl())->setName('comment')->setID('comment-content')->setLabel('Comment')->setValue($this->draft ? $this->draft->getDraft() : null))->appendChild(id(new AphrontFormSubmitControl())->setValue($is_serious ? 'Submit' : 'Clowncopterize'));
     Javelin::initBehavior('differential-add-reviewers-and-ccs', array('dynamic' => array('add-reviewers-tokenizer' => array('actions' => array('request_review' => 1, 'add_reviewers' => 1), 'src' => '/typeahead/common/users/', 'value' => $this->reviewers, 'row' => 'add-reviewers', 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a user name...'), 'add-ccs-tokenizer' => array('actions' => array('add_ccs' => 1), 'src' => '/typeahead/common/mailable/', 'value' => $this->ccs, 'row' => 'add-ccs', 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a user or mailing list...')), 'select' => 'comment-action'));
     $diff = $revision->loadActiveDiff();
     $warnings = mpull($this->auxFields, 'renderWarningBoxForRevisionAccept');
     $lint_warning = null;
     $unit_warning = null;
     Javelin::initBehavior('differential-accept-with-errors', array('select' => 'comment-action', 'warnings' => 'warnings'));
     $rev_id = $revision->getID();
     Javelin::initBehavior('differential-feedback-preview', array('uri' => '/differential/comment/preview/' . $rev_id . '/', 'preview' => 'comment-preview', 'action' => 'comment-action', 'content' => 'comment-content', 'previewTokenizers' => array('reviewers' => 'add-reviewers-tokenizer', 'ccs' => 'add-ccs-tokenizer'), 'inlineuri' => '/differential/comment/inline/preview/' . $rev_id . '/', 'inline' => 'inline-comment-preview'));
     $panel_view = new AphrontPanelView();
     $panel_view->appendChild($form);
     $warning_container = '<div id="warnings">';
     foreach ($warnings as $warning) {
         if ($warning) {
             $warning_container .= $warning->render();
         }
     }
     $warning_container .= '</div>';
     $panel_view->appendChild($warning_container);
     if ($lint_warning) {
         $panel_view->appendChild($lint_warning);
     }
     if ($unit_warning) {
         $panel_view->appendChild($unit_warning);
     }
     $panel_view->setHeader($is_serious ? 'Add Comment' : 'Leap Into Action');
     $panel_view->addClass('aphront-panel-accent');
     $panel_view->addClass('aphront-panel-flush');
     return id(new PhabricatorAnchorView())->setAnchorName('comment')->setNavigationMarker(true)->render() . '<div class="differential-add-comment-panel">' . $panel_view->render() . '<div class="aphront-panel-preview aphront-panel-flush">' . '<div id="comment-preview">' . '<span class="aphront-panel-preview-loading-text">' . 'Loading comment preview...' . '</span>' . '</div>' . '<div id="inline-comment-preview">' . '</div>' . '</div>' . '</div>';
 }