1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-23 03:59:25 +01:00

Provide phame.post.edit Conduit API method

Summary:
Ref T9897. This one is a little more involved because of how getting a post on a blog works.

I also changed moving posts to be a real transaction (which shows up in history, now).

Test Plan: Created posts from web UI and conduit.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9897

Differential Revision: https://secure.phabricator.com/D14902
This commit is contained in:
epriestley 2015-12-28 05:46:22 -08:00
parent 00f1389f72
commit e0a97c88db
10 changed files with 197 additions and 38 deletions

View file

@ -3429,6 +3429,7 @@ phutil_register_library_map(array(
'PhamePost' => 'applications/phame/storage/PhamePost.php', 'PhamePost' => 'applications/phame/storage/PhamePost.php',
'PhamePostCommentController' => 'applications/phame/controller/post/PhamePostCommentController.php', 'PhamePostCommentController' => 'applications/phame/controller/post/PhamePostCommentController.php',
'PhamePostController' => 'applications/phame/controller/post/PhamePostController.php', 'PhamePostController' => 'applications/phame/controller/post/PhamePostController.php',
'PhamePostEditConduitAPIMethod' => 'applications/phame/conduit/PhamePostEditConduitAPIMethod.php',
'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php',
'PhamePostEditEngine' => 'applications/phame/editor/PhamePostEditEngine.php', 'PhamePostEditEngine' => 'applications/phame/editor/PhamePostEditEngine.php',
'PhamePostEditor' => 'applications/phame/editor/PhamePostEditor.php', 'PhamePostEditor' => 'applications/phame/editor/PhamePostEditor.php',
@ -4159,7 +4160,7 @@ phutil_register_library_map(array(
'ConduitMethodDoesNotExistException' => 'ConduitMethodNotFoundException', 'ConduitMethodDoesNotExistException' => 'ConduitMethodNotFoundException',
'ConduitMethodNotFoundException' => 'ConduitException', 'ConduitMethodNotFoundException' => 'ConduitException',
'ConduitPHIDListParameterType' => 'ConduitListParameterType', 'ConduitPHIDListParameterType' => 'ConduitListParameterType',
'ConduitPHIDParameterType' => 'ConduitListParameterType', 'ConduitPHIDParameterType' => 'ConduitParameterType',
'ConduitParameterType' => 'Phobject', 'ConduitParameterType' => 'Phobject',
'ConduitPingConduitAPIMethod' => 'ConduitAPIMethod', 'ConduitPingConduitAPIMethod' => 'ConduitAPIMethod',
'ConduitProjectListParameterType' => 'ConduitListParameterType', 'ConduitProjectListParameterType' => 'ConduitListParameterType',
@ -7891,6 +7892,7 @@ phutil_register_library_map(array(
), ),
'PhamePostCommentController' => 'PhamePostController', 'PhamePostCommentController' => 'PhamePostController',
'PhamePostController' => 'PhameController', 'PhamePostController' => 'PhameController',
'PhamePostEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhamePostEditController' => 'PhamePostController', 'PhamePostEditController' => 'PhamePostController',
'PhamePostEditEngine' => 'PhabricatorEditEngine', 'PhamePostEditEngine' => 'PhabricatorEditEngine',
'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor', 'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor',

View file

@ -1,7 +1,7 @@
<?php <?php
final class ConduitPHIDParameterType final class ConduitPHIDParameterType
extends ConduitListParameterType { extends ConduitParameterType {
protected function getParameterValue(array $request, $key) { protected function getParameterValue(array $request, $key) {
$value = parent::getParameterValue($request, $key); $value = parent::getParameterValue($request, $key);

View file

@ -0,0 +1,18 @@
<?php
final class PhamePostEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'phame.post.edit';
}
public function newEditEngine() {
return new PhamePostEditEngine();
}
public function getMethodSummary() {
return pht('Create or edit blog posts in Phame.');
}
}

View file

@ -2,6 +2,17 @@
final class PhamePostEditController extends PhamePostController { final class PhamePostEditController extends PhamePostController {
private $blog;
public function setBlog(PhameBlog $blog) {
$this->blog = $blog;
return $this;
}
public function getBlog() {
return $this->blog;
}
public function handleRequest(AphrontRequest $request) { public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer(); $viewer = $request->getViewer();
$id = $request->getURIData('id'); $id = $request->getURIData('id');
@ -12,6 +23,7 @@ final class PhamePostEditController extends PhamePostController {
->withIDs(array($id)) ->withIDs(array($id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->executeOne(); ->executeOne();
@ -32,15 +44,29 @@ final class PhamePostEditController extends PhamePostController {
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->executeOne(); ->executeOne();
if (!$blog) { if (!$blog) {
return new Aphront404Response(); return new Aphront404Response();
} }
$this->setBlog($blog);
return id(new PhamePostEditEngine()) return id(new PhamePostEditEngine())
->setController($this) ->setController($this)
->setBlog($blog) ->setBlog($blog)
->buildResponse(); ->buildResponse();
} }
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$blog = $this->getBlog();
$crumbs->addTextCrumb(
$blog->getName(),
$blog->getViewURI());
return $crumbs;
}
} }

View file

@ -20,59 +20,57 @@ final class PhamePostMoveController extends PhamePostController {
return new Aphront404Response(); return new Aphront404Response();
} }
$view_uri = '/post/view/'.$post->getID().'/'; $view_uri = $post->getViewURI();
$view_uri = $this->getApplicationURI($view_uri); $v_blog = $post->getBlog()->getPHID();
if ($request->isFormPost()) { if ($request->isFormPost()) {
$blog = id(new PhameBlogQuery()) $v_blog = $request->getStr('blogPHID');
->setViewer($viewer)
->withIDs(array($request->getInt('blog')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if ($blog) { $xactions = array();
$post->setBlogPHID($blog->getPHID()); $xactions[] = id(new PhamePostTransaction())
$post->save(); ->setTransactionType(PhamePostTransaction::TYPE_BLOG)
->setNewValue($v_blog);
return id(new AphrontRedirectResponse()) $editor = id(new PhamePostEditor())
->setURI($view_uri.'?moved=1'); ->setActor($viewer)
} ->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true);
$editor->applyTransactions($post, $xactions);
$view_uri = $post->getViewURI();
return id(new AphrontRedirectResponse())
->setURI($view_uri.'?moved=1');
} }
$blogs = id(new PhameBlogQuery()) $blogs = id(new PhameBlogQuery())
->setViewer($viewer) ->setViewer($viewer)
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->execute(); ->execute();
$options = mpull($blogs, 'getName', 'getID'); $options = mpull($blogs, 'getName', 'getPHID');
asort($options); asort($options);
$selected_value = null;
if ($post && $post->getBlog()) {
$selected_value = $post->getBlog()->getID();
}
$form = id(new PHUIFormLayoutView()) $form = id(new PHUIFormLayoutView())
->setUser($viewer) ->setUser($viewer)
->appendChild( ->appendChild(
id(new AphrontFormSelectControl()) id(new AphrontFormSelectControl())
->setLabel(pht('Blog')) ->setLabel(pht('Blog'))
->setName('blog') ->setName('blogPHID')
->setOptions($options) ->setOptions($options)
->setValue($selected_value)); ->setValue($v_blog));
return $this->newDialog() return $this->newDialog()
->setTitle(pht('Move Post')) ->setTitle(pht('Move Post'))
->appendChild($form) ->appendChild($form)
->addSubmitButton(pht('Move Post')) ->addSubmitButton(pht('Move Post'))
->addCancelButton($view_uri); ->addCancelButton($view_uri);
} }
} }

View file

@ -65,16 +65,24 @@ final class PhamePostEditEngine
} }
protected function buildCustomEditFields($object) { protected function buildCustomEditFields($object) {
$blog_phid = $object->getBlog()->getPHID();
if ($this->blog) {
$blog_title = pht('Blog: %s', $this->blog->getName());
} else {
$blog_title = pht('Sample Blog Title');
}
return array( return array(
id(new PhabricatorInstructionsEditField()) id(new PhabricatorHandlesEditField())
->setValue($blog_title), ->setKey('blog')
->setLabel(pht('Blog'))
->setDescription(pht('Blog to publish this post to.'))
->setConduitDescription(
pht('Choose a blog to create a post on (or move a post to).'))
->setConduitTypeDescription(pht('PHID of the blog.'))
->setAliases(array('blogPHID'))
->setTransactionType(PhamePostTransaction::TYPE_BLOG)
->setHandleParameterType(new AphrontPHIDListHTTPParameterType())
->setSingleValue($blog_phid)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false)
->setIsLocked(true),
id(new PhabricatorTextEditField()) id(new PhabricatorTextEditField())
->setKey('title') ->setKey('title')
->setLabel(pht('Title')) ->setLabel(pht('Title'))

View file

@ -14,6 +14,7 @@ final class PhamePostEditor
public function getTransactionTypes() { public function getTransactionTypes() {
$types = parent::getTransactionTypes(); $types = parent::getTransactionTypes();
$types[] = PhamePostTransaction::TYPE_BLOG;
$types[] = PhamePostTransaction::TYPE_TITLE; $types[] = PhamePostTransaction::TYPE_TITLE;
$types[] = PhamePostTransaction::TYPE_BODY; $types[] = PhamePostTransaction::TYPE_BODY;
$types[] = PhamePostTransaction::TYPE_VISIBILITY; $types[] = PhamePostTransaction::TYPE_VISIBILITY;
@ -27,6 +28,8 @@ final class PhamePostEditor
PhabricatorApplicationTransaction $xaction) { PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case PhamePostTransaction::TYPE_BLOG:
return $object->getBlogPHID();
case PhamePostTransaction::TYPE_TITLE: case PhamePostTransaction::TYPE_TITLE:
return $object->getTitle(); return $object->getTitle();
case PhamePostTransaction::TYPE_BODY: case PhamePostTransaction::TYPE_BODY:
@ -44,6 +47,7 @@ final class PhamePostEditor
case PhamePostTransaction::TYPE_TITLE: case PhamePostTransaction::TYPE_TITLE:
case PhamePostTransaction::TYPE_BODY: case PhamePostTransaction::TYPE_BODY:
case PhamePostTransaction::TYPE_VISIBILITY: case PhamePostTransaction::TYPE_VISIBILITY:
case PhamePostTransaction::TYPE_BLOG:
return $xaction->getNewValue(); return $xaction->getNewValue();
} }
} }
@ -57,6 +61,8 @@ final class PhamePostEditor
return $object->setTitle($xaction->getNewValue()); return $object->setTitle($xaction->getNewValue());
case PhamePostTransaction::TYPE_BODY: case PhamePostTransaction::TYPE_BODY:
return $object->setBody($xaction->getNewValue()); return $object->setBody($xaction->getNewValue());
case PhamePostTransaction::TYPE_BLOG:
return $object->setBlogPHID($xaction->getNewValue());
case PhamePostTransaction::TYPE_VISIBILITY: case PhamePostTransaction::TYPE_VISIBILITY:
if ($xaction->getNewValue() == PhameConstants::VISIBILITY_DRAFT) { if ($xaction->getNewValue() == PhameConstants::VISIBILITY_DRAFT) {
$object->setDatePublished(0); $object->setDatePublished(0);
@ -77,6 +83,7 @@ final class PhamePostEditor
case PhamePostTransaction::TYPE_TITLE: case PhamePostTransaction::TYPE_TITLE:
case PhamePostTransaction::TYPE_BODY: case PhamePostTransaction::TYPE_BODY:
case PhamePostTransaction::TYPE_VISIBILITY: case PhamePostTransaction::TYPE_VISIBILITY:
case PhamePostTransaction::TYPE_BLOG:
return; return;
} }
@ -106,6 +113,53 @@ final class PhamePostEditor
$error->setIsMissingFieldError(true); $error->setIsMissingFieldError(true);
$errors[] = $error; $errors[] = $error;
} }
break;
case PhamePostTransaction::TYPE_BLOG:
if ($this->getIsNewObject()) {
if (!$xactions) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht(
'When creating a post, you must specify which blog it '.
'should belong to.'),
null);
$error->setIsMissingFieldError(true);
$errors[] = $error;
break;
}
}
foreach ($xactions as $xaction) {
$new_phid = $xaction->getNewValue();
$blog = id(new PhameBlogQuery())
->setViewer($this->getActor())
->withPHIDs(array($new_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
if ($blog) {
continue;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'The specified blog PHID ("%s") is not valid. You can only '.
'create a post on (or move a post into) a blog which you '.
'have permission to see and edit.',
$new_phid),
$xaction);
}
break; break;
} }
return $errors; return $errors;

