Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/diff/PhabricatorInlineCommentController.php
| Show All 33 Lines | protected function showComments(array $ids) { | ||||
| throw new PhutilMethodNotImplementedException(); | throw new PhutilMethodNotImplementedException(); | ||||
| } | } | ||||
| private $changesetID; | private $changesetID; | ||||
| private $isNewFile; | private $isNewFile; | ||||
| private $isOnRight; | private $isOnRight; | ||||
| private $lineNumber; | private $lineNumber; | ||||
| private $lineLength; | private $lineLength; | ||||
| private $commentText; | |||||
| private $operation; | private $operation; | ||||
| private $commentID; | private $commentID; | ||||
| private $renderer; | private $renderer; | ||||
| private $replyToCommentPHID; | private $replyToCommentPHID; | ||||
| public function getCommentID() { | public function getCommentID() { | ||||
| return $this->commentID; | return $this->commentID; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | abstract class PhabricatorInlineCommentController | ||||
| public function getReplyToCommentPHID() { | public function getReplyToCommentPHID() { | ||||
| return $this->replyToCommentPHID; | return $this->replyToCommentPHID; | ||||
| } | } | ||||
| public function processRequest() { | public function processRequest() { | ||||
| $request = $this->getRequest(); | $request = $this->getRequest(); | ||||
| $viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
| if (!$request->validateCSRF()) { | |||||
| return new Aphront404Response(); | |||||
| } | |||||
| $this->readRequestParameters(); | $this->readRequestParameters(); | ||||
| $op = $this->getOperation(); | $op = $this->getOperation(); | ||||
| switch ($op) { | switch ($op) { | ||||
| case 'hide': | case 'hide': | ||||
| case 'show': | case 'show': | ||||
| if (!$request->validateCSRF()) { | |||||
| return new Aphront404Response(); | |||||
| } | |||||
| $ids = $request->getStrList('ids'); | $ids = $request->getStrList('ids'); | ||||
| if ($ids) { | if ($ids) { | ||||
| if ($op == 'hide') { | if ($op == 'hide') { | ||||
| $this->hideComments($ids); | $this->hideComments($ids); | ||||
| } else { | } else { | ||||
| $this->showComments($ids); | $this->showComments($ids); | ||||
| } | } | ||||
| } | } | ||||
| return id(new AphrontAjaxResponse())->setContent(array()); | return id(new AphrontAjaxResponse())->setContent(array()); | ||||
| case 'done': | case 'done': | ||||
| if (!$request->validateCSRF()) { | |||||
| return new Aphront404Response(); | |||||
| } | |||||
| $inline = $this->loadCommentForDone($this->getCommentID()); | $inline = $this->loadCommentForDone($this->getCommentID()); | ||||
| $is_draft_state = false; | $is_draft_state = false; | ||||
| $is_checked = false; | $is_checked = false; | ||||
| switch ($inline->getFixedState()) { | switch ($inline->getFixedState()) { | ||||
| case PhabricatorInlineComment::STATE_DRAFT: | case PhabricatorInlineComment::STATE_DRAFT: | ||||
| $next_state = PhabricatorInlineComment::STATE_UNDONE; | $next_state = PhabricatorInlineComment::STATE_UNDONE; | ||||
| break; | break; | ||||
| Show All 19 Lines | switch ($op) { | ||||
| ->setContent( | ->setContent( | ||||
| array( | array( | ||||
| 'isChecked' => $is_checked, | 'isChecked' => $is_checked, | ||||
| 'draftState' => $is_draft_state, | 'draftState' => $is_draft_state, | ||||
| )); | )); | ||||
| case 'delete': | case 'delete': | ||||
| case 'undelete': | case 'undelete': | ||||
| case 'refdelete': | case 'refdelete': | ||||
| if (!$request->validateCSRF()) { | |||||
| return new Aphront404Response(); | |||||
| } | |||||
| // NOTE: For normal deletes, we just process the delete immediately | // NOTE: For normal deletes, we just process the delete immediately | ||||
| // and show an "Undo" action. For deletes by reference from the | // and show an "Undo" action. For deletes by reference from the | ||||
| // preview ("refdelete"), we prompt first (because the "Undo" may | // preview ("refdelete"), we prompt first (because the "Undo" may | ||||
| // not draw, or may not be easy to locate). | // not draw, or may not be easy to locate). | ||||
| if ($op == 'refdelete') { | if ($op == 'refdelete') { | ||||
| if (!$request->isFormPost()) { | if (!$request->isFormPost()) { | ||||
| return $this->newDialog() | return $this->newDialog() | ||||
| Show All 15 Lines | switch ($op) { | ||||
| } else { | } else { | ||||
| $inline->setIsDeleted(0); | $inline->setIsDeleted(0); | ||||
| } | } | ||||
| $this->saveComment($inline); | $this->saveComment($inline); | ||||
| return $this->buildEmptyResponse(); | return $this->buildEmptyResponse(); | ||||
| case 'edit': | case 'edit': | ||||
| case 'save': | |||||
| $inline = $this->loadCommentByIDForEdit($this->getCommentID()); | $inline = $this->loadCommentByIDForEdit($this->getCommentID()); | ||||
| $text = $this->getCommentText(); | if ($op === 'save') { | ||||
| $this->updateCommentContentState($inline); | |||||
| if ($request->isFormPost()) { | $inline->setIsEditing(false); | ||||
| if (strlen($text)) { | |||||
| $inline | |||||
| ->setContent($text) | |||||
| ->setIsEditing(false); | |||||
| if (!$inline->isVoidComment($viewer)) { | |||||
| $this->saveComment($inline); | $this->saveComment($inline); | ||||
| return $this->buildRenderedCommentResponse( | return $this->buildRenderedCommentResponse( | ||||
| $inline, | $inline, | ||||
| $this->getIsOnRight()); | $this->getIsOnRight()); | ||||
| } else { | } else { | ||||
| $inline->setIsDeleted(1); | $inline->setIsDeleted(1); | ||||
| $this->saveComment($inline); | $this->saveComment($inline); | ||||
| return $this->buildEmptyResponse(); | return $this->buildEmptyResponse(); | ||||
| } | } | ||||
| } else { | } else { | ||||
| // NOTE: At time of writing, the "editing" state of inlines is | // NOTE: At time of writing, the "editing" state of inlines is | ||||
| // preserved by simluating a click on "Edit" when the inline loads. | // preserved by simulating a click on "Edit" when the inline loads. | ||||
| // In this case, we don't want to "saveComment()", because it | // In this case, we don't want to "saveComment()", because it | ||||
| // recalculates object drafts and purges versioned drafts. | // recalculates object drafts and purges versioned drafts. | ||||
| // The recalculation is merely unnecessary (state doesn't change) | // The recalculation is merely unnecessary (state doesn't change) | ||||
| // but purging drafts means that loading a page and then closing it | // but purging drafts means that loading a page and then closing it | ||||
| // discards your drafts. | // discards your drafts. | ||||
| // To avoid the purge, only invoke "saveComment()" if we actually | // To avoid the purge, only invoke "saveComment()" if we actually | ||||
| // have changes to apply. | // have changes to apply. | ||||
| $is_dirty = false; | $is_dirty = false; | ||||
| if (!$inline->getIsEditing()) { | if (!$inline->getIsEditing()) { | ||||
| $inline->setIsEditing(true); | $inline->setIsEditing(true); | ||||
| $is_dirty = true; | $is_dirty = true; | ||||
| } | } | ||||
| if (strlen($text)) { | if ($this->hasContentState()) { | ||||
| $inline->setContent($text); | $this->updateCommentContentState($inline); | ||||
| $is_dirty = true; | $is_dirty = true; | ||||
| } else { | } else { | ||||
| PhabricatorInlineComment::loadAndAttachVersionedDrafts( | PhabricatorInlineComment::loadAndAttachVersionedDrafts( | ||||
| $viewer, | $viewer, | ||||
| array($inline)); | array($inline)); | ||||
| } | } | ||||
| if ($is_dirty) { | if ($is_dirty) { | ||||
| Show All 10 Lines | switch ($op) { | ||||
| case 'cancel': | case 'cancel': | ||||
| $inline = $this->loadCommentByIDForEdit($this->getCommentID()); | $inline = $this->loadCommentByIDForEdit($this->getCommentID()); | ||||
| $inline->setIsEditing(false); | $inline->setIsEditing(false); | ||||
| // If the user uses "Undo" to get into an edited state ("AB"), then | // If the user uses "Undo" to get into an edited state ("AB"), then | ||||
| // clicks cancel to return to the previous state ("A"), we also want | // clicks cancel to return to the previous state ("A"), we also want | ||||
| // to set the stored state back to "A". | // to set the stored state back to "A". | ||||
| $text = $this->getCommentText(); | $this->updateCommentContentState($inline); | ||||
| if (strlen($text)) { | |||||
| $inline->setContent($text); | |||||
| } | |||||
| $content = $inline->getContent(); | if ($inline->isVoidComment($viewer)) { | ||||
| if (!strlen($content)) { | |||||
| $inline->setIsDeleted(1); | $inline->setIsDeleted(1); | ||||
| } | } | ||||
| $this->saveComment($inline); | $this->saveComment($inline); | ||||
| return $this->buildEmptyResponse(); | return $this->buildEmptyResponse(); | ||||
| case 'draft': | case 'draft': | ||||
| $inline = $this->loadCommentByIDForEdit($this->getCommentID()); | $inline = $this->loadCommentByIDForEdit($this->getCommentID()); | ||||
| $versioned_draft = PhabricatorVersionedDraft::loadOrCreateDraft( | $versioned_draft = PhabricatorVersionedDraft::loadOrCreateDraft( | ||||
| $inline->getPHID(), | $inline->getPHID(), | ||||
| $viewer->getPHID(), | $viewer->getPHID(), | ||||
| $inline->getID()); | $inline->getID()); | ||||
| $text = $this->getCommentText(); | $map = $this->getContentState(); | ||||
| foreach ($map as $key => $value) { | |||||
| $versioned_draft | $versioned_draft->setProperty($key, $value); | ||||
| ->setProperty('inline.text', $text) | } | ||||
| ->save(); | $versioned_draft->save(); | ||||
| // We have to synchronize the draft engine after saving a versioned | // We have to synchronize the draft engine after saving a versioned | ||||
| // draft, because taking an inline comment from "no text, no draft" | // draft, because taking an inline comment from "no text, no draft" | ||||
| // to "no text, text in a draft" marks the container object as having | // to "no text, text in a draft" marks the container object as having | ||||
| // a draft. | // a draft. | ||||
| $draft_engine = $this->newDraftEngine(); | $draft_engine = $this->newDraftEngine(); | ||||
| if ($draft_engine) { | if ($draft_engine) { | ||||
| $draft_engine->synchronize(); | $draft_engine->synchronize(); | ||||
| Show All 14 Lines | switch ($op) { | ||||
| $length = $this->getLineLength(); | $length = $this->getLineLength(); | ||||
| $inline = $this->createComment() | $inline = $this->createComment() | ||||
| ->setChangesetID($this->getChangesetID()) | ->setChangesetID($this->getChangesetID()) | ||||
| ->setAuthorPHID($viewer->getPHID()) | ->setAuthorPHID($viewer->getPHID()) | ||||
| ->setIsNewFile($is_new) | ->setIsNewFile($is_new) | ||||
| ->setLineNumber($number) | ->setLineNumber($number) | ||||
| ->setLineLength($length) | ->setLineLength($length) | ||||
| ->setContent((string)$this->getCommentText()) | |||||
| ->setReplyToCommentPHID($this->getReplyToCommentPHID()) | ->setReplyToCommentPHID($this->getReplyToCommentPHID()) | ||||
| ->setIsEditing(true) | ->setIsEditing(true) | ||||
| ->setStartOffset($request->getInt('startOffset')) | ->setStartOffset($request->getInt('startOffset')) | ||||
| ->setEndOffset($request->getInt('endOffset')); | ->setEndOffset($request->getInt('endOffset')) | ||||
| ->setContent(''); | |||||
| $document_engine_key = $request->getStr('documentEngineKey'); | $document_engine_key = $request->getStr('documentEngineKey'); | ||||
| if ($document_engine_key !== null) { | if ($document_engine_key !== null) { | ||||
| $inline->setDocumentEngineKey($document_engine_key); | $inline->setDocumentEngineKey($document_engine_key); | ||||
| } | } | ||||
| // If you own this object, mark your own inlines as "Done" by default. | // If you own this object, mark your own inlines as "Done" by default. | ||||
| $owner_phid = $this->loadObjectOwnerPHID($inline); | $owner_phid = $this->loadObjectOwnerPHID($inline); | ||||
| if ($owner_phid) { | if ($owner_phid) { | ||||
| if ($viewer->getPHID() == $owner_phid) { | if ($viewer->getPHID() == $owner_phid) { | ||||
| $fixed_state = PhabricatorInlineComment::STATE_DRAFT; | $fixed_state = PhabricatorInlineComment::STATE_DRAFT; | ||||
| $inline->setFixedState($fixed_state); | $inline->setFixedState($fixed_state); | ||||
| } | } | ||||
| } | } | ||||
| if ($this->hasContentState()) { | |||||
| $this->updateCommentContentState($inline); | |||||
| } | |||||
| $this->saveComment($inline); | $this->saveComment($inline); | ||||
| $edit_dialog = $this->buildEditDialog($inline); | $edit_dialog = $this->buildEditDialog($inline); | ||||
| if ($this->getOperation() == 'reply') { | if ($this->getOperation() == 'reply') { | ||||
| $edit_dialog->setTitle(pht('Reply to Inline Comment')); | $edit_dialog->setTitle(pht('Reply to Inline Comment')); | ||||
| } else { | } else { | ||||
| $edit_dialog->setTitle(pht('New Inline Comment')); | $edit_dialog->setTitle(pht('New Inline Comment')); | ||||
| Show All 11 Lines | private function readRequestParameters() { | ||||
| // NOTE: This isn't necessarily a DifferentialChangeset ID, just an | // NOTE: This isn't necessarily a DifferentialChangeset ID, just an | ||||
| // application identifier for the changeset. In Diffusion, it's a Path ID. | // application identifier for the changeset. In Diffusion, it's a Path ID. | ||||
| $this->changesetID = $request->getInt('changesetID'); | $this->changesetID = $request->getInt('changesetID'); | ||||
| $this->isNewFile = (int)$request->getBool('is_new'); | $this->isNewFile = (int)$request->getBool('is_new'); | ||||
| $this->isOnRight = $request->getBool('on_right'); | $this->isOnRight = $request->getBool('on_right'); | ||||
| $this->lineNumber = $request->getInt('number'); | $this->lineNumber = $request->getInt('number'); | ||||
| $this->lineLength = $request->getInt('length'); | $this->lineLength = $request->getInt('length'); | ||||
| $this->commentText = $request->getStr('text'); | |||||
| $this->commentID = $request->getInt('id'); | $this->commentID = $request->getInt('id'); | ||||
| $this->operation = $request->getStr('op'); | $this->operation = $request->getStr('op'); | ||||
| $this->renderer = $request->getStr('renderer'); | $this->renderer = $request->getStr('renderer'); | ||||
| $this->replyToCommentPHID = $request->getStr('replyToCommentPHID'); | $this->replyToCommentPHID = $request->getStr('replyToCommentPHID'); | ||||
| if ($this->getReplyToCommentPHID()) { | if ($this->getReplyToCommentPHID()) { | ||||
| $reply_phid = $this->getReplyToCommentPHID(); | $reply_phid = $this->getReplyToCommentPHID(); | ||||
| $reply_comment = $this->loadCommentByPHID($reply_phid); | $reply_comment = $this->loadCommentByPHID($reply_phid); | ||||
| ▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | private function loadCommentByQuery( | ||||
| if ($inline) { | if ($inline) { | ||||
| $inline = $inline->newInlineCommentObject(); | $inline = $inline->newInlineCommentObject(); | ||||
| } | } | ||||
| return $inline; | return $inline; | ||||
| } | } | ||||
| private function hasContentState() { | |||||
| $request = $this->getRequest(); | |||||
| return (bool)$request->getBool('hasContentState'); | |||||
| } | |||||
| private function getContentState() { | |||||
| $request = $this->getRequest(); | |||||
| $comment_text = $request->getStr('text'); | |||||
| return array( | |||||
| 'inline.text' => (string)$comment_text, | |||||
| ); | |||||
| } | |||||
| private function updateCommentContentState(PhabricatorInlineComment $inline) { | |||||
| if (!$this->hasContentState()) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Attempting to update comment content state, but request has no '. | |||||
| 'content state.')); | |||||
| } | |||||
| $state = $this->getContentState(); | |||||
| $text = $state['inline.text']; | |||||
| $inline->setContent($text); | |||||
| } | |||||
| private function saveComment(PhabricatorInlineComment $inline) { | private function saveComment(PhabricatorInlineComment $inline) { | ||||
| $viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
| $draft_engine = $this->newDraftEngine(); | $draft_engine = $this->newDraftEngine(); | ||||
| $inline->openTransaction(); | $inline->openTransaction(); | ||||
| $inline->save(); | $inline->save(); | ||||
| PhabricatorVersionedDraft::purgeDrafts( | PhabricatorVersionedDraft::purgeDrafts( | ||||
| Show All 24 Lines | |||||