@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.

Modernize PonderQuestion with EditEngine

Summary: Just a small touch up to move this to edit engine.

Test Plan:
- Create a question
- Edit a question
- Close question
- Test NUX state

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

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

+170 -242
+2
src/__phutil_library_map__.php
··· 4606 4606 'PonderQuestionContentTransaction' => 'applications/ponder/xaction/PonderQuestionContentTransaction.php', 4607 4607 'PonderQuestionCreateMailReceiver' => 'applications/ponder/mail/PonderQuestionCreateMailReceiver.php', 4608 4608 'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php', 4609 + 'PonderQuestionEditEngine' => 'applications/ponder/editor/PonderQuestionEditEngine.php', 4609 4610 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 4610 4611 'PonderQuestionFulltextEngine' => 'applications/ponder/search/PonderQuestionFulltextEngine.php', 4611 4612 'PonderQuestionHistoryController' => 'applications/ponder/controller/PonderQuestionHistoryController.php', ··· 10194 10195 'PonderQuestionContentTransaction' => 'PonderQuestionTransactionType', 10195 10196 'PonderQuestionCreateMailReceiver' => 'PhabricatorMailReceiver', 10196 10197 'PonderQuestionEditController' => 'PonderController', 10198 + 'PonderQuestionEditEngine' => 'PhabricatorEditEngine', 10197 10199 'PonderQuestionEditor' => 'PonderEditor', 10198 10200 'PonderQuestionFulltextEngine' => 'PhabricatorFulltextEngine', 10199 10201 'PonderQuestionHistoryController' => 'PonderController',
+20 -16
src/applications/ponder/application/PhabricatorPonderApplication.php
··· 60 60 '/ponder/' => array( 61 61 '(?:query/(?P<queryKey>[^/]+)/)?' 62 62 => 'PonderQuestionListController', 63 - 'answer/add/' 64 - => 'PonderAnswerSaveController', 65 - 'answer/edit/(?P<id>\d+)/' 66 - => 'PonderAnswerEditController', 67 - 'answer/comment/(?P<id>\d+)/' 68 - => 'PonderAnswerCommentController', 69 - 'answer/history/(?P<id>\d+)/' 70 - => 'PonderAnswerHistoryController', 71 - 'question/edit/(?:(?P<id>\d+)/)?' 72 - => 'PonderQuestionEditController', 73 - 'question/create/' 74 - => 'PonderQuestionEditController', 75 - 'question/comment/(?P<id>\d+)/' 76 - => 'PonderQuestionCommentController', 77 - 'question/history/(?P<id>\d+)/' 78 - => 'PonderQuestionHistoryController', 63 + 'answer/' => array( 64 + 'add/' 65 + => 'PonderAnswerSaveController', 66 + 'edit/(?P<id>\d+)/' 67 + => 'PonderAnswerEditController', 68 + 'comment/(?P<id>\d+)/' 69 + => 'PonderAnswerCommentController', 70 + 'history/(?P<id>\d+)/' 71 + => 'PonderAnswerHistoryController', 72 + ), 73 + 'question/' => array( 74 + $this->getEditRoutePattern('edit/') 75 + => 'PonderQuestionEditController', 76 + 'create/' 77 + => 'PonderQuestionEditController', 78 + 'comment/(?P<id>\d+)/' 79 + => 'PonderQuestionCommentController', 80 + 'history/(?P<id>\d+)/' 81 + => 'PonderQuestionHistoryController', 82 + ), 79 83 'preview/' 80 84 => 'PhabricatorMarkupPreviewController', 81 85 'question/status/(?P<id>[1-9]\d*)/'
+3 -7
src/applications/ponder/controller/PonderController.php
··· 27 27 28 28 protected function buildApplicationCrumbs() { 29 29 $crumbs = parent::buildApplicationCrumbs(); 30 - $href = $this->getApplicationURI('question/create/'); 31 - $crumbs 32 - ->addAction( 33 - id(new PHUIListItemView()) 34 - ->setName(pht('Ask Question')) 35 - ->setHref($href) 36 - ->setIcon('fa-plus-square')); 30 + id(new PonderQuestionEditEngine()) 31 + ->setViewer($this->getViewer()) 32 + ->addActionToCrumbs($crumbs); 37 33 38 34 return $crumbs; 39 35 }
+5 -216
src/applications/ponder/controller/PonderQuestionEditController.php
··· 1 1 <?php 2 2 3 - final class PonderQuestionEditController extends PonderController { 4 - 3 + final class PonderQuestionEditController extends 4 + PonderController { 5 5 public function handleRequest(AphrontRequest $request) { 6 - $viewer = $request->getViewer(); 7 - $id = $request->getURIData('id'); 8 - 9 - if ($id) { 10 - $question = id(new PonderQuestionQuery()) 11 - ->setViewer($viewer) 12 - ->withIDs(array($id)) 13 - ->requireCapabilities( 14 - array( 15 - PhabricatorPolicyCapability::CAN_VIEW, 16 - PhabricatorPolicyCapability::CAN_EDIT, 17 - )) 18 - ->executeOne(); 19 - if (!$question) { 20 - return new Aphront404Response(); 21 - } 22 - $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( 23 - $question->getPHID(), 24 - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); 25 - $v_projects = array_reverse($v_projects); 26 - $is_new = false; 27 - } else { 28 - $is_new = true; 29 - $question = PonderQuestion::initializeNewQuestion($viewer); 30 - $v_projects = array(); 31 - } 32 - 33 - $v_title = $question->getTitle(); 34 - $v_content = $question->getContent(); 35 - $v_wiki = $question->getAnswerWiki(); 36 - $v_view = $question->getViewPolicy(); 37 - $v_space = $question->getSpacePHID(); 38 - $v_status = $question->getStatus(); 39 - 40 - 41 - $errors = array(); 42 - $e_title = true; 43 - if ($request->isFormPost()) { 44 - $v_title = $request->getStr('title'); 45 - $v_content = $request->getStr('content'); 46 - $v_wiki = $request->getStr('answerWiki'); 47 - $v_projects = $request->getArr('projects'); 48 - $v_view = $request->getStr('viewPolicy'); 49 - $v_space = $request->getStr('spacePHID'); 50 - $v_status = $request->getStr('status'); 51 - 52 - $len = phutil_utf8_strlen($v_title); 53 - if ($len < 1) { 54 - $errors[] = pht('Title must not be empty.'); 55 - $e_title = pht('Required'); 56 - } else if ($len > 255) { 57 - $errors[] = pht('Title is too long.'); 58 - $e_title = pht('Too Long'); 59 - } 60 - 61 - if (!$errors) { 62 - $template = id(new PonderQuestionTransaction()); 63 - $xactions = array(); 64 - 65 - $xactions[] = id(clone $template) 66 - ->setTransactionType(PonderQuestionTitleTransaction::TRANSACTIONTYPE) 67 - ->setNewValue($v_title); 68 - 69 - $xactions[] = id(clone $template) 70 - ->setTransactionType( 71 - PonderQuestionContentTransaction::TRANSACTIONTYPE) 72 - ->setNewValue($v_content); 73 - 74 - $xactions[] = id(clone $template) 75 - ->setTransactionType( 76 - PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE) 77 - ->setNewValue($v_wiki); 78 - 79 - if (!$is_new) { 80 - $xactions[] = id(clone $template) 81 - ->setTransactionType( 82 - PonderQuestionStatusTransaction::TRANSACTIONTYPE) 83 - ->setNewValue($v_status); 84 - } 85 - 86 - $xactions[] = id(clone $template) 87 - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) 88 - ->setNewValue($v_view); 89 - 90 - $xactions[] = id(clone $template) 91 - ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) 92 - ->setNewValue($v_space); 93 - 94 - $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; 95 - $xactions[] = id(new PonderQuestionTransaction()) 96 - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 97 - ->setMetadataValue('edge:type', $proj_edge_type) 98 - ->setNewValue(array('=' => array_fuse($v_projects))); 99 - 100 - $editor = id(new PonderQuestionEditor()) 101 - ->setActor($viewer) 102 - ->setContentSourceFromRequest($request) 103 - ->setContinueOnNoEffect(true); 104 - 105 - $editor->applyTransactions($question, $xactions); 106 - 107 - return id(new AphrontRedirectResponse()) 108 - ->setURI('/Q'.$question->getID()); 109 - } 110 - } 111 - 112 - $policies = id(new PhabricatorPolicyQuery()) 113 - ->setViewer($viewer) 114 - ->setObject($question) 115 - ->execute(); 116 - 117 - $form = id(new AphrontFormView()) 118 - ->setUser($viewer) 119 - ->appendChild( 120 - id(new AphrontFormTextControl()) 121 - ->setLabel(pht('Question')) 122 - ->setName('title') 123 - ->setValue($v_title) 124 - ->setError($e_title)) 125 - ->appendChild( 126 - id(new PhabricatorRemarkupControl()) 127 - ->setUser($viewer) 128 - ->setName('content') 129 - ->setID('content') 130 - ->setValue($v_content) 131 - ->setLabel(pht('Question Details')) 132 - ->setUser($viewer)) 133 - ->appendChild( 134 - id(new PhabricatorRemarkupControl()) 135 - ->setUser($viewer) 136 - ->setName('answerWiki') 137 - ->setID('answerWiki') 138 - ->setValue($v_wiki) 139 - ->setLabel(pht('Answer Summary')) 140 - ->setUser($viewer)) 141 - ->appendControl( 142 - id(new AphrontFormPolicyControl()) 143 - ->setName('viewPolicy') 144 - ->setPolicyObject($question) 145 - ->setSpacePHID($v_space) 146 - ->setPolicies($policies) 147 - ->setValue($v_view) 148 - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)); 149 - 150 - 151 - if (!$is_new) { 152 - $form->appendChild( 153 - id(new AphrontFormSelectControl()) 154 - ->setLabel(pht('Status')) 155 - ->setName('status') 156 - ->setValue($v_status) 157 - ->setOptions(PonderQuestionStatus::getQuestionStatusMap())); 158 - } 159 - 160 - $form->appendControl( 161 - id(new AphrontFormTokenizerControl()) 162 - ->setLabel(pht('Tags')) 163 - ->setName('projects') 164 - ->setValue($v_projects) 165 - ->setDatasource(new PhabricatorProjectDatasource())); 166 - 167 - $form->appendChild( 168 - id(new AphrontFormSubmitControl()) 169 - ->addCancelButton($this->getApplicationURI()) 170 - ->setValue(pht('Submit'))); 171 - 172 - $preview = id(new PHUIRemarkupPreviewPanel()) 173 - ->setHeader(pht('Question Preview')) 174 - ->setControlID('content') 175 - ->setPreviewURI($this->getApplicationURI('preview/')); 176 - 177 - $answer_preview = id(new PHUIRemarkupPreviewPanel()) 178 - ->setHeader(pht('Answer Summary Preview')) 179 - ->setControlID('answerWiki') 180 - ->setPreviewURI($this->getApplicationURI('preview/')); 181 - 182 - $crumbs = $this->buildApplicationCrumbs(); 183 - 184 - $id = $question->getID(); 185 - if ($id) { 186 - $crumbs->addTextCrumb("Q{$id}", "/Q{$id}"); 187 - $crumbs->addTextCrumb(pht('Edit')); 188 - $title = pht('Edit Question'); 189 - $header = id(new PHUIHeaderView()) 190 - ->setHeader($title) 191 - ->setHeaderIcon('fa-pencil'); 192 - } else { 193 - $crumbs->addTextCrumb(pht('Ask Question')); 194 - $title = pht('Ask New Question'); 195 - $header = id(new PHUIHeaderView()) 196 - ->setHeader($title) 197 - ->setHeaderIcon('fa-plus-square'); 198 - } 199 - $crumbs->setBorder(true); 200 - 201 - $box = id(new PHUIObjectBoxView()) 202 - ->setHeaderText(pht('Question')) 203 - ->setFormErrors($errors) 204 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 205 - ->setForm($form); 206 - 207 - $view = id(new PHUITwoColumnView()) 208 - ->setHeader($header) 209 - ->setFooter(array( 210 - $box, 211 - $preview, 212 - $answer_preview, 213 - )); 214 - 215 - return $this->newPage() 216 - ->setTitle($title) 217 - ->setCrumbs($crumbs) 218 - ->appendChild($view); 219 - 6 + return id(new PonderQuestionEditEngine()) 7 + ->setController($this) 8 + ->buildResponse(); 220 9 } 221 10 222 11 }
+8
src/applications/ponder/editor/PonderAnswerEditor.php
··· 6 6 return pht('Ponder Answers'); 7 7 } 8 8 9 + public function getCreateObjectTitle($author, $object) { 10 + return pht('%s added this answer.', $author); 11 + } 12 + 13 + public function getCreateObjectTitleForFeed($author, $object) { 14 + return pht('%s added %s.', $author, $object); 15 + } 16 + 9 17 public function getTransactionTypes() { 10 18 $types = parent::getTransactionTypes(); 11 19 $types[] = PhabricatorTransactions::TYPE_COMMENT;
+109
src/applications/ponder/editor/PonderQuestionEditEngine.php
··· 1 + <?php 2 + 3 + final class PonderQuestionEditEngine 4 + extends PhabricatorEditEngine { 5 + 6 + const ENGINECONST = 'ponder.question'; 7 + 8 + public function getEngineName() { 9 + return pht('Ponder Question'); 10 + } 11 + 12 + public function getEngineApplicationClass() { 13 + return 'PhabricatorPonderApplication'; 14 + } 15 + 16 + public function getSummaryHeader() { 17 + return pht('Configure Ponder Question Forms'); 18 + } 19 + 20 + public function getSummaryText() { 21 + return pht('Configure creation and editing forms in Ponder Questions.'); 22 + } 23 + 24 + public function isEngineConfigurable() { 25 + return false; 26 + } 27 + 28 + protected function newEditableObject() { 29 + return PonderQuestion::initializeNewQuestion($this->getViewer()); 30 + } 31 + 32 + protected function newObjectQuery() { 33 + return new PonderQuestionQuery(); 34 + } 35 + 36 + protected function getObjectCreateTitleText($object) { 37 + return pht('Create New Question'); 38 + } 39 + 40 + protected function getObjectEditTitleText($object) { 41 + return pht('Edit Question: %s', $object->getTitle()); 42 + } 43 + 44 + protected function getObjectEditShortText($object) { 45 + return $object->getTitle(); 46 + } 47 + 48 + protected function getObjectCreateShortText() { 49 + return pht('New Question'); 50 + } 51 + 52 + protected function getObjectName() { 53 + return pht('Question'); 54 + } 55 + 56 + protected function getObjectCreateCancelURI($object) { 57 + return $this->getApplication()->getApplicationURI('/'); 58 + } 59 + 60 + protected function getEditorURI() { 61 + return $this->getApplication()->getApplicationURI('question/edit/'); 62 + } 63 + 64 + protected function getObjectViewURI($object) { 65 + return $object->getViewURI(); 66 + } 67 + 68 + protected function buildCustomEditFields($object) { 69 + 70 + return array( 71 + id(new PhabricatorTextEditField()) 72 + ->setKey('title') 73 + ->setLabel(pht('Question')) 74 + ->setDescription(pht('Question title.')) 75 + ->setConduitTypeDescription(pht('New question title.')) 76 + ->setTransactionType( 77 + PonderQuestionTitleTransaction::TRANSACTIONTYPE) 78 + ->setValue($object->getTitle()) 79 + ->setIsRequired(true), 80 + id(new PhabricatorRemarkupEditField()) 81 + ->setKey('content') 82 + ->setLabel(pht('Details')) 83 + ->setDescription(pht('Long details of the question.')) 84 + ->setConduitTypeDescription(pht('New question details.')) 85 + ->setValue($object->getContent()) 86 + ->setTransactionType( 87 + PonderQuestionContentTransaction::TRANSACTIONTYPE), 88 + id(new PhabricatorRemarkupEditField()) 89 + ->setKey('answerWiki') 90 + ->setLabel(pht('Answer Summary')) 91 + ->setDescription(pht('Answer summary of the question.')) 92 + ->setConduitTypeDescription(pht('New question answer summary.')) 93 + ->setValue($object->getAnswerWiki()) 94 + ->setTransactionType( 95 + PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE), 96 + id(new PhabricatorSelectEditField()) 97 + ->setKey('status') 98 + ->setLabel(pht('Status')) 99 + ->setDescription(pht('Status of the question.')) 100 + ->setConduitTypeDescription(pht('New question status.')) 101 + ->setValue($object->getStatus()) 102 + ->setTransactionType( 103 + PonderQuestionStatusTransaction::TRANSACTIONTYPE) 104 + ->setOptions(PonderQuestionStatus::getQuestionStatusMap()), 105 + 106 + ); 107 + } 108 + 109 + }
+8 -3
src/applications/ponder/editor/PonderQuestionEditor.php
··· 9 9 return pht('Ponder Questions'); 10 10 } 11 11 12 + public function getCreateObjectTitle($author, $object) { 13 + return pht('%s created this question.', $author); 14 + } 15 + 16 + public function getCreateObjectTitleForFeed($author, $object) { 17 + return pht('%s created %s.', $author, $object); 18 + } 19 + 12 20 /** 13 21 * This is used internally on @{method:applyInitialEffects} if a transaction 14 22 * of type PonderQuestionTransaction::TYPE_ANSWERS is in the mix. The value ··· 64 72 65 73 public function getTransactionTypes() { 66 74 $types = parent::getTransactionTypes(); 67 - 68 75 $types[] = PhabricatorTransactions::TYPE_COMMENT; 69 76 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 70 - $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 71 - $types[] = PhabricatorTransactions::TYPE_SPACE; 72 77 73 78 return $types; 74 79 }
+8
src/applications/ponder/storage/PonderQuestion.php
··· 105 105 return $this->comments; 106 106 } 107 107 108 + public function getMonogram() { 109 + return 'Q'.$this->getID(); 110 + } 111 + 112 + public function getViewURI() { 113 + return '/'.$this->getMonogram(); 114 + } 115 + 108 116 public function attachAnswers(array $answers) { 109 117 assert_instances_of($answers, 'PonderAnswer'); 110 118 $this->answers = $answers;
+7
src/applications/ponder/xaction/PonderQuestionAnswerTransaction.php
··· 21 21 $this->renderAuthor()); 22 22 } 23 23 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s added an answer to %s.', 27 + $this->renderAuthor(), 28 + $this->renderObject()); 29 + } 30 + 24 31 public function getIcon() { 25 32 return 'fa-plus'; 26 33 }