View file

@ -7,6 +7,7 @@ final class PhamePostTransaction
const TYPE_PHAME_TITLE = 'phame.post.phame.title'; const TYPE_PHAME_TITLE = 'phame.post.phame.title';
const TYPE_BODY = 'phame.post.body'; const TYPE_BODY = 'phame.post.body';
const TYPE_VISIBILITY = 'phame.post.visibility'; const TYPE_VISIBILITY = 'phame.post.visibility';
const TYPE_BLOG = 'phame.post.blog';
const MAILTAG_CONTENT = 'phame-post-content'; const MAILTAG_CONTENT = 'phame-post-content';
const MAILTAG_SUBSCRIBERS = 'phame-post-subscribers'; const MAILTAG_SUBSCRIBERS = 'phame-post-subscribers';
@ -47,6 +48,28 @@ final class PhamePostTransaction
return parent::shouldHide(); return parent::shouldHide();
} }
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
switch ($this->getTransactionType()) {
case self::TYPE_BLOG:
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old) {
$phids[] = $old;
}
if ($new) {
$phids[] = $new;
}
break;
}
return $phids;
}
public function getIcon() { public function getIcon() {
$old = $this->getOldValue(); $old = $this->getOldValue();
switch ($this->getTransactionType()) { switch ($this->getTransactionType()) {
@ -98,6 +121,16 @@ final class PhamePostTransaction
$type = $this->getTransactionType(); $type = $this->getTransactionType();
switch ($type) { switch ($type) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this post.',
$this->renderHandleLink($author_phid));
case self::TYPE_BLOG:
return pht(
'%s moved this post from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
case self::TYPE_TITLE: case self::TYPE_TITLE:
if ($old === null) { if ($old === null) {
return pht( return pht(
@ -146,6 +179,13 @@ final class PhamePostTransaction
$type = $this->getTransactionType(); $type = $this->getTransactionType();
switch ($type) { switch ($type) {
case self::TYPE_BLOG:
return pht(
'%s moved post "%s" from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
case self::TYPE_TITLE: case self::TYPE_TITLE:
if ($old === null) { if ($old === null) {
return pht( return pht(

View file

@ -1688,7 +1688,16 @@ abstract class PhabricatorEditEngine
// Let the parameter type interpret the value. This allows you to // Let the parameter type interpret the value. This allows you to
// use usernames in list<user> fields, for example. // use usernames in list<user> fields, for example.
$parameter_type = $type->getConduitParameterType(); $parameter_type = $type->getConduitParameterType();
$xaction['value'] = $parameter_type->getValue($xaction, 'value');
try {
$xaction['value'] = $parameter_type->getValue($xaction, 'value');
} catch (Exception $ex) {
throw new PhutilProxyException(
pht(
'Exception when processing transaction of type "%s".',
$xaction['type']),
$ex);
}
$type_xactions = $type->generateTransactions( $type_xactions = $type->generateTransactions(
clone $template, clone $template,

View file

@ -35,7 +35,11 @@ abstract class PhabricatorPHIDListEditField
} }
protected function newConduitParameterType() { protected function newConduitParameterType() {
return new ConduitPHIDListParameterType(); if ($this->getIsSingleValue()) {
return new ConduitPHIDParameterType();
} else {
return new ConduitPHIDListParameterType();
}
} }
protected function getValueFromRequest(AphrontRequest $request, $key) { protected function getValueFromRequest(AphrontRequest $request, $key) {