From b1dfbda74113a3e347064b09b3f098158e54a379 Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Wed, 18 Sep 2013 15:15:25 -0700 Subject: [PATCH] Ponder - make feed stories and emails a bit better Summary: Also some random cleanup now and again. Note reply handler stuff is kind of bojangles bad right now. It didn't work before though either so hey. Test Plan: asked questions, answered questions, edited answers... the feed pleased my eye Reviewers: epriestley Reviewed By: epriestley CC: Korvin, aran Maniphest Tasks: T3653 Differential Revision: https://secure.phabricator.com/D7027 --- src/__phutil_library_map__.php | 10 +- .../storage/PhabricatorMacroTransaction.php | 4 +- .../storage/PhabricatorPasteTransaction.php | 4 +- .../pholio/storage/PholioTransaction.php | 4 +- .../controller/PonderAnswerEditController.php | 9 +- .../controller/PonderAnswerViewController.php | 25 ----- .../PonderQuestionViewController.php | 2 + .../ponder/editor/PonderAnswerEditor.php | 40 +++++++- .../ponder/editor/PonderEditor.php | 32 +++++++ .../ponder/editor/PonderQuestionEditor.php | 80 ++++++++++------ .../feed/PonderTransactionFeedStory.php | 14 +++ .../mail/PonderQuestionReplyHandler.php | 5 - .../ponder/phid/PonderPHIDTypeAnswer.php | 3 +- .../ponder/phid/PonderPHIDTypeQuestion.php | 3 +- .../ponder/query/PonderQuestionQuery.php | 3 +- .../ponder/storage/PonderAnswer.php | 9 +- .../storage/PonderAnswerTransaction.php | 84 +++++++++++++++-- .../ponder/storage/PonderQuestion.php | 8 +- .../storage/PonderQuestionTransaction.php | 92 +++++++++++++++++-- ...ricatorApplicationTransactionFeedStory.php | 2 +- .../PhabricatorApplicationTransaction.php | 2 +- 21 files changed, 326 insertions(+), 109 deletions(-) delete mode 100644 src/applications/ponder/controller/PonderAnswerViewController.php create mode 100644 src/applications/ponder/editor/PonderEditor.php create mode 100644 src/applications/ponder/feed/PonderTransactionFeedStory.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5928959b03..b8b0e3cb13 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1938,12 +1938,12 @@ phutil_register_library_map(array( 'PonderAnswerTransaction' => 'applications/ponder/storage/PonderAnswerTransaction.php', 'PonderAnswerTransactionComment' => 'applications/ponder/storage/PonderAnswerTransactionComment.php', 'PonderAnswerTransactionQuery' => 'applications/ponder/query/PonderAnswerTransactionQuery.php', - 'PonderAnswerViewController' => 'applications/ponder/controller/PonderAnswerViewController.php', 'PonderComment' => 'applications/ponder/storage/PonderComment.php', 'PonderCommentQuery' => 'applications/ponder/query/PonderCommentQuery.php', 'PonderConstants' => 'applications/ponder/constants/PonderConstants.php', 'PonderController' => 'applications/ponder/controller/PonderController.php', 'PonderDAO' => 'applications/ponder/storage/PonderDAO.php', + 'PonderEditor' => 'applications/ponder/editor/PonderEditor.php', 'PonderPHIDTypeAnswer' => 'applications/ponder/phid/PonderPHIDTypeAnswer.php', 'PonderPHIDTypeQuestion' => 'applications/ponder/phid/PonderPHIDTypeQuestion.php', 'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php', @@ -1964,6 +1964,7 @@ phutil_register_library_map(array( 'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php', 'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php', 'PonderSearchIndexer' => 'applications/ponder/search/PonderSearchIndexer.php', + 'PonderTransactionFeedStory' => 'applications/ponder/feed/PonderTransactionFeedStory.php', 'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php', 'PonderVotableView' => 'applications/ponder/view/PonderVotableView.php', 'PonderVote' => 'applications/ponder/constants/PonderVote.php', @@ -4149,14 +4150,13 @@ phutil_register_library_map(array( ), 'PonderAnswerCommentController' => 'PonderController', 'PonderAnswerEditController' => 'PonderController', - 'PonderAnswerEditor' => 'PhabricatorApplicationTransactionEditor', + 'PonderAnswerEditor' => 'PonderEditor', 'PonderAnswerHistoryController' => 'PonderController', 'PonderAnswerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PonderAnswerSaveController' => 'PonderController', 'PonderAnswerTransaction' => 'PhabricatorApplicationTransaction', 'PonderAnswerTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderAnswerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', - 'PonderAnswerViewController' => 'PonderController', 'PonderComment' => array( 0 => 'PonderDAO', @@ -4165,6 +4165,7 @@ phutil_register_library_map(array( 'PonderCommentQuery' => 'PhabricatorQuery', 'PonderController' => 'PhabricatorController', 'PonderDAO' => 'PhabricatorLiskDAO', + 'PonderEditor' => 'PhabricatorApplicationTransactionEditor', 'PonderPHIDTypeAnswer' => 'PhabricatorPHIDType', 'PonderPHIDTypeQuestion' => 'PhabricatorPHIDType', 'PonderQuestion' => @@ -4178,7 +4179,7 @@ phutil_register_library_map(array( ), 'PonderQuestionCommentController' => 'PonderController', 'PonderQuestionEditController' => 'PonderController', - 'PonderQuestionEditor' => 'PhabricatorApplicationTransactionEditor', + 'PonderQuestionEditor' => 'PonderEditor', 'PonderQuestionHistoryController' => 'PonderController', 'PonderQuestionListController' => array( @@ -4197,6 +4198,7 @@ phutil_register_library_map(array( 'PonderQuestionViewController' => 'PonderController', 'PonderRemarkupRule' => 'PhabricatorRemarkupRuleObject', 'PonderSearchIndexer' => 'PhabricatorSearchDocumentIndexer', + 'PonderTransactionFeedStory' => 'PhabricatorApplicationTransactionFeedStory', 'PonderVotableView' => 'AphrontView', 'PonderVote' => 'PonderConstants', 'PonderVoteEditor' => 'PhabricatorEditor', diff --git a/src/applications/macro/storage/PhabricatorMacroTransaction.php b/src/applications/macro/storage/PhabricatorMacroTransaction.php index ab97055271..04e8834eba 100644 --- a/src/applications/macro/storage/PhabricatorMacroTransaction.php +++ b/src/applications/macro/storage/PhabricatorMacroTransaction.php @@ -92,7 +92,7 @@ final class PhabricatorMacroTransaction return parent::getTitle(); } - public function getTitleForFeed() { + public function getTitleForFeed(PhabricatorFeedStory $story) { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); @@ -133,7 +133,7 @@ final class PhabricatorMacroTransaction } } - return parent::getTitleForFeed(); + return parent::getTitleForFeed($story); } public function getActionName() { diff --git a/src/applications/paste/storage/PhabricatorPasteTransaction.php b/src/applications/paste/storage/PhabricatorPasteTransaction.php index 05bcb00151..96e5e5827f 100644 --- a/src/applications/paste/storage/PhabricatorPasteTransaction.php +++ b/src/applications/paste/storage/PhabricatorPasteTransaction.php @@ -88,7 +88,7 @@ final class PhabricatorPasteTransaction return parent::getTitle(); } - public function getTitleForFeed() { + public function getTitleForFeed(PhabricatorFeedStory $story) { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); @@ -117,7 +117,7 @@ final class PhabricatorPasteTransaction break; } - return parent::getTitleForFeed(); + return parent::getTitleForFeed($story); } public function getColor() { diff --git a/src/applications/pholio/storage/PholioTransaction.php b/src/applications/pholio/storage/PholioTransaction.php index 9ddb4c4235..af9c0502a8 100644 --- a/src/applications/pholio/storage/PholioTransaction.php +++ b/src/applications/pholio/storage/PholioTransaction.php @@ -180,7 +180,7 @@ final class PholioTransaction extends PhabricatorApplicationTransaction { return parent::getTitle(); } - public function getTitleForFeed() { + public function getTitleForFeed(PhabricatorFeedStory $story) { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); @@ -243,7 +243,7 @@ final class PholioTransaction extends PhabricatorApplicationTransaction { break; } - return parent::getTitleForFeed(); + return parent::getTitleForFeed($story); } public function getBodyForFeed(PhabricatorFeedStory $story) { diff --git a/src/applications/ponder/controller/PonderAnswerEditController.php b/src/applications/ponder/controller/PonderAnswerEditController.php index aa684801f4..cb7dafef65 100644 --- a/src/applications/ponder/controller/PonderAnswerEditController.php +++ b/src/applications/ponder/controller/PonderAnswerEditController.php @@ -31,9 +31,8 @@ final class PonderAnswerEditController extends PonderController { $question = $answer->getQuestion(); $qid = $question->getID(); - $aid = $answer->getID(); - $question_uri = "/Q{$qid}#A{$aid}"; + $answer_uri = $answer->getURI(); $errors = array(); if ($request->isFormPost()) { @@ -58,7 +57,7 @@ final class PonderAnswerEditController extends PonderController { $editor->applyTransactions($answer, $xactions); return id(new AphrontRedirectResponse()) - ->setURI($question_uri); + ->setURI($answer_uri); } } @@ -84,13 +83,13 @@ final class PonderAnswerEditController extends PonderController { ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Update Answer')) - ->addCancelButton($question_uri)); + ->addCancelButton($answer_uri)); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName("Q{$qid}") - ->setHref($question_uri)); + ->setHref($answer_uri)); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName(pht('Edit Answer'))); diff --git a/src/applications/ponder/controller/PonderAnswerViewController.php b/src/applications/ponder/controller/PonderAnswerViewController.php deleted file mode 100644 index 23183fbada..0000000000 --- a/src/applications/ponder/controller/PonderAnswerViewController.php +++ /dev/null @@ -1,25 +0,0 @@ -answerID = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $answer = id(new PonderAnswer())->load($this->answerID); - - if (!$answer) { - return new Aphront404Response(); - } - - $question_id = $answer->getQuestionID(); - - return id(new AphrontRedirectResponse()) - ->setURI('/Q'.$question_id . '#A' . $answer->getID()); - } - -} diff --git a/src/applications/ponder/controller/PonderQuestionViewController.php b/src/applications/ponder/controller/PonderQuestionViewController.php index fb5179695a..69c3f12c05 100644 --- a/src/applications/ponder/controller/PonderQuestionViewController.php +++ b/src/applications/ponder/controller/PonderQuestionViewController.php @@ -251,6 +251,8 @@ final class PonderQuestionViewController extends PonderController { $out[] = phutil_tag('br'); $out[] = phutil_tag('br'); + $out[] = id(new PhabricatorAnchorView()) + ->setAnchorName("A$id"); $out[] = id(new PHUIHeaderView()) ->setHeader($this->getHandle($author_phid)->getFullName()) ->setImage($this->getHandle($author_phid)->getImageURI()); diff --git a/src/applications/ponder/editor/PonderAnswerEditor.php b/src/applications/ponder/editor/PonderAnswerEditor.php index 6daeca17c6..cf774d94a1 100644 --- a/src/applications/ponder/editor/PonderAnswerEditor.php +++ b/src/applications/ponder/editor/PonderAnswerEditor.php @@ -1,7 +1,6 @@ getAuthorPHID()); + protected function buildReplyHandler(PhabricatorLiskDAO $object) { + $question = $object->getQuestion(); + return id(new PonderQuestionReplyHandler()) + ->setMailReceiver($question); + } + + protected function buildMailTemplate(PhabricatorLiskDAO $object) { + $question = $object->getQuestion(); + return parent::buildMailTemplate($question); } + protected function buildMailBody( + PhabricatorLiskDAO $object, + array $xactions) { + + $body = parent::buildMailBody($object, $xactions); + + // If the user just gave the answer, add the answer text. + foreach ($xactions as $xaction) { + $type = $xaction->getTransactionType(); + $new = $xaction->getNewValue(); + if ($type == PonderAnswerTransaction::TYPE_CONTENT) { + $body->addRawSection($new); + } + } + + $body->addTextSection( + pht('ANSWER DETAIL'), + PhabricatorEnv::getProductionURI($object->getURI())); + + return $body; + } + } diff --git a/src/applications/ponder/editor/PonderEditor.php b/src/applications/ponder/editor/PonderEditor.php new file mode 100644 index 0000000000..94f75fd245 --- /dev/null +++ b/src/applications/ponder/editor/PonderEditor.php @@ -0,0 +1,32 @@ +getID(); + $title = $object->getTitle(); + $original_title = $object->getOriginalTitle(); + + return id(new PhabricatorMetaMTAMail()) + ->setSubject("Q{$id}: {$title}") + ->addHeader('Thread-Topic', "Q{$id}: {$original_title}"); + } + + + protected function getMailTo(PhabricatorLiskDAO $object) { + return array( + $object->getAuthorPHID(), + $this->requireActor()->getPHID(), + ); + } + + protected function getMailSubjectPrefix() { + return '[Ponder]'; + } + +} diff --git a/src/applications/ponder/editor/PonderQuestionEditor.php b/src/applications/ponder/editor/PonderQuestionEditor.php index 978c29cc11..653dc2ed75 100644 --- a/src/applications/ponder/editor/PonderQuestionEditor.php +++ b/src/applications/ponder/editor/PonderQuestionEditor.php @@ -1,7 +1,26 @@ answer = $answer; + return $this; + } + private function getAnswer() { + return $this->answer; + } protected function shouldApplyInitialEffects( PhabricatorLiskDAO $object, @@ -32,6 +51,7 @@ final class PonderQuestionEditor continue; } $answer->save(); + $this->setAnswer($answer); } break; } @@ -145,14 +165,27 @@ final class PonderQuestionEditor return parent::mergeTransactions($u, $v); } - protected function supportsFeed() { - return true; - } - protected function supportsSearch() { return true; } + protected function getFeedStoryType() { + return 'PonderTransactionFeedStory'; + } + + protected function getFeedStoryData( + PhabricatorLiskDAO $object, + array $xactions) { + + $data = parent::getFeedStoryData($object, $xactions); + $answer = $this->getAnswer(); + if ($answer) { + $data['answerPHID'] = $answer->getPHID(); + } + + return $data; + } + protected function shouldImplyCC( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { @@ -176,50 +209,39 @@ final class PonderQuestionEditor ->setMailReceiver($object); } - protected function buildMailTemplate(PhabricatorLiskDAO $object) { - $id = $object->getID(); - $title = $object->getTitle(); - $original_title = $object->getOriginalTitle(); - - return id(new PhabricatorMetaMTAMail()) - ->setSubject("Q{$id}: {$title}") - ->addHeader('Thread-Topic', "Q{$id}: {$original_title}"); - } - - protected function getMailTo(PhabricatorLiskDAO $object) { - return array( - $object->getAuthorPHID(), - $this->requireActor()->getPHID(), - ); - } - protected function buildMailBody( PhabricatorLiskDAO $object, array $xactions) { $body = parent::buildMailBody($object, $xactions); - // If the user just asked the question, add the question text. + $header = pht('QUESTION DETAIL'); + $uri = '/Q'.$object->getID(); foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); + // If the user just asked the question, add the question text. if ($type == PonderQuestionTransaction::TYPE_CONTENT) { if ($old === null) { $body->addRawSection($new); } } + // If the user gave an answer, add the answer text. Also update + // the header and uri to be more answer-specific. + if ($type == PonderQuestionTransaction::TYPE_ANSWERS) { + $answer = $this->getAnswer(); + $body->addRawSection($answer->getContent()); + $header = pht('ANSWER DETAIL'); + $uri = $answer->getURI(); + } } $body->addTextSection( - pht('QUESTION DETAIL'), - PhabricatorEnv::getProductionURI('/Q'.$object->getID())); + $header, + PhabricatorEnv::getProductionURI($uri)); return $body; } - protected function getMailSubjectPrefix() { - return '[Ponder]'; - } - } diff --git a/src/applications/ponder/feed/PonderTransactionFeedStory.php b/src/applications/ponder/feed/PonderTransactionFeedStory.php new file mode 100644 index 0000000000..354170af51 --- /dev/null +++ b/src/applications/ponder/feed/PonderTransactionFeedStory.php @@ -0,0 +1,14 @@ +getValue('answerPHID'); + if ($answer_phid) { + $phids[] = $answer_phid; + } + return $phids; + } +} diff --git a/src/applications/ponder/mail/PonderQuestionReplyHandler.php b/src/applications/ponder/mail/PonderQuestionReplyHandler.php index 3892195c07..d788996110 100644 --- a/src/applications/ponder/mail/PonderQuestionReplyHandler.php +++ b/src/applications/ponder/mail/PonderQuestionReplyHandler.php @@ -17,11 +17,6 @@ final class PonderQuestionReplyHandler extends PhabricatorMailReplyHandler { return $this->getDefaultPublicReplyHandlerEmailAddress('Q'); } - public function getReplyHandlerDomain() { - return PhabricatorEnv::getEnvConfig( - 'metamta.maniphest.reply-handler-domain'); - } - public function getReplyHandlerInstructions() { return null; } diff --git a/src/applications/ponder/phid/PonderPHIDTypeAnswer.php b/src/applications/ponder/phid/PonderPHIDTypeAnswer.php index b6d10c2d7a..ebe9c40fb6 100644 --- a/src/applications/ponder/phid/PonderPHIDTypeAnswer.php +++ b/src/applications/ponder/phid/PonderPHIDTypeAnswer.php @@ -36,10 +36,9 @@ final class PonderPHIDTypeAnswer extends PhabricatorPHIDType { $answer = $objects[$phid]; $id = $answer->getID(); - $qid = $answer->getQuestionID(); $handle->setName("Answer {$id}"); - $handle->setURI("/Q{$qid}#A{$id}"); + $handle->setURI($answer->getURI()); } } diff --git a/src/applications/ponder/phid/PonderPHIDTypeQuestion.php b/src/applications/ponder/phid/PonderPHIDTypeQuestion.php index 32a81a5d28..23f59095a7 100644 --- a/src/applications/ponder/phid/PonderPHIDTypeQuestion.php +++ b/src/applications/ponder/phid/PonderPHIDTypeQuestion.php @@ -36,11 +36,10 @@ final class PonderPHIDTypeQuestion extends PhabricatorPHIDType { $question = $objects[$phid]; $id = $question->getID(); - $title = $question->getTitle(); $handle->setName("Q{$id}"); $handle->setURI("/Q{$id}"); - $handle->setFullName("Q{$id}: {$title}"); + $handle->setFullName($question->getFullTitle()); } } diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php index 3aae8cbb65..e297fe06bb 100644 --- a/src/applications/ponder/query/PonderQuestionQuery.php +++ b/src/applications/ponder/query/PonderQuestionQuery.php @@ -151,7 +151,8 @@ final class PonderQuestionQuery $answers = mgroup($answers, 'getQuestionID'); foreach ($questions as $question) { - $question->attachAnswers(idx($answers, $question->getID(), array())); + $question_answers = idx($answers, $question->getID(), array()); + $question->attachAnswers(mpull($question_answers, null, 'getPHID')); } } diff --git a/src/applications/ponder/storage/PonderAnswer.php b/src/applications/ponder/storage/PonderAnswer.php index c96e71b701..edaa0f4b8e 100644 --- a/src/applications/ponder/storage/PonderAnswer.php +++ b/src/applications/ponder/storage/PonderAnswer.php @@ -23,11 +23,6 @@ final class PonderAnswer extends PonderDAO private $userVotes = array(); - // TODO: Get rid of this method. - public function setQuestion($question) { - return $this->attachQuestion($question); - } - public function attachQuestion(PonderQuestion $question = null) { $this->question = $question; return $this; @@ -37,6 +32,10 @@ final class PonderAnswer extends PonderDAO return $this->assertAttached($this->question); } + public function getURI() { + return '/Q'.$this->getQuestionID().'#A'.$this->getID(); + } + public function setUserVote($vote) { $this->vote = $vote['data']; if (!$this->vote) { diff --git a/src/applications/ponder/storage/PonderAnswerTransaction.php b/src/applications/ponder/storage/PonderAnswerTransaction.php index d8a2ff4fd0..aaffe9102f 100644 --- a/src/applications/ponder/storage/PonderAnswerTransaction.php +++ b/src/applications/ponder/storage/PonderAnswerTransaction.php @@ -21,23 +21,89 @@ final class PonderAnswerTransaction return new PonderAnswerTransactionComment(); } - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); + public function getRequiredHandlePHIDs() { + $phids = parent::getRequiredHandlePHIDs(); + + switch ($this->getTransactionType()) { + case self::TYPE_CONTENT: + $phids[] = $this->getObjectPHID(); + break; + } + + return $phids; + } + + public function getTitle() { + $author_phid = $this->getAuthorPHID(); + $object_phid = $this->getObjectPHID(); switch ($this->getTransactionType()) { case self::TYPE_CONTENT: - // TODO: This is not so good. return pht( - '%s edited their answer to %s', + '%s edited %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } - return $this->getTitle(); + return parent::getTitle(); + } + + public function getTitleForFeed(PhabricatorFeedStory $story) { + $author_phid = $this->getAuthorPHID(); + $object_phid = $this->getObjectPHID(); + + switch ($this->getTransactionType()) { + case self::TYPE_CONTENT: + $answer = $story->getObject($object_phid); + $question = $answer->getQuestion(); + $answer_handle = $this->getHandle($object_phid); + $link = $answer_handle->renderLink( + $question->getFullTitle()); + + return pht( + '%s updated their answer to %s', + $this->renderHandleLink($author_phid), + $link); + } + + return parent::getTitleForFeed($story); + } + + public function getBodyForFeed(PhabricatorFeedStory $story) { + $new = $this->getNewValue(); + + $body = null; + + switch ($this->getTransactionType()) { + case self::TYPE_CONTENT: + return phutil_escape_html_newlines( + phutil_utf8_shorten($new, 128)); + break; + } + return parent::getBodyForFeed($story); + } + + + public function hasChangeDetails() { + $old = $this->getOldValue(); + + switch ($this->getTransactionType()) { + case self::TYPE_CONTENT: + return $old !== null; + } + return parent::hasChangeDetails(); + } + + public function renderChangeDetails(PhabricatorUser $viewer) { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + $view = id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setUser($viewer) + ->setOldText($old) + ->setNewText($new); + + return $view->render(); } } diff --git a/src/applications/ponder/storage/PonderQuestion.php b/src/applications/ponder/storage/PonderQuestion.php index d01d70eb4c..09864aada9 100644 --- a/src/applications/ponder/storage/PonderQuestion.php +++ b/src/applications/ponder/storage/PonderQuestion.php @@ -62,7 +62,7 @@ final class PonderQuestion extends PonderDAO $this->setComments(idx($comments, $this->getPHID(), array())); foreach ($this->answers as $answer) { - $answer->setQuestion($this); + $answer->attachQuestion($this); $answer->setComments(idx($comments, $answer->getPHID(), array())); } } @@ -208,6 +208,12 @@ final class PonderQuestion extends PonderDAO return $this->getTitle(); } + public function getFullTitle() { + $id = $this->getID(); + $title = $this->getTitle(); + return "Q{$id}: {$title}"; + } + /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/ponder/storage/PonderQuestionTransaction.php b/src/applications/ponder/storage/PonderQuestionTransaction.php index 90f509ebaa..6c1da4be8d 100644 --- a/src/applications/ponder/storage/PonderQuestionTransaction.php +++ b/src/applications/ponder/storage/PonderQuestionTransaction.php @@ -24,8 +24,22 @@ final class PonderQuestionTransaction return new PonderQuestionTransactionComment(); } + public function getRequiredHandlePHIDs() { + $phids = parent::getRequiredHandlePHIDs(); + + switch ($this->getTransactionType()) { + case self::TYPE_ANSWERS: + $phids[] = $this->getNewAnswerPHID(); + $phids[] = $this->getObjectPHID(); + break; + } + + return $phids; + } + public function getTitle() { $author_phid = $this->getAuthorPHID(); + $object_phid = $this->getObjectPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); @@ -48,10 +62,12 @@ final class PonderQuestionTransaction '%s edited the question description.', $this->renderHandleLink($author_phid)); case self::TYPE_ANSWERS: - // TODO: This could be richer. + $answer_handle = $this->getHandle($this->getNewAnswerPHID()); + $question_handle = $this->getHandle($object_phid); return pht( - '%s added an answer.', - $this->renderHandleLink($author_phid)); + '%s answered %s', + $this->renderHandleLink($author_phid), + $answer_handle->renderLink($question_handle->getFullName())); case self::TYPE_STATUS: switch ($new) { case PonderQuestionStatus::STATUS_OPEN: @@ -178,7 +194,7 @@ final class PonderQuestionTransaction return parent::shouldHide(); } - public function getTitleForFeed() { + public function getTitleForFeed(PhabricatorFeedStory $story) { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); @@ -205,11 +221,12 @@ final class PonderQuestionTransaction $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case self::TYPE_ANSWERS: - // TODO: This could be richer, too. + $answer_handle = $this->getHandle($this->getNewAnswerPHID()); + $question_handle = $this->getHandle($object_phid); return pht( '%s answered %s', $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); + $answer_handle->renderLink($question_handle->getFullName())); case self::TYPE_STATUS: switch ($new) { case PonderQuestionStatus::STATUS_OPEN: @@ -225,8 +242,67 @@ final class PonderQuestionTransaction } } - return $this->getTitle(); + return parent::getTitleForFeed($story); + } + + public function getBodyForFeed(PhabricatorFeedStory $story) { + $new = $this->getNewValue(); + $old = $this->getOldValue(); + + $body = null; + + switch ($this->getTransactionType()) { + case self::TYPE_TITLE: + if ($old === null) { + $question = $story->getObject($this->getObjectPHID()); + return phutil_escape_html_newlines( + phutil_utf8_shorten($question->getContent(), 128)); + } + case self::TYPE_ANSWERS: + $answer = $this->getNewAnswerObject($story); + if ($answer) { + return phutil_escape_html_newlines( + phutil_utf8_shorten($answer->getContent(), 128)); + } + } + return parent::getBodyForFeed($story); + } + + /** + * Currently the application only supports adding answers one at a time. + * This data is stored as a list of phids. Use this function to get the + * new phid. + */ + private function getNewAnswerPHID() { + $new = $this->getNewValue(); + $old = $this->getOldValue(); + $add = array_diff($new, $old); + + if (count($add) != 1) { + throw new Exception( + 'There should be only one answer added at a time.'); + } + + return reset($add); + } + + /** + * Generally, the answer object is only available if the transaction + * type is self::TYPE_ANSWERS. + * + * Some stories - notably ones made before D7027 - will be of the more + * generic @{class:PhabricatorApplicationTransactionFeedStory}. These + * poor stories won't have the PonderAnswer loaded, and thus will have + * less cool information. + */ + private function getNewAnswerObject(PhabricatorFeedStory $story) { + if ($story instanceof PonderTransactionFeedStory) { + $answer_phid = $this->getNewAnswerPHID(); + if ($answer_phid) { + return $story->getObject($answer_phid); + } + } + return null; } } - diff --git a/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php b/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php index a235560a8f..c8faf99a94 100644 --- a/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php +++ b/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php @@ -43,7 +43,7 @@ class PhabricatorApplicationTransactionFeedStory $xaction = $this->getObject(head($xaction_phids)); $xaction->setHandles($this->getHandles()); - $view->setTitle($xaction->getTitleForFeed()); + $view->setTitle($xaction->getTitleForFeed($this)); $body = $xaction->getBodyForFeed($this); if (nonempty($body)) { $view->appendChild($body); diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index f90d24bd94..6ace56d5ea 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -355,7 +355,7 @@ abstract class PhabricatorApplicationTransaction } } - public function getTitleForFeed() { + public function getTitleForFeed(PhabricatorFeedStory $story) { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID();