Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/autopatches/20151108.phame.blog.joinpolicy.sql b/resources/sql/autopatches/20151108.phame.blog.joinpolicy.sql
new file mode 100644
index 0000000000..54aea48bbf
--- /dev/null
+++ b/resources/sql/autopatches/20151108.phame.blog.joinpolicy.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_phame.phame_blog
+ DROP joinPolicy;
diff --git a/src/applications/phame/conduit/PhameCreatePostConduitAPIMethod.php b/src/applications/phame/conduit/PhameCreatePostConduitAPIMethod.php
index 425bf17353..1f569d3a3b 100644
--- a/src/applications/phame/conduit/PhameCreatePostConduitAPIMethod.php
+++ b/src/applications/phame/conduit/PhameCreatePostConduitAPIMethod.php
@@ -1,103 +1,104 @@
<?php
final class PhameCreatePostConduitAPIMethod extends PhameConduitAPIMethod {
public function getAPIMethodName() {
return 'phame.createpost';
}
public function getMethodDescription() {
return pht('Create a phame post.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
}
protected function defineParamTypes() {
return array(
'blogPHID' => 'required phid',
'title' => 'required string',
'body' => 'required string',
'phameTitle' => 'optional string',
'bloggerPHID' => 'optional phid',
'isDraft' => 'optional bool',
);
}
protected function defineReturnType() {
return 'list<dict>';
}
protected function defineErrorTypes() {
return array(
'ERR-INVALID-PARAMETER' =>
pht('Missing or malformed parameter.'),
'ERR-INVALID-BLOG' =>
pht('Invalid blog PHID or user can not post to blog.'),
);
}
protected function execute(ConduitAPIRequest $request) {
$user = $request->getUser();
$blog_phid = $request->getValue('blogPHID');
$title = $request->getValue('title');
$body = $request->getValue('body');
$exception_description = array();
if (!$blog_phid) {
$exception_description[] = pht('No blog phid.');
}
if (!strlen($title)) {
$exception_description[] = pht('No post title.');
}
if (!strlen($body)) {
$exception_description[] = pht('No post body.');
}
if ($exception_description) {
throw id(new ConduitException('ERR-INVALID-PARAMETER'))
->setErrorDescription(implode("\n", $exception_description));
}
$blogger_phid = $request->getValue('bloggerPHID');
if ($blogger_phid) {
$blogger = id(new PhabricatorPeopleQuery())
->setViewer($user)
->withPHIDs(array($blogger_phid))
->executeOne();
} else {
$blogger = $user;
}
$blog = id(new PhameBlogQuery())
->setViewer($blogger)
->withPHIDs(array($blog_phid))
->requireCapabilities(
array(
- PhabricatorPolicyCapability::CAN_JOIN,
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$blog) {
throw new ConduitException('ERR-INVALID-BLOG');
}
$post = PhamePost::initializePost($blogger, $blog);
$is_draft = $request->getValue('isDraft', false);
if (!$is_draft) {
$post->setDatePublished(time());
$post->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
}
$post->setTitle($title);
$phame_title = $request->getValue(
'phameTitle',
id(new PhutilUTF8StringTruncator())
->setMaximumBytes(64)
->truncateString($title));
$post->setPhameTitle(PhabricatorSlug::normalize($phame_title));
$post->setBody($body);
$post->save();
return $post->toDictionary();
}
}
diff --git a/src/applications/phame/controller/blog/PhameBlogEditController.php b/src/applications/phame/controller/blog/PhameBlogEditController.php
index b59e5e01a2..0c2bb324dc 100644
--- a/src/applications/phame/controller/blog/PhameBlogEditController.php
+++ b/src/applications/phame/controller/blog/PhameBlogEditController.php
@@ -1,223 +1,210 @@
<?php
final class PhameBlogEditController
extends PhameBlogController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if ($id) {
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
$submit_button = pht('Save Changes');
$page_title = pht('Edit Blog');
$cancel_uri = $this->getApplicationURI('blog/view/'.$blog->getID().'/');
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$blog->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
$v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$blog->getPHID());
} else {
$this->requireApplicationCapability(
PhameBlogCreateCapability::CAPABILITY);
$blog = PhameBlog::initializeNewBlog($viewer);
$submit_button = pht('Create Blog');
$page_title = pht('Create Blog');
$cancel_uri = $this->getApplicationURI();
$v_projects = array();
$v_cc = array();
}
$name = $blog->getName();
$description = $blog->getDescription();
$custom_domain = $blog->getDomain();
$skin = $blog->getSkin();
$can_view = $blog->getViewPolicy();
$can_edit = $blog->getEditPolicy();
- $can_join = $blog->getJoinPolicy();
$e_name = true;
$e_custom_domain = null;
$e_view_policy = null;
$validation_exception = null;
if ($request->isFormPost()) {
$name = $request->getStr('name');
$description = $request->getStr('description');
$custom_domain = nonempty($request->getStr('custom_domain'), null);
$skin = $request->getStr('skin');
$can_view = $request->getStr('can_view');
$can_edit = $request->getStr('can_edit');
- $can_join = $request->getStr('can_join');
$v_projects = $request->getArr('projects');
$v_cc = $request->getArr('cc');
$xactions = array(
id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_NAME)
->setNewValue($name),
id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_DESCRIPTION)
->setNewValue($description),
id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_DOMAIN)
->setNewValue($custom_domain),
id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_SKIN)
->setNewValue($skin),
id(new PhameBlogTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($can_view),
id(new PhameBlogTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($can_edit),
- id(new PhameBlogTransaction())
- ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY)
- ->setNewValue($can_join),
id(new PhameBlogTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => $v_cc)),
);
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PhameBlogTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $proj_edge_type)
->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new PhameBlogEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$editor->applyTransactions($blog, $xactions);
return id(new AphrontRedirectResponse())
->setURI($this->getApplicationURI('blog/view/'.$blog->getID().'/'));
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_name = $validation_exception->getShortMessage(
PhameBlogTransaction::TYPE_NAME);
$e_custom_domain = $validation_exception->getShortMessage(
PhameBlogTransaction::TYPE_DOMAIN);
$e_view_policy = $validation_exception->getShortMessage(
PhabricatorTransactions::TYPE_VIEW_POLICY);
}
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($blog)
->execute();
$skins = PhameSkinSpecification::loadAllSkinSpecifications();
$skins = mpull($skins, 'getName');
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($name)
->setID('blog-name')
->setError($e_name))
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setLabel(pht('Description'))
->setName('description')
->setValue($description)
->setID('blog-description')
->setUser($viewer)
->setDisableMacros(true))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('cc')
->setValue($v_cc)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($blog)
->setPolicies($policies)
->setError($e_view_policy)
->setValue($can_view)
->setName('can_view'))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($blog)
->setPolicies($policies)
->setValue($can_edit)
->setName('can_edit'))
- ->appendChild(
- id(new AphrontFormPolicyControl())
- ->setUser($viewer)
- ->setCapability(PhabricatorPolicyCapability::CAN_JOIN)
- ->setPolicyObject($blog)
- ->setPolicies($policies)
- ->setValue($can_join)
- ->setName('can_join'))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setValue($v_projects)
->setDatasource(new PhabricatorProjectDatasource()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Custom Domain'))
->setName('custom_domain')
->setValue($custom_domain)
->setCaption(
pht('Must include at least one dot (.), e.g. %s', 'blog.example.com'))
->setError($e_custom_domain))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Skin'))
->setName('skin')
->setValue($skin)
->setOptions($skins))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($submit_button));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setValidationException($validation_exception)
->setForm($form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/'));
$crumbs->addTextCrumb($page_title, $this->getApplicationURI('blog/new'));
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->appendChild(
array(
$form_box,
));
}
}
diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php
index 03dfc8c1c6..249bd5506a 100644
--- a/src/applications/phame/controller/blog/PhameBlogViewController.php
+++ b/src/applications/phame/controller/blog/PhameBlogViewController.php
@@ -1,178 +1,169 @@
<?php
final class PhameBlogViewController extends PhameBlogController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
$pager = id(new AphrontCursorPagerView())
->readFromRequest($request);
$posts = id(new PhamePostQuery())
->setViewer($viewer)
->withBlogPHIDs(array($blog->getPHID()))
->executeWithCursorPager($pager);
$header = id(new PHUIHeaderView())
->setHeader($blog->getName())
->setUser($viewer)
->setPolicyObject($blog);
$actions = $this->renderActions($blog, $viewer);
$properties = $this->renderProperties($blog, $viewer, $actions);
$post_list = $this->renderPostList(
$posts,
$viewer,
pht('This blog has no visible posts.'));
$post_list = id(new PHUIObjectBoxView())
->setHeaderText(pht('Latest Posts'))
->appendChild($post_list);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/'));
$crumbs->addTextCrumb($blog->getName(), $this->getApplicationURI());
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
return $this->newPage()
->setTitle($blog->getName())
->setCrumbs($crumbs)
->appendChild(
array(
$object_box,
$post_list,
));
}
private function renderProperties(
PhameBlog $blog,
PhabricatorUser $viewer,
PhabricatorActionListView $actions) {
require_celerity_resource('aphront-tooltip-css');
Javelin::initBehavior('phabricator-tooltips');
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($blog)
->setActionList($actions);
$properties->addProperty(
pht('Skin'),
$blog->getSkin());
$properties->addProperty(
pht('Domain'),
$blog->getDomain());
$feed_uri = PhabricatorEnv::getProductionURI(
$this->getApplicationURI('blog/feed/'.$blog->getID().'/'));
$properties->addProperty(
pht('Atom URI'),
javelin_tag('a',
array(
'href' => $feed_uri,
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => pht('Atom URI does not support custom domains.'),
'size' => 320,
),
),
$feed_uri));
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$viewer,
$blog);
$properties->addProperty(
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
- $properties->addProperty(
- pht('Joinable By'),
- $descriptions[PhabricatorPolicyCapability::CAN_JOIN]);
-
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->addObject($blog, PhameBlog::MARKUP_FIELD_DESCRIPTION)
->process();
$properties->invokeWillRenderEvent();
if (strlen($blog->getDescription())) {
$description = PhabricatorMarkupEngine::renderOneObject(
id(new PhabricatorMarkupOneOff())->setContent($blog->getDescription()),
'default',
$viewer);
$properties->addSectionHeader(
pht('Description'),
PHUIPropertyListView::ICON_SUMMARY);
$properties->addTextContent($description);
}
return $properties;
}
private function renderActions(PhameBlog $blog, PhabricatorUser $viewer) {
$actions = id(new PhabricatorActionListView())
->setObject($blog)
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$blog,
PhabricatorPolicyCapability::CAN_EDIT);
- $can_join = PhabricatorPolicyFilter::hasCapability(
- $viewer,
- $blog,
- PhabricatorPolicyCapability::CAN_JOIN);
-
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-plus')
->setHref($this->getApplicationURI('post/edit/?blog='.$blog->getID()))
->setName(pht('Write Post'))
- ->setDisabled(!$can_join)
- ->setWorkflow(!$can_join));
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit));
$actions->addAction(
id(new PhabricatorActionView())
->setUser($viewer)
->setIcon('fa-globe')
->setHref($blog->getLiveURI())
->setName(pht('View Live')));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setHref($this->getApplicationURI('blog/edit/'.$blog->getID().'/'))
->setName(pht('Edit Blog'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-times')
->setHref($this->getApplicationURI('blog/delete/'.$blog->getID().'/'))
->setName(pht('Delete Blog'))
->setDisabled(!$can_edit)
->setWorkflow(true));
return $actions;
}
}
diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php
index 99e6df390e..55ce9e176f 100644
--- a/src/applications/phame/controller/post/PhamePostEditController.php
+++ b/src/applications/phame/controller/post/PhamePostEditController.php
@@ -1,232 +1,232 @@
<?php
final class PhamePostEditController extends PhamePostController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if ($id) {
$post = id(new PhamePostQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$cancel_uri = $this->getApplicationURI('/post/view/'.$id.'/');
$submit_button = pht('Save Changes');
$page_title = pht('Edit Post');
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$post->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
$v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$post->getPHID());
} else {
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($request->getInt('blog')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
- PhabricatorPolicyCapability::CAN_JOIN,
+ PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
$v_projects = array();
$v_cc = array();
$post = PhamePost::initializePost($viewer, $blog);
$cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/');
$submit_button = pht('Create Post');
$page_title = pht('Create Post');
}
$title = $post->getTitle();
$phame_title = $post->getPhameTitle();
$body = $post->getBody();
$comments_widget = $post->getCommentsWidget();
$visibility = $post->getVisibility();
$e_title = true;
$e_phame_title = true;
$validation_exception = null;
if ($request->isFormPost()) {
$title = $request->getStr('title');
$phame_title = $request->getStr('phame_title');
$phame_title = PhabricatorSlug::normalize($phame_title);
$body = $request->getStr('body');
$comments_widget = $request->getStr('comments_widget');
$v_projects = $request->getArr('projects');
$v_cc = $request->getArr('cc');
$visibility = $request->getInt('visibility');
$xactions = array(
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_TITLE)
->setNewValue($title),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_PHAME_TITLE)
->setNewValue($phame_title),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_BODY)
->setNewValue($body),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_VISIBILITY)
->setNewValue($visibility),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_COMMENTS_WIDGET)
->setNewValue($comments_widget),
id(new PhamePostTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => $v_cc)),
);
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PhamePostTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $proj_edge_type)
->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new PhamePostEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$editor->applyTransactions($post, $xactions);
$uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
return id(new AphrontRedirectResponse())->setURI($uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_title = $validation_exception->getShortMessage(
PhamePostTransaction::TYPE_TITLE);
$e_phame_title = $validation_exception->getShortMessage(
PhamePostTransaction::TYPE_PHAME_TITLE);
}
}
$handle = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(array($post->getBlogPHID()))
->executeOne();
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('blog', $request->getInt('blog'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Blog'))
->setValue($handle->renderLink()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Title'))
->setName('title')
->setValue($title)
->setID('post-title')
->setError($e_title))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Phame Title'))
->setName('phame_title')
->setValue(rtrim($phame_title, '/'))
->setID('post-phame-title')
->setCaption(pht('Up to 64 alphanumeric characters '.
'with underscores for spaces. '.
'Formatting is enforced.'))
->setError($e_phame_title))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Visibility'))
->setName('visibility')
->setvalue($visibility)
->setOptions(PhameConstants::getPhamePostStatusMap()))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Body'))
->setName('body')
->setValue($body)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setID('post-body')
->setUser($viewer)
->setDisableMacros(true))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('cc')
->setValue($v_cc)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setValue($v_projects)
->setDatasource(new PhabricatorProjectDatasource()))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Comments Widget'))
->setName('comments_widget')
->setvalue($comments_widget)
->setOptions($post->getCommentsWidgetOptionsForSelect()))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($submit_button));
$header = id(new PHUIHeaderView())
->setHeader(pht('%s (Post Preview)', $title));
$container = id(new PHUIBoxView())
->setID('post-preview');
$document = id(new PHUIDocumentViewPro())
->setHeader($header)
->appendChild($container);
$preview_panel = id(new PHUIObjectBoxView())
->appendChild($document);
Javelin::initBehavior(
'phame-post-preview',
array(
'preview' => 'post-preview',
'body' => 'post-body',
'title' => 'post-title',
'phame_title' => 'post-phame-title',
'uri' => '/phame/post/preview/',
));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setValidationException($validation_exception)
->setForm($form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
$page_title,
$this->getApplicationURI('/post/view/'.$id.'/'));
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->appendChild(
array(
$form_box,
$preview_panel,
));
}
}
diff --git a/src/applications/phame/controller/post/PhamePostNewController.php b/src/applications/phame/controller/post/PhamePostNewController.php
index 7098401749..8dd2e0d3c7 100644
--- a/src/applications/phame/controller/post/PhamePostNewController.php
+++ b/src/applications/phame/controller/post/PhamePostNewController.php
@@ -1,120 +1,120 @@
<?php
final class PhamePostNewController extends PhamePostController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$post = null;
$view_uri = null;
if ($id) {
$post = id(new PhamePostQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$view_uri = '/post/view/'.$post->getID().'/';
$view_uri = $this->getApplicationURI($view_uri);
if ($request->isFormPost()) {
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($request->getInt('blog')))
->requireCapabilities(
array(
- PhabricatorPolicyCapability::CAN_JOIN,
+ PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if ($blog) {
$post->setBlogPHID($blog->getPHID());
$post->save();
return id(new AphrontRedirectResponse())->setURI($view_uri);
}
}
$title = pht('Move Post');
} else {
$title = pht('Create Post');
$view_uri = $this->getApplicationURI('/post/new');
}
$blogs = id(new PhameBlogQuery())
->setViewer($viewer)
->requireCapabilities(
array(
- PhabricatorPolicyCapability::CAN_JOIN,
+ PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($title, $view_uri);
$notification = null;
$form_box = null;
if (!$blogs) {
$notification = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NODATA)
->appendChild(
- pht('You do not have permission to join any blogs. Create a blog '.
+ pht('You do not have permission to post to any blogs. Create a blog '.
'first, then you can post to it.'));
} else {
$options = mpull($blogs, 'getName', 'getID');
asort($options);
$selected_value = null;
if ($post && $post->getBlog()) {
$selected_value = $post->getBlog()->getID();
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Blog'))
->setName('blog')
->setOptions($options)
->setValue($selected_value));
if ($post) {
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Move Post'))
->addCancelButton($view_uri));
} else {
$form
->setAction($this->getApplicationURI('post/edit/'))
->setMethod('GET')
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Continue')));
}
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setForm($form);
}
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild(
array(
$notification,
$form_box,
));
}
}
diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php
index 3afdf5401d..ca48af1036 100644
--- a/src/applications/phame/controller/post/PhamePostViewController.php
+++ b/src/applications/phame/controller/post/PhamePostViewController.php
@@ -1,193 +1,195 @@
<?php
final class PhamePostViewController extends PhamePostController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$post = id(new PhamePostQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
$post->getTitle(),
$this->getApplicationURI('post/view/'.$post->getID().'/'));
$crumbs->setBorder(true);
$actions = $this->renderActions($post, $viewer);
$properties = $this->renderProperties($post, $viewer);
$action_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Actions'))
->setHref('#')
->setIconFont('fa-bars')
->addClass('phui-mobile-menu')
->setDropdownMenu($actions);
$header = id(new PHUIHeaderView())
->setHeader($post->getTitle())
->setUser($viewer)
->setPolicyObject($post)
->addActionLink($action_button);
$document = id(new PHUIDocumentViewPro())
->setHeader($header)
->setPropertyList($properties);
if ($post->isDraft()) {
$document->appendChild(
id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setTitle(pht('Draft Post'))
->appendChild(
pht(
'Only you can see this draft until you publish it. '.
'Use "Preview / Publish" to publish this post.')));
}
if (!$post->getBlog()) {
$document->appendChild(
id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
->setTitle(pht('Not On A Blog'))
->appendChild(
pht(
'This post is not associated with a blog (the blog may have '.
'been deleted). Use "Move Post" to move it to a new blog.')));
}
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->addObject($post, PhamePost::MARKUP_FIELD_BODY)
->process();
$document->appendChild(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY)));
return $this->newPage()
->setTitle($post->getTitle())
->addClass('pro-white-background')
->setCrumbs($crumbs)
->appendChild(
array(
$document,
));
}
private function renderActions(
PhamePost $post,
PhabricatorUser $viewer) {
$actions = id(new PhabricatorActionListView())
->setObject($post)
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$post,
PhabricatorPolicyCapability::CAN_EDIT);
$id = $post->getID();
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setHref($this->getApplicationURI('post/edit/'.$id.'/'))
->setName(pht('Edit Post'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-arrows')
->setHref($this->getApplicationURI('post/move/'.$id.'/'))
->setName(pht('Move Post'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
if ($post->isDraft()) {
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-eye')
->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
+ ->setDisabled(!$can_edit)
->setName(pht('Preview / Publish')));
} else {
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-eye-slash')
->setHref($this->getApplicationURI('post/unpublish/'.$id.'/'))
->setName(pht('Unpublish'))
+ ->setDisabled(!$can_edit)
->setWorkflow(true));
}
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-times')
->setHref($this->getApplicationURI('post/delete/'.$id.'/'))
->setName(pht('Delete Post'))
->setDisabled(!$can_edit)
->setWorkflow(true));
$blog = $post->getBlog();
$can_view_live = $blog && !$post->isDraft();
if ($can_view_live) {
$live_uri = $blog->getLiveURI($post);
} else {
$live_uri = 'post/notlive/'.$post->getID().'/';
$live_uri = $this->getApplicationURI($live_uri);
}
$actions->addAction(
id(new PhabricatorActionView())
->setUser($viewer)
->setIcon('fa-globe')
->setHref($live_uri)
->setName(pht('View Live'))
->setDisabled(!$can_view_live)
->setWorkflow(!$can_view_live));
return $actions;
}
private function renderProperties(
PhamePost $post,
PhabricatorUser $viewer) {
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($post);
$properties->addProperty(
pht('Blog'),
$viewer->renderHandle($post->getBlogPHID()));
$properties->addProperty(
pht('Blogger'),
$viewer->renderHandle($post->getBloggerPHID()));
$properties->addProperty(
pht('Published'),
$post->isDraft()
? pht('Draft')
: phabricator_datetime($post->getDatePublished(), $viewer));
$properties->invokeWillRenderEvent();
return $properties;
}
}
diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php
index 7c793aff63..712c4ddd5b 100644
--- a/src/applications/phame/editor/PhameBlogEditor.php
+++ b/src/applications/phame/editor/PhameBlogEditor.php
@@ -1,229 +1,228 @@
<?php
final class PhameBlogEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorPhameApplication';
}
public function getEditorObjectsDescription() {
return pht('Phame Blogs');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhameBlogTransaction::TYPE_NAME;
$types[] = PhameBlogTransaction::TYPE_DESCRIPTION;
$types[] = PhameBlogTransaction::TYPE_DOMAIN;
$types[] = PhameBlogTransaction::TYPE_SKIN;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
- $types[] = PhabricatorTransactions::TYPE_JOIN_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
return $object->getName();
case PhameBlogTransaction::TYPE_DESCRIPTION:
return $object->getDescription();
case PhameBlogTransaction::TYPE_DOMAIN:
return $object->getDomain();
case PhameBlogTransaction::TYPE_SKIN:
return $object->getSkin();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
case PhameBlogTransaction::TYPE_DESCRIPTION:
case PhameBlogTransaction::TYPE_DOMAIN:
case PhameBlogTransaction::TYPE_SKIN:
return $xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
return $object->setName($xaction->getNewValue());
case PhameBlogTransaction::TYPE_DESCRIPTION:
return $object->setDescription($xaction->getNewValue());
case PhameBlogTransaction::TYPE_DOMAIN:
return $object->setDomain($xaction->getNewValue());
case PhameBlogTransaction::TYPE_SKIN:
return $object->setSkin($xaction->getNewValue());
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
case PhameBlogTransaction::TYPE_DESCRIPTION:
case PhameBlogTransaction::TYPE_DOMAIN:
case PhameBlogTransaction::TYPE_SKIN:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhameBlogTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
case PhameBlogTransaction::TYPE_DOMAIN:
if (!$xactions) {
continue;
}
$custom_domain = last($xactions)->getNewValue();
if (empty($custom_domain)) {
continue;
}
list($error_label, $error_text) =
$object->validateCustomDomain($custom_domain);
if ($error_label) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
$error_label,
$error_text,
nonempty(last($xactions), null));
$errors[] = $error;
}
if ($object->getViewPolicy() != PhabricatorPolicies::POLICY_PUBLIC) {
$error_text = pht(
'For custom domains to work, the blog must have a view policy of '.
'public.');
$error = new PhabricatorApplicationTransactionValidationError(
PhabricatorTransactions::TYPE_VIEW_POLICY,
pht('Invalid Policy'),
$error_text,
nonempty(last($xactions), null));
$errors[] = $error;
}
$duplicate_blog = id(new PhameBlogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withDomain($custom_domain)
->executeOne();
if ($duplicate_blog && $duplicate_blog->getID() != $object->getID()) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Unique'),
pht('Domain must be unique; another blog already has this domain.'),
nonempty(last($xactions), null));
$errors[] = $error;
}
break;
}
return $errors;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $this->requireActor()->getPHID();
$phids[] = $object->getCreatorPHID();
return $phids;
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$phid = $object->getPHID();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject($name)
->addHeader('Thread-Topic', $phid);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhameBlogReplyHandler())
->setMailReceiver($object);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('BLOG DETAIL'),
PhabricatorEnv::getProductionURI($object->getViewURI()));
return $body;
}
public function getMailTagsMap() {
return array(
PhameBlogTransaction::MAILTAG_DETAILS =>
pht("A blog's details change."),
PhameBlogTransaction::MAILTAG_SUBSCRIBERS =>
pht("A blog's subscribers change."),
PhameBlogTransaction::MAILTAG_OTHER =>
pht('Other blog activity not listed above occurs.'),
);
}
protected function getMailSubjectPrefix() {
return '[Phame]';
}
protected function supportsSearch() {
return false;
}
}
diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php
index fa9828e5f2..3082592a93 100644
--- a/src/applications/phame/storage/PhameBlog.php
+++ b/src/applications/phame/storage/PhameBlog.php
@@ -1,364 +1,345 @@
<?php
final class PhameBlog extends PhameDAO
implements
PhabricatorPolicyInterface,
PhabricatorMarkupInterface,
PhabricatorSubscribableInterface,
PhabricatorFlaggableInterface,
PhabricatorProjectInterface,
PhabricatorApplicationTransactionInterface {
const MARKUP_FIELD_DESCRIPTION = 'markup:description';
const SKIN_DEFAULT = 'oblivious';
protected $name;
protected $description;
protected $domain;
protected $configData;
protected $creatorPHID;
protected $viewPolicy;
protected $editPolicy;
- protected $joinPolicy;
protected $mailKey;
private static $requestBlog;
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'configData' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text64',
'description' => 'text',
'domain' => 'text128?',
'mailKey' => 'bytes20',
// T6203/NULLABILITY
// These policies should always be non-null.
- 'joinPolicy' => 'policy?',
'editPolicy' => 'policy?',
'viewPolicy' => 'policy?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
'domain' => array(
'columns' => array('domain'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPhameBlogPHIDType::TYPECONST);
}
public static function initializeNewBlog(PhabricatorUser $actor) {
$blog = id(new PhameBlog())
->setCreatorPHID($actor->getPHID())
->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy())
- ->setEditPolicy(PhabricatorPolicies::POLICY_USER)
- ->setJoinPolicy(PhabricatorPolicies::POLICY_USER);
+ ->setEditPolicy(PhabricatorPolicies::POLICY_USER);
return $blog;
}
public function getSkinRenderer(AphrontRequest $request) {
$spec = PhameSkinSpecification::loadOneSkinSpecification(
$this->getSkin());
if (!$spec) {
$spec = PhameSkinSpecification::loadOneSkinSpecification(
self::SKIN_DEFAULT);
}
if (!$spec) {
throw new Exception(
pht(
'This blog has an invalid skin, and the default skin failed to '.
'load.'));
}
$skin = newv($spec->getSkinClass(), array());
$skin->setRequest($request);
$skin->setSpecification($spec);
return $skin;
}
/**
* Makes sure a given custom blog uri is properly configured in DNS
* to point at this Phabricator instance. If there is an error in
* the configuration, return a string describing the error and how
* to fix it. If there is no error, return an empty string.
*
* @return string
*/
public function validateCustomDomain($custom_domain) {
$example_domain = 'blog.example.com';
$label = pht('Invalid');
// note this "uri" should be pretty busted given the desired input
// so just use it to test if there's a protocol specified
$uri = new PhutilURI($custom_domain);
if ($uri->getProtocol()) {
return array(
$label,
pht(
'The custom domain should not include a protocol. Just provide '.
'the bare domain name (for example, "%s").',
$example_domain),
);
}
if ($uri->getPort()) {
return array(
$label,
pht(
'The custom domain should not include a port number. Just provide '.
'the bare domain name (for example, "%s").',
$example_domain),
);
}
if (strpos($custom_domain, '/') !== false) {
return array(
$label,
pht(
'The custom domain should not specify a path (hosting a Phame '.
'blog at a path is currently not supported). Instead, just provide '.
'the bare domain name (for example, "%s").',
$example_domain),
);
}
if (strpos($custom_domain, '.') === false) {
return array(
$label,
pht(
'The custom domain should contain at least one dot (.) because '.
'some browsers fail to set cookies on domains without a dot. '.
'Instead, use a normal looking domain name like "%s".',
$example_domain),
);
}
if (!PhabricatorEnv::getEnvConfig('policy.allow-public')) {
$href = PhabricatorEnv::getProductionURI(
'/config/edit/policy.allow-public/');
return array(
pht('Fix Configuration'),
pht(
'For custom domains to work, this Phabricator instance must be '.
'configured to allow the public access policy. Configure this '.
'setting %s, or ask an administrator to configure this setting. '.
'The domain can be specified later once this setting has been '.
'changed.',
phutil_tag(
'a',
array('href' => $href),
pht('here'))),
);
}
return null;
}
public function getSkin() {
$config = coalesce($this->getConfigData(), array());
return idx($config, 'skin', self::SKIN_DEFAULT);
}
public function setSkin($skin) {
$config = coalesce($this->getConfigData(), array());
$config['skin'] = $skin;
return $this->setConfigData($config);
}
public static function getSkinOptionsForSelect() {
$classes = id(new PhutilSymbolLoader())
->setAncestorClass('PhameBlogSkin')
->setType('class')
->setConcreteOnly(true)
->selectSymbolsWithoutLoading();
return ipull($classes, 'name', 'name');
}
public static function setRequestBlog(PhameBlog $blog) {
self::$requestBlog = $blog;
}
public static function getRequestBlog() {
return self::$requestBlog;
}
public function getLiveURI(PhamePost $post = null) {
if ($this->getDomain()) {
$base = new PhutilURI('http://'.$this->getDomain().'/');
} else {
$base = '/phame/live/'.$this->getID().'/';
$base = PhabricatorEnv::getURI($base);
}
if ($post) {
$base .= '/post/'.$post->getPhameTitle();
}
return $base;
}
public function getViewURI() {
$uri = '/phame/blog/view/'.$this->getID().'/';
return PhabricatorEnv::getProductionURI($uri);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
- PhabricatorPolicyCapability::CAN_JOIN,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
- case PhabricatorPolicyCapability::CAN_JOIN:
- return $this->getJoinPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
$can_edit = PhabricatorPolicyCapability::CAN_EDIT;
- $can_join = PhabricatorPolicyCapability::CAN_JOIN;
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
// Users who can edit or post to a blog can always view it.
if (PhabricatorPolicyFilter::hasCapability($user, $this, $can_edit)) {
return true;
}
- if (PhabricatorPolicyFilter::hasCapability($user, $this, $can_join)) {
- return true;
- }
- break;
- case PhabricatorPolicyCapability::CAN_JOIN:
- // Users who can edit a blog can always post to it.
- if (PhabricatorPolicyFilter::hasCapability($user, $this, $can_edit)) {
- return true;
- }
break;
}
return false;
}
public function describeAutomaticCapability($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return pht(
- 'Users who can edit or post on a blog can always view it.');
- case PhabricatorPolicyCapability::CAN_JOIN:
- return pht(
- 'Users who can edit a blog can always post on it.');
+ 'Users who can edit a blog can always view it.');
}
return null;
}
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */
public function getMarkupFieldKey($field) {
$hash = PhabricatorHash::digest($this->getMarkupText($field));
return $this->getPHID().':'.$field.':'.$hash;
}
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newPhameMarkupEngine();
}
public function getMarkupText($field) {
return $this->getDescription();
}
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
return $output;
}
public function shouldUseMarkupCache($field) {
return (bool)$this->getPHID();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhameBlogEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhameBlogTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
public function isAutomaticallySubscribed($phid) {
return ($this->creatorPHID == $phid);
}
public function shouldShowSubscribersProperty() {
return true;
}
public function shouldAllowSubscription($phid) {
return true;
}
}
diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php
index ef39d20544..76681f2f57 100644
--- a/src/applications/phame/storage/PhamePost.php
+++ b/src/applications/phame/storage/PhamePost.php
@@ -1,307 +1,310 @@
<?php
final class PhamePost extends PhameDAO
implements
PhabricatorPolicyInterface,
PhabricatorMarkupInterface,
PhabricatorFlaggableInterface,
PhabricatorProjectInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorSubscribableInterface,
PhabricatorTokenReceiverInterface {
const MARKUP_FIELD_BODY = 'markup:body';
const MARKUP_FIELD_SUMMARY = 'markup:summary';
protected $bloggerPHID;
protected $title;
protected $phameTitle;
protected $body;
protected $visibility;
protected $configData;
protected $datePublished;
protected $blogPHID;
protected $mailKey;
private $blog;
public static function initializePost(
PhabricatorUser $blogger,
PhameBlog $blog) {
$post = id(new PhamePost())
->setBloggerPHID($blogger->getPHID())
->setBlogPHID($blog->getPHID())
->setBlog($blog)
->setDatePublished(0)
->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
return $post;
}
public function setBlog(PhameBlog $blog) {
$this->blog = $blog;
return $this;
}
public function getBlog() {
return $this->blog;
}
public function getViewURI() {
// go for the pretty uri if we can
$domain = ($this->blog ? $this->blog->getDomain() : '');
if ($domain) {
$phame_title = PhabricatorSlug::normalize($this->getPhameTitle());
return 'http://'.$domain.'/post/'.$phame_title;
}
$uri = '/phame/post/view/'.$this->getID().'/';
return PhabricatorEnv::getProductionURI($uri);
}
public function getEditURI() {
return '/phame/post/edit/'.$this->getID().'/';
}
public function isDraft() {
return $this->getVisibility() == PhameConstants::VISIBILITY_DRAFT;
}
public function getHumanName() {
if ($this->isDraft()) {
$name = 'draft';
} else {
$name = 'post';
}
return $name;
}
public function setCommentsWidget($widget) {
$config_data = $this->getConfigData();
$config_data['comments_widget'] = $widget;
return $this;
}
public function getCommentsWidget() {
$config_data = $this->getConfigData();
if (empty($config_data)) {
return 'none';
}
return idx($config_data, 'comments_widget', 'none');
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'configData' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'title' => 'text255',
'phameTitle' => 'sort64',
'visibility' => 'uint32',
'mailKey' => 'bytes20',
// T6203/NULLABILITY
// These seem like they should always be non-null?
'blogPHID' => 'phid?',
'body' => 'text?',
'configData' => 'text?',
// T6203/NULLABILITY
// This one probably should be nullable?
'datePublished' => 'epoch',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
'phameTitle' => array(
'columns' => array('bloggerPHID', 'phameTitle'),
'unique' => true,
),
'bloggerPosts' => array(
'columns' => array(
'bloggerPHID',
'visibility',
'datePublished',
'id',
),
),
),
) + parent::getConfiguration();
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPhamePostPHIDType::TYPECONST);
}
public function toDictionary() {
return array(
'id' => $this->getID(),
'phid' => $this->getPHID(),
'blogPHID' => $this->getBlogPHID(),
'bloggerPHID' => $this->getBloggerPHID(),
'viewURI' => $this->getViewURI(),
'title' => $this->getTitle(),
'phameTitle' => $this->getPhameTitle(),
'body' => $this->getBody(),
'summary' => PhabricatorMarkupEngine::summarize($this->getBody()),
'datePublished' => $this->getDatePublished(),
'published' => !$this->isDraft(),
);
}
public function getCommentsWidgetOptionsForSelect() {
$current = $this->getCommentsWidget();
$options = array();
if ($current == 'facebook' ||
PhabricatorFacebookAuthProvider::getFacebookApplicationID()) {
$options['facebook'] = pht('Facebook');
}
if ($current == 'disqus' ||
PhabricatorEnv::getEnvConfig('disqus.shortname')) {
$options['disqus'] = pht('Disqus');
}
$options['none'] = pht('None');
return $options;
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
// Draft posts are visible only to the author. Published posts are visible
// to whoever the blog is visible to.
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
if (!$this->isDraft() && $this->getBlog()) {
return $this->getBlog()->getViewPolicy();
- } else {
- return PhabricatorPolicies::POLICY_NOONE;
+ } else if ($this->getBlog()) {
+ return $this->getBlog()->getEditPolicy();
}
break;
case PhabricatorPolicyCapability::CAN_EDIT:
- return PhabricatorPolicies::POLICY_NOONE;
+ if ($this->getBlog()) {
+ return $this->getBlog()->getEditPolicy();
+ } else {
+ return PhabricatorPolicies::POLICY_NOONE;
+ }
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
- // A blog post's author can always view it, and is the only user allowed
- // to edit it.
+ // A blog post's author can always view it.
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
case PhabricatorPolicyCapability::CAN_EDIT:
return ($user->getPHID() == $this->getBloggerPHID());
}
}
public function describeAutomaticCapability($capability) {
return pht('The author of a blog post can always view and edit it.');
}
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */
public function getMarkupFieldKey($field) {
$hash = PhabricatorHash::digest($this->getMarkupText($field));
return $this->getPHID().':'.$field.':'.$hash;
}
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newPhameMarkupEngine();
}
public function getMarkupText($field) {
switch ($field) {
case self::MARKUP_FIELD_BODY:
return $this->getBody();
case self::MARKUP_FIELD_SUMMARY:
return PhabricatorMarkupEngine::summarize($this->getBody());
}
}
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
return $output;
}
public function shouldUseMarkupCache($field) {
return (bool)$this->getPHID();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhamePostEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhamePostTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array(
$this->getBloggerPHID(),
);
}
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
public function isAutomaticallySubscribed($phid) {
return ($this->bloggerPHID == $phid);
}
public function shouldShowSubscribersProperty() {
return true;
}
public function shouldAllowSubscription($phid) {
return true;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 11, 8:23 PM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
143212
Default Alt Text
(61 KB)

Event Timeline