@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make adding an answer to a Ponder question a QuestionTransaction operation

Summary: Ref T3578. This is currently handled in a weird way in the Answer transaction. Instead, make it a Question transaction so, e.g., viewing Question transaction history shows who added answers and when.

Test Plan: Added answers to questions in Ponder.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3578

Differential Revision: https://secure.phabricator.com/D6603

+117 -9
+19 -9
src/applications/ponder/controller/PonderAnswerSaveController.php
··· 14 14 $question = id(new PonderQuestionQuery()) 15 15 ->setViewer($viewer) 16 16 ->withIDs(array($question_id)) 17 + ->needAnswers(true) 17 18 ->executeOne(); 18 19 if (!$question) { 19 20 return new Aphront404Response(); ··· 39 40 'ip' => $request->getRemoteAddr(), 40 41 )); 41 42 42 - $res = new PonderAnswer(); 43 - $res 43 + $res = id(new PonderAnswer()) 44 + ->setAuthorPHID($viewer->getPHID()) 45 + ->setQuestionID($question->getID()) 44 46 ->setContent($answer) 45 - ->setAuthorPHID($viewer->getPHID()) 46 47 ->setVoteCount(0) 47 - ->setQuestionID($question_id) 48 48 ->setContentSource($content_source); 49 49 50 - id(new PonderAnswerEditor()) 50 + $xactions = array(); 51 + $xactions[] = id(new PonderQuestionTransaction()) 52 + ->setTransactionType(PonderQuestionTransaction::TYPE_ANSWERS) 53 + ->setNewValue( 54 + array( 55 + '+' => array( 56 + array('answer' => $res), 57 + ), 58 + )); 59 + 60 + $editor = id(new PonderQuestionEditor()) 51 61 ->setActor($viewer) 52 - ->setQuestion($question) 53 - ->setAnswer($res) 54 - ->saveAnswer(); 62 + ->setContentSourceFromRequest($request); 63 + 64 + $editor->applyTransactions($question, $xactions); 55 65 56 66 return id(new AphrontRedirectResponse())->setURI( 57 - id(new PhutilURI('/Q'. $question->getID()))); 67 + id(new PhutilURI('/Q'.$question->getID()))); 58 68 } 59 69 }
+68
src/applications/ponder/editor/PonderQuestionEditor.php
··· 3 3 final class PonderQuestionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + protected function shouldApplyInitialEffects( 7 + PhabricatorLiskDAO $object, 8 + array $xactions) { 9 + 10 + foreach ($xactions as $xaction) { 11 + switch ($xaction->getTransactionType()) { 12 + case PonderQuestionTransaction::TYPE_ANSWERS: 13 + return true; 14 + } 15 + } 16 + 17 + return false; 18 + } 19 + 20 + protected function applyInitialEffects( 21 + PhabricatorLiskDAO $object, 22 + array $xactions) { 23 + 24 + foreach ($xactions as $xaction) { 25 + switch ($xaction->getTransactionType()) { 26 + case PonderQuestionTransaction::TYPE_ANSWERS: 27 + $new_value = $xaction->getNewValue(); 28 + $new = idx($new_value, '+', array()); 29 + foreach ($new as $new_answer) { 30 + $answer = idx($new_answer, 'answer'); 31 + if (!$answer) { 32 + continue; 33 + } 34 + $answer->save(); 35 + } 36 + break; 37 + } 38 + } 39 + } 40 + 6 41 public function getTransactionTypes() { 7 42 $types = parent::getTransactionTypes(); 8 43 9 44 $types[] = PhabricatorTransactions::TYPE_COMMENT; 10 45 $types[] = PonderQuestionTransaction::TYPE_TITLE; 11 46 $types[] = PonderQuestionTransaction::TYPE_CONTENT; 47 + $types[] = PonderQuestionTransaction::TYPE_ANSWERS; 12 48 13 49 return $types; 14 50 } 51 + 15 52 protected function getCustomTransactionOldValue( 16 53 PhabricatorLiskDAO $object, 17 54 PhabricatorApplicationTransaction $xaction) { ··· 21 58 return $object->getTitle(); 22 59 case PonderQuestionTransaction::TYPE_CONTENT: 23 60 return $object->getContent(); 61 + case PonderQuestionTransaction::TYPE_ANSWERS: 62 + return mpull($object->getAnswers(), 'getPHID'); 24 63 } 25 64 } 26 65 ··· 32 71 case PonderQuestionTransaction::TYPE_TITLE: 33 72 case PonderQuestionTransaction::TYPE_CONTENT: 34 73 return $xaction->getNewValue(); 74 + case PonderQuestionTransaction::TYPE_ANSWERS: 75 + $raw_new_value = $xaction->getNewValue(); 76 + $new_value = array(); 77 + foreach ($raw_new_value as $key => $answers) { 78 + $phids = array(); 79 + foreach ($answers as $answer) { 80 + $obj = idx($answer, 'answer'); 81 + if (!$answer) { 82 + continue; 83 + } 84 + $phids[] = $obj->getPHID(); 85 + } 86 + $new_value[$key] = $phids; 87 + } 88 + $xaction->setNewValue($new_value); 89 + return $this->getPHIDTransactionNewValue($xaction); 35 90 } 36 91 } 37 92 ··· 45 100 break; 46 101 case PonderQuestionTransaction::TYPE_CONTENT: 47 102 $object->setContent($xaction->getNewValue()); 103 + break; 104 + case PonderQuestionTransaction::TYPE_ANSWERS: 105 + $old = $xaction->getOldValue(); 106 + $new = $xaction->getNewValue(); 107 + 108 + $add = array_diff_key($new, $old); 109 + $rem = array_diff_key($old, $new); 110 + 111 + $count = $object->getAnswerCount(); 112 + $count += count($add); 113 + $count -= count($rem); 114 + 115 + $object->setAnswerCount($count); 48 116 break; 49 117 } 50 118 }
+23
src/applications/ponder/query/PonderQuestionQuery.php
··· 17 17 const STATUS_OPEN = 'status-open'; 18 18 const STATUS_CLOSED = 'status-closed'; 19 19 20 + private $needAnswers; 21 + 20 22 public function withIDs(array $ids) { 21 23 $this->ids = $ids; 22 24 return $this; ··· 39 41 40 42 public function withAnswererPHIDs(array $phids) { 41 43 $this->answererPHIDs = $phids; 44 + return $this; 45 + } 46 + 47 + public function needAnswers($need_answers) { 48 + $this->needAnswers = $need_answers; 42 49 return $this; 43 50 } 44 51 ··· 122 129 $this->buildLimitClause($conn_r)); 123 130 124 131 return $question->loadAllFromArray($data); 132 + } 133 + 134 + public function willFilterPage(array $questions) { 135 + if ($this->needAnswers) { 136 + $answers = id(new PonderAnswerQuery()) 137 + ->setViewer($this->getViewer()) 138 + ->withQuestionIDs(mpull($questions, 'getID')) 139 + ->execute(); 140 + $answers = mgroup($answers, 'getQuestionID'); 141 + 142 + foreach ($questions as $question) { 143 + $question->attachAnswers(idx($answers, $question->getID(), array())); 144 + } 145 + } 146 + 147 + return $questions; 125 148 } 126 149 127 150 private function buildJoinsClause(AphrontDatabaseConnection $conn_r) {
+6
src/applications/ponder/storage/PonderQuestion.php
··· 114 114 return $this->comments; 115 115 } 116 116 117 + public function attachAnswers(array $answers) { 118 + assert_instances_of($answers, 'PonderAnswer'); 119 + $this->answers = $answers; 120 + return $this; 121 + } 122 + 117 123 public function getAnswers() { 118 124 return $this->answers; 119 125 }
+1
src/applications/ponder/storage/PonderQuestionTransaction.php
··· 5 5 6 6 const TYPE_TITLE = 'ponder.question:question'; 7 7 const TYPE_CONTENT = 'ponder.question:content'; 8 + const TYPE_ANSWERS = 'ponder.question:answer'; 8 9 9 10 public function getApplicationName() { 10 11 return 'ponder';