1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

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
This commit is contained in:
Chad Little 2017-05-02 08:52:09 -07:00
parent 4aec809b69
commit d467a9e337
9 changed files with 170 additions and 242 deletions

View file

@ -4606,6 +4606,7 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'PonderQuestionContentTransaction' => 'PonderQuestionTransactionType',
'PonderQuestionCreateMailReceiver' => 'PhabricatorMailReceiver',
'PonderQuestionEditController' => 'PonderController',
'PonderQuestionEditEngine' => 'PhabricatorEditEngine',
'PonderQuestionEditor' => 'PonderEditor',
'PonderQuestionFulltextEngine' => 'PhabricatorFulltextEngine',
'PonderQuestionHistoryController' => 'PonderController',

View file

@ -60,22 +60,26 @@ final class PhabricatorPonderApplication extends PhabricatorApplication {
'/ponder/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PonderQuestionListController',
'answer/add/'
=> 'PonderAnswerSaveController',
'answer/edit/(?P<id>\d+)/'
=> 'PonderAnswerEditController',
'answer/comment/(?P<id>\d+)/'
=> 'PonderAnswerCommentController',
'answer/history/(?P<id>\d+)/'
=> 'PonderAnswerHistoryController',
'question/edit/(?:(?P<id>\d+)/)?'
=> 'PonderQuestionEditController',
'question/create/'
=> 'PonderQuestionEditController',
'question/comment/(?P<id>\d+)/'
=> 'PonderQuestionCommentController',
'question/history/(?P<id>\d+)/'
=> 'PonderQuestionHistoryController',
'answer/' => array(
'add/'
=> 'PonderAnswerSaveController',
'edit/(?P<id>\d+)/'
=> 'PonderAnswerEditController',
'comment/(?P<id>\d+)/'
=> 'PonderAnswerCommentController',
'history/(?P<id>\d+)/'
=> 'PonderAnswerHistoryController',
),
'question/' => array(
$this->getEditRoutePattern('edit/')
=> 'PonderQuestionEditController',
'create/'
=> 'PonderQuestionEditController',
'comment/(?P<id>\d+)/'
=> 'PonderQuestionCommentController',
'history/(?P<id>\d+)/'
=> 'PonderQuestionHistoryController',
),
'preview/'
=> 'PhabricatorMarkupPreviewController',
'question/status/(?P<id>[1-9]\d*)/'

View file

@ -27,13 +27,9 @@ abstract class PonderController extends PhabricatorController {
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;
}

View file

@ -1,222 +1,11 @@
<?php
final class PonderQuestionEditController extends PonderController {
final class PonderQuestionEditController extends
PonderController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->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();
}
}

View file

@ -6,6 +6,14 @@ final class PonderAnswerEditor extends PonderEditor {
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;

View file

@ -0,0 +1,109 @@
<?php
final class PonderQuestionEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'ponder.question';
public function getEngineName() {
return pht('Ponder Question');
}
public function getEngineApplicationClass() {
return 'PhabricatorPonderApplication';
}
public function getSummaryHeader() {
return pht('Configure Ponder Question Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Ponder Questions.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return PonderQuestion::initializeNewQuestion($this->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()),
);
}
}

View file

@ -9,6 +9,14 @@ final class PonderQuestionEditor
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 @@ final class PonderQuestionEditor
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;
}

View file

@ -105,6 +105,14 @@ final class PonderQuestion extends PonderDAO
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;

View file

@ -21,6 +21,13 @@ final class PonderQuestionAnswerTransaction
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s added an answer to %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function getIcon() {
return 'fa-plus';
}