diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4606,6 +4606,7 @@ 'PonderQuestionContentTransaction' => 'applications/ponder/xaction/PonderQuestionContentTransaction.php', 'PonderQuestionCreateMailReceiver' => 'applications/ponder/mail/PonderQuestionCreateMailReceiver.php', 'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php', + 'PonderQuestionEditEngine' => 'applications/ponder/editor/PonderQuestionEditEngine.php', 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 'PonderQuestionFulltextEngine' => 'applications/ponder/search/PonderQuestionFulltextEngine.php', 'PonderQuestionHistoryController' => 'applications/ponder/controller/PonderQuestionHistoryController.php', @@ -10194,6 +10195,7 @@ 'PonderQuestionContentTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionCreateMailReceiver' => 'PhabricatorMailReceiver', 'PonderQuestionEditController' => 'PonderController', + 'PonderQuestionEditEngine' => 'PhabricatorEditEngine', 'PonderQuestionEditor' => 'PonderEditor', 'PonderQuestionFulltextEngine' => 'PhabricatorFulltextEngine', 'PonderQuestionHistoryController' => 'PonderController', diff --git a/src/applications/ponder/application/PhabricatorPonderApplication.php b/src/applications/ponder/application/PhabricatorPonderApplication.php --- a/src/applications/ponder/application/PhabricatorPonderApplication.php +++ b/src/applications/ponder/application/PhabricatorPonderApplication.php @@ -60,22 +60,26 @@ '/ponder/' => array( '(?:query/(?P[^/]+)/)?' => 'PonderQuestionListController', - 'answer/add/' - => 'PonderAnswerSaveController', - 'answer/edit/(?P\d+)/' - => 'PonderAnswerEditController', - 'answer/comment/(?P\d+)/' - => 'PonderAnswerCommentController', - 'answer/history/(?P\d+)/' - => 'PonderAnswerHistoryController', - 'question/edit/(?:(?P\d+)/)?' - => 'PonderQuestionEditController', - 'question/create/' - => 'PonderQuestionEditController', - 'question/comment/(?P\d+)/' - => 'PonderQuestionCommentController', - 'question/history/(?P\d+)/' - => 'PonderQuestionHistoryController', + 'answer/' => array( + 'add/' + => 'PonderAnswerSaveController', + 'edit/(?P\d+)/' + => 'PonderAnswerEditController', + 'comment/(?P\d+)/' + => 'PonderAnswerCommentController', + 'history/(?P\d+)/' + => 'PonderAnswerHistoryController', + ), + 'question/' => array( + $this->getEditRoutePattern('edit/') + => 'PonderQuestionEditController', + 'create/' + => 'PonderQuestionEditController', + 'comment/(?P\d+)/' + => 'PonderQuestionCommentController', + 'history/(?P\d+)/' + => 'PonderQuestionHistoryController', + ), 'preview/' => 'PhabricatorMarkupPreviewController', 'question/status/(?P[1-9]\d*)/' diff --git a/src/applications/ponder/controller/PonderController.php b/src/applications/ponder/controller/PonderController.php --- a/src/applications/ponder/controller/PonderController.php +++ b/src/applications/ponder/controller/PonderController.php @@ -27,13 +27,9 @@ protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); - $href = $this->getApplicationURI('question/create/'); - $crumbs - ->addAction( - id(new PHUIListItemView()) - ->setName(pht('Ask Question')) - ->setHref($href) - ->setIcon('fa-plus-square')); + id(new PonderQuestionEditEngine()) + ->setViewer($this->getViewer()) + ->addActionToCrumbs($crumbs); return $crumbs; } diff --git a/src/applications/ponder/controller/PonderQuestionEditController.php b/src/applications/ponder/controller/PonderQuestionEditController.php --- a/src/applications/ponder/controller/PonderQuestionEditController.php +++ b/src/applications/ponder/controller/PonderQuestionEditController.php @@ -1,222 +1,11 @@ getViewer(); - $id = $request->getURIData('id'); - - if ($id) { - $question = id(new PonderQuestionQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$question) { - return new Aphront404Response(); - } - $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $question->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $v_projects = array_reverse($v_projects); - $is_new = false; - } else { - $is_new = true; - $question = PonderQuestion::initializeNewQuestion($viewer); - $v_projects = array(); - } - - $v_title = $question->getTitle(); - $v_content = $question->getContent(); - $v_wiki = $question->getAnswerWiki(); - $v_view = $question->getViewPolicy(); - $v_space = $question->getSpacePHID(); - $v_status = $question->getStatus(); - - - $errors = array(); - $e_title = true; - if ($request->isFormPost()) { - $v_title = $request->getStr('title'); - $v_content = $request->getStr('content'); - $v_wiki = $request->getStr('answerWiki'); - $v_projects = $request->getArr('projects'); - $v_view = $request->getStr('viewPolicy'); - $v_space = $request->getStr('spacePHID'); - $v_status = $request->getStr('status'); - - $len = phutil_utf8_strlen($v_title); - if ($len < 1) { - $errors[] = pht('Title must not be empty.'); - $e_title = pht('Required'); - } else if ($len > 255) { - $errors[] = pht('Title is too long.'); - $e_title = pht('Too Long'); - } - - if (!$errors) { - $template = id(new PonderQuestionTransaction()); - $xactions = array(); - - $xactions[] = id(clone $template) - ->setTransactionType(PonderQuestionTitleTransaction::TRANSACTIONTYPE) - ->setNewValue($v_title); - - $xactions[] = id(clone $template) - ->setTransactionType( - PonderQuestionContentTransaction::TRANSACTIONTYPE) - ->setNewValue($v_content); - - $xactions[] = id(clone $template) - ->setTransactionType( - PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE) - ->setNewValue($v_wiki); - - if (!$is_new) { - $xactions[] = id(clone $template) - ->setTransactionType( - PonderQuestionStatusTransaction::TRANSACTIONTYPE) - ->setNewValue($v_status); - } - - $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) - ->setNewValue($v_view); - - $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) - ->setNewValue($v_space); - - $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $xactions[] = id(new PonderQuestionTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $proj_edge_type) - ->setNewValue(array('=' => array_fuse($v_projects))); - - $editor = id(new PonderQuestionEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - $editor->applyTransactions($question, $xactions); - - return id(new AphrontRedirectResponse()) - ->setURI('/Q'.$question->getID()); - } - } - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($question) - ->execute(); - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Question')) - ->setName('title') - ->setValue($v_title) - ->setError($e_title)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($viewer) - ->setName('content') - ->setID('content') - ->setValue($v_content) - ->setLabel(pht('Question Details')) - ->setUser($viewer)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($viewer) - ->setName('answerWiki') - ->setID('answerWiki') - ->setValue($v_wiki) - ->setLabel(pht('Answer Summary')) - ->setUser($viewer)) - ->appendControl( - id(new AphrontFormPolicyControl()) - ->setName('viewPolicy') - ->setPolicyObject($question) - ->setSpacePHID($v_space) - ->setPolicies($policies) - ->setValue($v_view) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)); - - - if (!$is_new) { - $form->appendChild( - id(new AphrontFormSelectControl()) - ->setLabel(pht('Status')) - ->setName('status') - ->setValue($v_status) - ->setOptions(PonderQuestionStatus::getQuestionStatusMap())); - } - - $form->appendControl( - id(new AphrontFormTokenizerControl()) - ->setLabel(pht('Tags')) - ->setName('projects') - ->setValue($v_projects) - ->setDatasource(new PhabricatorProjectDatasource())); - - $form->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($this->getApplicationURI()) - ->setValue(pht('Submit'))); - - $preview = id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Question Preview')) - ->setControlID('content') - ->setPreviewURI($this->getApplicationURI('preview/')); - - $answer_preview = id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Answer Summary Preview')) - ->setControlID('answerWiki') - ->setPreviewURI($this->getApplicationURI('preview/')); - - $crumbs = $this->buildApplicationCrumbs(); - - $id = $question->getID(); - if ($id) { - $crumbs->addTextCrumb("Q{$id}", "/Q{$id}"); - $crumbs->addTextCrumb(pht('Edit')); - $title = pht('Edit Question'); - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon('fa-pencil'); - } else { - $crumbs->addTextCrumb(pht('Ask Question')); - $title = pht('Ask New Question'); - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon('fa-plus-square'); - } - $crumbs->setBorder(true); - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Question')) - ->setFormErrors($errors) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($form); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter(array( - $box, - $preview, - $answer_preview, - )); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); - + return id(new PonderQuestionEditEngine()) + ->setController($this) + ->buildResponse(); } } diff --git a/src/applications/ponder/editor/PonderAnswerEditor.php b/src/applications/ponder/editor/PonderAnswerEditor.php --- a/src/applications/ponder/editor/PonderAnswerEditor.php +++ b/src/applications/ponder/editor/PonderAnswerEditor.php @@ -6,6 +6,14 @@ return pht('Ponder Answers'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s added this answer.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s added %s.', $author, $object); + } + public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; diff --git a/src/applications/ponder/editor/PonderQuestionEditEngine.php b/src/applications/ponder/editor/PonderQuestionEditEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/ponder/editor/PonderQuestionEditEngine.php @@ -0,0 +1,109 @@ +getViewer()); + } + + protected function newObjectQuery() { + return new PonderQuestionQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Question'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit Question: %s', $object->getTitle()); + } + + protected function getObjectEditShortText($object) { + return $object->getTitle(); + } + + protected function getObjectCreateShortText() { + return pht('New Question'); + } + + protected function getObjectName() { + return pht('Question'); + } + + protected function getObjectCreateCancelURI($object) { + return $this->getApplication()->getApplicationURI('/'); + } + + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('question/edit/'); + } + + protected function getObjectViewURI($object) { + return $object->getViewURI(); + } + + protected function buildCustomEditFields($object) { + + return array( + id(new PhabricatorTextEditField()) + ->setKey('title') + ->setLabel(pht('Question')) + ->setDescription(pht('Question title.')) + ->setConduitTypeDescription(pht('New question title.')) + ->setTransactionType( + PonderQuestionTitleTransaction::TRANSACTIONTYPE) + ->setValue($object->getTitle()) + ->setIsRequired(true), + id(new PhabricatorRemarkupEditField()) + ->setKey('content') + ->setLabel(pht('Details')) + ->setDescription(pht('Long details of the question.')) + ->setConduitTypeDescription(pht('New question details.')) + ->setValue($object->getContent()) + ->setTransactionType( + PonderQuestionContentTransaction::TRANSACTIONTYPE), + id(new PhabricatorRemarkupEditField()) + ->setKey('answerWiki') + ->setLabel(pht('Answer Summary')) + ->setDescription(pht('Answer summary of the question.')) + ->setConduitTypeDescription(pht('New question answer summary.')) + ->setValue($object->getAnswerWiki()) + ->setTransactionType( + PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE), + id(new PhabricatorSelectEditField()) + ->setKey('status') + ->setLabel(pht('Status')) + ->setDescription(pht('Status of the question.')) + ->setConduitTypeDescription(pht('New question status.')) + ->setValue($object->getStatus()) + ->setTransactionType( + PonderQuestionStatusTransaction::TRANSACTIONTYPE) + ->setOptions(PonderQuestionStatus::getQuestionStatusMap()), + + ); + } + +} diff --git a/src/applications/ponder/editor/PonderQuestionEditor.php b/src/applications/ponder/editor/PonderQuestionEditor.php --- a/src/applications/ponder/editor/PonderQuestionEditor.php +++ b/src/applications/ponder/editor/PonderQuestionEditor.php @@ -9,6 +9,14 @@ return pht('Ponder Questions'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s created this question.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); + } + /** * This is used internally on @{method:applyInitialEffects} if a transaction * of type PonderQuestionTransaction::TYPE_ANSWERS is in the mix. The value @@ -64,11 +72,8 @@ public function getTransactionTypes() { $types = parent::getTransactionTypes(); - $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; - $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; - $types[] = PhabricatorTransactions::TYPE_SPACE; return $types; } diff --git a/src/applications/ponder/storage/PonderQuestion.php b/src/applications/ponder/storage/PonderQuestion.php --- a/src/applications/ponder/storage/PonderQuestion.php +++ b/src/applications/ponder/storage/PonderQuestion.php @@ -105,6 +105,14 @@ return $this->comments; } + public function getMonogram() { + return 'Q'.$this->getID(); + } + + public function getViewURI() { + return '/'.$this->getMonogram(); + } + public function attachAnswers(array $answers) { assert_instances_of($answers, 'PonderAnswer'); $this->answers = $answers; diff --git a/src/applications/ponder/xaction/PonderQuestionAnswerTransaction.php b/src/applications/ponder/xaction/PonderQuestionAnswerTransaction.php --- a/src/applications/ponder/xaction/PonderQuestionAnswerTransaction.php +++ b/src/applications/ponder/xaction/PonderQuestionAnswerTransaction.php @@ -21,6 +21,13 @@ $this->renderAuthor()); } + public function getTitleForFeed() { + return pht( + '%s added an answer to %s.', + $this->renderAuthor(), + $this->renderObject()); + } + public function getIcon() { return 'fa-plus'; }