mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Mostly modernize post edit/detail UIs
Summary: Still some big chunks left but this moves us a bit closer to getting everything device-ready. Stuff not addressed here but which I'm planning to do soon: - Posts don't have a live URI yet. - Post detail pages don't actually show the post content. I'm going to tweak PhabricatorObjectPropertyListView for this since we need it some other places. - Some of the hinting about use/states is gone (e.g., "This post is a draft, publish it to make it live to the world."); I'm planning to restore it. - Left nav is still a bit of a mess with states/highlighting. Major changes are: - If you click "New Post" you get a screen asking you to pick a blog to post to. - "Publish/Preview" and Unpublish are now separate actions from the post detail screen. - "Publish/Preview" renders a preview of the post in an iframe and gives you a "Publish" button. Test Plan: Will attach screenshots. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1373 Differential Revision: https://secure.phabricator.com/D3697
This commit is contained in:
parent
c37202dd48
commit
0e07ef8d56
14 changed files with 520 additions and 340 deletions
|
@ -1162,10 +1162,14 @@ phutil_register_library_map(array(
|
|||
'PhamePostDeleteController' => 'applications/phame/controller/post/PhamePostDeleteController.php',
|
||||
'PhamePostDetailView' => 'applications/phame/view/PhamePostDetailView.php',
|
||||
'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php',
|
||||
'PhamePostFramedController' => 'applications/phame/controller/post/PhamePostFramedController.php',
|
||||
'PhamePostListController' => 'applications/phame/controller/post/PhamePostListController.php',
|
||||
'PhamePostListView' => 'applications/phame/view/PhamePostListView.php',
|
||||
'PhamePostNewController' => 'applications/phame/controller/post/PhamePostNewController.php',
|
||||
'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php',
|
||||
'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php',
|
||||
'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php',
|
||||
'PhamePostUnpublishController' => 'applications/phame/controller/post/PhamePostUnpublishController.php',
|
||||
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
|
||||
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
|
||||
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php',
|
||||
|
@ -2291,10 +2295,14 @@ phutil_register_library_map(array(
|
|||
'PhamePostDeleteController' => 'PhameController',
|
||||
'PhamePostDetailView' => 'AphrontView',
|
||||
'PhamePostEditController' => 'PhameController',
|
||||
'PhamePostFramedController' => 'PhameController',
|
||||
'PhamePostListController' => 'PhameController',
|
||||
'PhamePostListView' => 'AphrontView',
|
||||
'PhamePostNewController' => 'PhameController',
|
||||
'PhamePostPreviewController' => 'PhameController',
|
||||
'PhamePostPublishController' => 'PhameController',
|
||||
'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhamePostUnpublishController' => 'PhameController',
|
||||
'PhamePostViewController' => 'PhameController',
|
||||
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
|
||||
'PhortuneStripeBaseController' => 'PhabricatorController',
|
||||
|
|
|
@ -49,11 +49,14 @@ final class PhabricatorApplicationPhame extends PhabricatorApplication {
|
|||
'post/' => array(
|
||||
'(?:(?P<filter>draft|all)/)?' => 'PhamePostListController',
|
||||
'blogger/(?P<bloggername>[\w\.-_]+)/' => 'PhamePostListController',
|
||||
'delete/(?P<phid>[^/]+)/' => 'PhamePostDeleteController',
|
||||
'edit/(?P<phid>[^/]+)/' => 'PhamePostEditController',
|
||||
'new/' => 'PhamePostEditController',
|
||||
'delete/(?P<id>[^/]+)/' => 'PhamePostDeleteController',
|
||||
'edit/(?:(?P<id>[^/]+)/)?' => 'PhamePostEditController',
|
||||
'view/(?P<id>\d+)/' => 'PhamePostViewController',
|
||||
'publish/(?P<id>\d+)/' => 'PhamePostPublishController',
|
||||
'unpublish/(?P<id>\d+)/' => 'PhamePostUnpublishController',
|
||||
'preview/' => 'PhamePostPreviewController',
|
||||
'view/(?P<phid>[^/]+)/' => 'PhamePostViewController',
|
||||
'framed/(?P<id>\d+)/' => 'PhamePostFramedController',
|
||||
'new/' => 'PhamePostNewController',
|
||||
),
|
||||
'blog/' => array(
|
||||
'(?:(?P<filter>user|all)/)?' => 'PhameBlogListController',
|
||||
|
|
|
@ -76,7 +76,7 @@ abstract class PhameController extends PhabricatorController {
|
|||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI($base_uri);
|
||||
$nav->addLabel('Create');
|
||||
$nav->addFilter('post/new', 'New Draft');
|
||||
$nav->addFilter('post/new', 'New Post');
|
||||
$nav->addFilter('blog/new', 'New Blog');
|
||||
|
||||
$nav->addSpacer();
|
||||
|
@ -164,7 +164,7 @@ abstract class PhameController extends PhabricatorController {
|
|||
foreach ($posts as $post) {
|
||||
$item = id(new PhabricatorObjectItemView())
|
||||
->setHeader($post->getTitle())
|
||||
->setHref($this->getApplicationURI('post/view/'.$post->getPHID()))
|
||||
->setHref($this->getApplicationURI('post/view/'.$post->getID().'/'))
|
||||
->addDetail(
|
||||
pht('Blogger'),
|
||||
$this->getHandle($post->getBloggerPHID())->renderLink())
|
||||
|
|
|
@ -23,20 +23,6 @@ final class PhameBlogDeleteController extends PhameController {
|
|||
|
||||
private $id;
|
||||
|
||||
|
||||
protected function getSideNavFilter() {
|
||||
return 'blog/delete/'.$this->getBlogPHID();
|
||||
}
|
||||
|
||||
protected function getSideNavExtraBlogFilters() {
|
||||
$filters = array(
|
||||
array('key' => $this->getSideNavFilter(),
|
||||
'name' => 'Delete Blog')
|
||||
);
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
@ -67,11 +53,11 @@ final class PhameBlogDeleteController extends PhameController {
|
|||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($user)
|
||||
->setTitle(pht('Delete blog?'))
|
||||
->setTitle(pht('Delete Blog?'))
|
||||
->appendChild(
|
||||
pht(
|
||||
'Really delete the blog "%s"? It will be gone forever.',
|
||||
$blog->getName()))
|
||||
phutil_escape_html($blog->getName())))
|
||||
->addSubmitButton(pht('Delete'))
|
||||
->addCancelButton($cancel_uri);
|
||||
|
||||
|
|
|
@ -24,11 +24,6 @@ final class PhameBlogEditController
|
|||
|
||||
private $id;
|
||||
|
||||
protected function getSideNavFilter() {
|
||||
return 'blog/edit/'.$this->id;
|
||||
}
|
||||
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = idx($data, 'id');
|
||||
}
|
||||
|
|
|
@ -23,19 +23,6 @@ final class PhameBlogViewController extends PhameController {
|
|||
|
||||
private $id;
|
||||
|
||||
protected function getSideNavFilter() {
|
||||
$filter = 'blog/view/'.$this->getBlogPHID();
|
||||
return $filter;
|
||||
}
|
||||
|
||||
protected function getSideNavExtraBlogFilters() {
|
||||
$filters = array(
|
||||
array('key' => $this->getSideNavFilter(),
|
||||
'name' => $this->getPhameTitle())
|
||||
);
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
|
|
@ -19,31 +19,21 @@
|
|||
/**
|
||||
* @group phame
|
||||
*/
|
||||
final class PhamePostDeleteController
|
||||
extends PhameController {
|
||||
final class PhamePostDeleteController extends PhameController {
|
||||
|
||||
private $phid;
|
||||
|
||||
private function setPostPHID($phid) {
|
||||
$this->phid = $phid;
|
||||
return $this;
|
||||
}
|
||||
private function getPostPHID() {
|
||||
return $this->phid;
|
||||
}
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$phid = $data['phid'];
|
||||
$this->setPostPHID($phid);
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withPHIDs(array($this->getPostPHID()))
|
||||
->withIDs(array($this->id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
|
@ -52,37 +42,24 @@ extends PhameController {
|
|||
if (!$post) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$post_noun = $post->getHumanName();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$edge_type = PhabricatorEdgeConfig::TYPE_POST_HAS_BLOG;
|
||||
$edges = id(new PhabricatorEdgeQuery())
|
||||
->withSourcePHIDs(array($post->getPHID()))
|
||||
->withEdgeTypes(array($edge_type))
|
||||
->execute();
|
||||
|
||||
$blog_edges = $edges[$post->getPHID()][$edge_type];
|
||||
$blog_phids = array_keys($blog_edges);
|
||||
$editor = id(new PhabricatorEdgeEditor())
|
||||
->setActor($user);
|
||||
foreach ($blog_phids as $phid) {
|
||||
$editor->removeEdge($post->getPHID(), $edge_type, $phid);
|
||||
}
|
||||
$editor->save();
|
||||
|
||||
$post->delete();
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI('/phame/'.$post_noun.'/?deleted');
|
||||
->setURI('/phame/post/');
|
||||
}
|
||||
|
||||
$edit_uri = $post->getEditURI();
|
||||
$dialog = id(new AphrontDialogView())
|
||||
$cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($user)
|
||||
->setTitle('Delete '.$post_noun.'?')
|
||||
->appendChild('Really delete this '.$post_noun.'? '.
|
||||
'It will be gone forever.')
|
||||
->addSubmitButton('Delete')
|
||||
->addCancelButton($edit_uri);
|
||||
->setTitle(pht('Delete Post?'))
|
||||
->appendChild(
|
||||
pht(
|
||||
'Really delete the post "%s"? It will be gone forever.',
|
||||
phutil_escape_html($post->getTitle())))
|
||||
->addSubmitButton(pht('Delete'))
|
||||
->addCancelButton($cancel_uri);
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
|
|
|
@ -22,102 +22,20 @@
|
|||
final class PhamePostEditController
|
||||
extends PhameController {
|
||||
|
||||
private $phid;
|
||||
private $isPostEdit;
|
||||
private $userBlogs;
|
||||
private $postBlogs;
|
||||
private $post;
|
||||
|
||||
private function setPost(PhamePost $post) {
|
||||
$this->post = $post;
|
||||
return $this;
|
||||
}
|
||||
private function getPost() {
|
||||
return $this->post;
|
||||
}
|
||||
|
||||
private function setPostPHID($phid) {
|
||||
$this->phid = $phid;
|
||||
return $this;
|
||||
}
|
||||
private function getPostPHID() {
|
||||
return $this->phid;
|
||||
}
|
||||
private function setIsPostEdit($is_post_edit) {
|
||||
$this->isPostEdit = $is_post_edit;
|
||||
return $this;
|
||||
}
|
||||
private function isPostEdit() {
|
||||
return $this->isPostEdit;
|
||||
}
|
||||
private function setUserBlogs(array $blogs) {
|
||||
assert_instances_of($blogs, 'PhameBlog');
|
||||
$this->userBlogs = $blogs;
|
||||
return $this;
|
||||
}
|
||||
private function getUserBlogs() {
|
||||
return $this->userBlogs;
|
||||
}
|
||||
private function setPostBlogs(array $blogs) {
|
||||
assert_instances_of($blogs, 'PhameBlog');
|
||||
$this->postBlogs = $blogs;
|
||||
return $this;
|
||||
}
|
||||
private function getPostBlogs() {
|
||||
return $this->postBlogs;
|
||||
}
|
||||
|
||||
protected function getSideNavFilter() {
|
||||
if ($this->isPostEdit()) {
|
||||
$post_noun = $this->getPost()->getHumanName();
|
||||
$filter = $post_noun.'/edit/'.$this->getPostPHID();
|
||||
} else {
|
||||
$filter = 'post/new';
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
protected function getSideNavExtraPostFilters() {
|
||||
if ($this->isPostEdit() && !$this->getPost()->isDraft()) {
|
||||
$filters = array(
|
||||
array('key' => 'post/edit/'.$this->getPostPHID(),
|
||||
'name' => 'Edit Post')
|
||||
);
|
||||
} else {
|
||||
$filters = array();
|
||||
}
|
||||
|
||||
return $filters;
|
||||
}
|
||||
protected function getSideNavExtraDraftFilters() {
|
||||
if ($this->isPostEdit() && $this->getPost()->isDraft()) {
|
||||
$filters = array(
|
||||
array('key' => 'draft/edit/'.$this->getPostPHID(),
|
||||
'name' => 'Edit Draft')
|
||||
);
|
||||
} else {
|
||||
$filters = array();
|
||||
}
|
||||
|
||||
return $filters;
|
||||
}
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$phid = idx($data, 'phid');
|
||||
$this->setPostPHID($phid);
|
||||
$this->setIsPostEdit((bool) $phid);
|
||||
$this->id = idx($data, 'id');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$e_phame_title = null;
|
||||
$e_title = null;
|
||||
$errors = array();
|
||||
|
||||
if ($this->isPostEdit()) {
|
||||
if ($this->id) {
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withPHIDs(array($this->getPostPHID()))
|
||||
->withIDs(array($this->id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
|
@ -127,45 +45,35 @@ final class PhamePostEditController
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$post_noun = ucfirst($post->getHumanName());
|
||||
$cancel_uri = $post->getViewURI($user->getUsername());
|
||||
$submit_button = 'Save Changes';
|
||||
$delete_button = javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $post->getDeleteURI(),
|
||||
'class' => 'grey button',
|
||||
'sigil' => 'workflow',
|
||||
),
|
||||
'Delete '.$post_noun);
|
||||
$page_title = 'Edit '.$post_noun;
|
||||
$cancel_uri = $this->getApplicationURI('/post/view/'.$this->id.'/');
|
||||
$submit_button = pht('Save Changes');
|
||||
$page_title = pht('Edit Post');
|
||||
} else {
|
||||
$blog = id(new PhameBlogQuery())
|
||||
->setViewer($user)
|
||||
->withIDs(array($request->getInt('blog')))
|
||||
->executeOne();
|
||||
|
||||
if (!$blog) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$post = id(new PhamePost())
|
||||
->setBloggerPHID($user->getPHID())
|
||||
->setBlog($blog)
|
||||
->setBlogPHID($blog->getPHID())
|
||||
->setBlog($blog)
|
||||
->setDatePublished(0)
|
||||
->setVisibility(PhamePost::VISIBILITY_DRAFT);
|
||||
$cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/');
|
||||
|
||||
$submit_button = pht('Create Draft');
|
||||
$delete_button = null;
|
||||
$page_title = pht('Create Draft');
|
||||
$submit_button = pht('Save Draft');
|
||||
$page_title = pht('Create Post');
|
||||
}
|
||||
|
||||
$this->setPost($post);
|
||||
$e_phame_title = null;
|
||||
$e_title = true;
|
||||
$errors = array();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$saved = true;
|
||||
$visibility = $request->getInt('visibility');
|
||||
$comments = $request->getStr('comments_widget');
|
||||
$data = array('comments_widget' => $comments);
|
||||
$phame_title = $request->getStr('phame_title');
|
||||
|
@ -174,34 +82,26 @@ final class PhamePostEditController
|
|||
$post->setTitle($title);
|
||||
$post->setPhameTitle($phame_title);
|
||||
$post->setBody($request->getStr('body'));
|
||||
$post->setVisibility($visibility);
|
||||
$post->setConfigData($data);
|
||||
// only publish once...!
|
||||
if ($visibility == PhamePost::VISIBILITY_PUBLISHED) {
|
||||
if (!$post->getDatePublished()) {
|
||||
$post->setDatePublished(time());
|
||||
}
|
||||
// this is basically a cast of null to 0 if its a new post
|
||||
} else if (!$post->getDatePublished()) {
|
||||
$post->setDatePublished(0);
|
||||
}
|
||||
|
||||
if ($phame_title == '/') {
|
||||
$errors[] = 'Phame title must be nonempty.';
|
||||
$e_phame_title = 'Required';
|
||||
}
|
||||
if (empty($title)) {
|
||||
|
||||
if (!strlen($title)) {
|
||||
$errors[] = 'Title must be nonempty.';
|
||||
$e_title = 'Required';
|
||||
} else {
|
||||
$e_title = null;
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
try {
|
||||
$post->save();
|
||||
|
||||
$uri = new PhutilURI($post->getViewURI($user->getUsername()));
|
||||
$uri->setQueryParam('saved', true);
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($uri);
|
||||
$uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
|
||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||
} catch (AphrontQueryDuplicateKeyException $e) {
|
||||
$e_phame_title = 'Not Unique';
|
||||
$errors[] = 'Another post already uses this slug. '.
|
||||
|
@ -210,19 +110,14 @@ final class PhamePostEditController
|
|||
}
|
||||
}
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader($page_title);
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_FULL);
|
||||
if ($delete_button) {
|
||||
$panel->addButton($delete_button);
|
||||
}
|
||||
|
||||
$handle = PhabricatorObjectHandleData::loadOneHandle(
|
||||
$post->getBlogPHID(),
|
||||
$user);
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setFlexible(true)
|
||||
->addHiddenInput('blog', $request->getInt('blog'))
|
||||
->appendChild(
|
||||
id(new AphrontFormMarkupControl())
|
||||
->setLabel('Blog')
|
||||
|
@ -254,14 +149,6 @@ final class PhamePostEditController
|
|||
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
|
||||
->setID('post-body')
|
||||
)
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel('Visibility')
|
||||
->setName('visibility')
|
||||
->setValue($post->getVisibility())
|
||||
->setOptions(PhamePost::getVisibilityOptionsForSelect())
|
||||
->setID('post-visibility')
|
||||
)
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel('Comments Widget')
|
||||
|
@ -275,10 +162,8 @@ final class PhamePostEditController
|
|||
->setValue($submit_button)
|
||||
);
|
||||
|
||||
$panel->appendChild($form);
|
||||
|
||||
$preview_panel =
|
||||
'<div class="aphront-panel-preview ">
|
||||
'<div class="aphront-panel-preview">
|
||||
<div class="phame-post-preview-header">
|
||||
Post Preview
|
||||
</div>
|
||||
|
@ -300,6 +185,8 @@ final class PhamePostEditController
|
|||
'uri' => '/phame/post/preview/',
|
||||
));
|
||||
|
||||
$header = id(new PhabricatorHeaderView())->setHeader($page_title);
|
||||
|
||||
if ($errors) {
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle('Errors saving post.')
|
||||
|
@ -308,15 +195,20 @@ final class PhamePostEditController
|
|||
$error_view = null;
|
||||
}
|
||||
|
||||
$this->setShowSideNav(true);
|
||||
return $this->buildStandardPageResponse(
|
||||
$nav = $this->renderSideNavFilterView(null);
|
||||
$nav->appendChild(
|
||||
array(
|
||||
$header,
|
||||
$error_view,
|
||||
$panel,
|
||||
$form,
|
||||
$preview_panel,
|
||||
),
|
||||
));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => $page_title,
|
||||
'device' => true,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group phame
|
||||
*/
|
||||
final class PhamePostFramedController extends PhameController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withIDs(array($this->id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$post) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$skin = $post->getBlog()->getSkinRenderer();
|
||||
|
||||
$handles = $this->loadViewerHandles(
|
||||
array(
|
||||
$post->getBloggerPHID(),
|
||||
));
|
||||
|
||||
$skin
|
||||
->setUser($user)
|
||||
->setBlog($post->getBlog())
|
||||
->setPosts(array($post))
|
||||
->setBloggers($handles)
|
||||
->setRequestURI($this->getRequest()->getRequestURI());
|
||||
|
||||
$page = $this->buildStandardPageView();
|
||||
$page->setFrameable(true);
|
||||
$page->setShowChrome(false);
|
||||
$page->appendChild($skin);
|
||||
|
||||
$response = new AphrontWebpageResponse();
|
||||
$response->setFrameable(true);
|
||||
$response->setContent($page->render());
|
||||
return $response;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group phame
|
||||
*/
|
||||
final class PhamePostNewController extends PhameController {
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$blogs = id(new PhameBlogQuery())
|
||||
->setViewer($user)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_JOIN,
|
||||
))
|
||||
->execute();
|
||||
|
||||
$nav = $this->renderSideNavFilterView(null);
|
||||
$nav->appendChild(
|
||||
id(new PhabricatorHeaderView())->setHeader(
|
||||
pht('Create Post')));
|
||||
|
||||
if (!$blogs) {
|
||||
|
||||
} else {
|
||||
$options = mpull($blogs, 'getName', 'getID');
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setMethod('GET')
|
||||
->setFlexible(true)
|
||||
->setAction($this->getApplicationURI('post/edit/'))
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel('Blog')
|
||||
->setName('blog')
|
||||
->setOptions($options))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Continue'));
|
||||
|
||||
$nav->appendChild($form);
|
||||
}
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => 'Create Post',
|
||||
'device' => true,
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group phame
|
||||
*/
|
||||
final class PhamePostPublishController extends PhameController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withIDs(array($this->id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$post) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$view_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$post->setVisibility(PhamePost::VISIBILITY_PUBLISHED);
|
||||
$post->setDatePublished(time());
|
||||
$post->save();
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($view_uri);
|
||||
}
|
||||
|
||||
$header = id(new PhabricatorHeaderView())
|
||||
->setHeader('Preview Post');
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setFlexible(true)
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue(pht('Publish Post'))
|
||||
->addCancelButton($view_uri));
|
||||
|
||||
$frame = $this->renderPreviewFrame($post);
|
||||
|
||||
$nav = $this->renderSideNavFilterView(null);
|
||||
$nav->appendChild(
|
||||
array(
|
||||
$header,
|
||||
$form,
|
||||
$frame,
|
||||
));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => pht('Preview Post'),
|
||||
'device' => true,
|
||||
));
|
||||
}
|
||||
|
||||
private function renderPreviewFrame(PhamePost $post) {
|
||||
|
||||
// TODO: Clean up this CSS.
|
||||
|
||||
return phutil_render_tag(
|
||||
'div',
|
||||
array(
|
||||
'style' => 'text-align: center; padding: 1em;',
|
||||
),
|
||||
phutil_render_tag(
|
||||
'iframe',
|
||||
array(
|
||||
'style' => 'width: 100%; height: 600px; '.
|
||||
'border: 1px solid #303030; background: #303030;',
|
||||
'src' => $this->getApplicationURI('/post/framed/'.$post->getID().'/'),
|
||||
),
|
||||
''));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group phame
|
||||
*/
|
||||
final class PhamePostUnpublishController extends PhameController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withIDs(array($this->id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$post) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$post->setVisibility(PhamePost::VISIBILITY_DRAFT);
|
||||
$post->setDatePublished(0);
|
||||
$post->save();
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($this->getApplicationURI('/post/view/'.$post->getID().'/'));
|
||||
}
|
||||
|
||||
$cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($user)
|
||||
->setTitle(pht('Unpublish Post?'))
|
||||
->appendChild(
|
||||
pht(
|
||||
'The post "%s" will no longer be visible to other users until you '.
|
||||
'republish it.',
|
||||
phutil_escape_html($post->getTitle())))
|
||||
->addSubmitButton(pht('Unpublish'))
|
||||
->addCancelButton($cancel_uri);
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
}
|
|
@ -21,111 +21,25 @@
|
|||
*/
|
||||
final class PhamePostViewController extends PhameController {
|
||||
|
||||
private $postPHID;
|
||||
private $phameTitle;
|
||||
private $bloggerName;
|
||||
|
||||
private function setPostPHID($post_phid) {
|
||||
$this->postPHID = $post_phid;
|
||||
return $this;
|
||||
}
|
||||
private function getPostPHID() {
|
||||
return $this->postPHID;
|
||||
}
|
||||
private function setPhameTitle($phame_title) {
|
||||
$this->phameTitle = $phame_title;
|
||||
return $this;
|
||||
}
|
||||
private function getPhameTitle() {
|
||||
return $this->phameTitle;
|
||||
}
|
||||
private function setBloggerName($blogger_name) {
|
||||
$this->bloggerName = $blogger_name;
|
||||
return $this;
|
||||
}
|
||||
private function getBloggerName() {
|
||||
return $this->bloggerName;
|
||||
}
|
||||
|
||||
protected function getSideNavFilter() {
|
||||
$filter = 'post/view/'.$this->getPostPHID();
|
||||
return $filter;
|
||||
}
|
||||
protected function getSideNavExtraPostFilters() {
|
||||
$filters = array(
|
||||
array('key' => $this->getSideNavFilter(),
|
||||
'name' => $this->getPhameTitle())
|
||||
);
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
// TODO -- get policy logic going
|
||||
// return PhabricatorEnv::getEnvConfig('policy.allow-public');
|
||||
return true;
|
||||
}
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->setPostPHID(idx($data, 'phid'));
|
||||
$this->setPhameTitle(idx($data, 'phametitle'));
|
||||
$this->setBloggerName(idx($data, 'bloggername'));
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
if ($this->getPostPHID()) {
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withPHIDs(array($this->getPostPHID()))
|
||||
->executeOne();
|
||||
|
||||
if (!$post) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$this->setPhameTitle($post->getPhameTitle());
|
||||
$blogger = PhabricatorObjectHandleData::loadOneHandle(
|
||||
$post->getBloggerPHID(),
|
||||
$user);
|
||||
} else if ($this->getBloggerName() && $this->getPhameTitle()) {
|
||||
$phame_title = $this->getPhameTitle();
|
||||
$phame_title = PhabricatorSlug::normalize($phame_title);
|
||||
$blogger_user = id(new PhabricatorUser())->loadOneWhere(
|
||||
'username = %s',
|
||||
$this->getBloggerName());
|
||||
if (!$blogger_user) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$blogger = PhabricatorObjectHandleData::loadOneHandle(
|
||||
$blogger_user->getPHID(),
|
||||
$user);
|
||||
if (!$blogger) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$posts = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withBloggerPHIDs(array($blogger->getPHID()))
|
||||
->withPhameTitles(array($phame_title))
|
||||
->execute();
|
||||
$post = reset($posts);
|
||||
|
||||
if ($post && $phame_title != $this->getPhameTitle()) {
|
||||
$uri = $post->getViewURI($this->getBloggerName());
|
||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||
}
|
||||
}
|
||||
$post = id(new PhamePostQuery())
|
||||
->setViewer($user)
|
||||
->withIDs(array($this->id))
|
||||
->executeOne();
|
||||
|
||||
if (!$post) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($post->isDraft() &&
|
||||
$post->getBloggerPHID() != $user->getPHID()) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($post->isDraft()) {
|
||||
$notice = array(
|
||||
'title' => 'You are previewing a draft.',
|
||||
|
@ -150,32 +64,123 @@ final class PhamePostViewController extends PhameController {
|
|||
$notice = array();
|
||||
}
|
||||
|
||||
$actions = array('more');
|
||||
if ($post->getBloggerPHID() == $user->getPHID()) {
|
||||
$actions[] = 'edit';
|
||||
}
|
||||
|
||||
$skin = new PhabricatorBlogSkin();
|
||||
|
||||
$skin
|
||||
->setUser($user)
|
||||
->setRequestURI($request->getRequestURI())
|
||||
->setBloggers(array($blogger->getPHID() => $blogger))
|
||||
->setPosts(array($post))
|
||||
->setNotice($notice)
|
||||
->setShowPostComments(true)
|
||||
->setActions($actions);
|
||||
|
||||
$this->setShowSideNav(false);
|
||||
$this->setShowChrome($skin->getShowChrome());
|
||||
$this->setDeviceReady($skin->getDeviceReady());
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$this->loadHandles(
|
||||
array(
|
||||
$skin
|
||||
),
|
||||
$post->getBlogPHID(),
|
||||
$post->getBloggerPHID(),
|
||||
));
|
||||
|
||||
$nav = $this->renderSideNavFilterView(null);
|
||||
|
||||
$header = id(new PhabricatorHeaderView())->setHeader($post->getTitle());
|
||||
|
||||
$actions = $this->renderActions($post, $user);
|
||||
$properties = $this->renderProperties($post, $user);
|
||||
|
||||
$nav->appendChild(
|
||||
array(
|
||||
$header,
|
||||
$actions,
|
||||
$properties,
|
||||
));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => $post->getTitle(),
|
||||
'device' => true,
|
||||
));
|
||||
}
|
||||
|
||||
private function renderActions(
|
||||
PhamePost $post,
|
||||
PhabricatorUser $user) {
|
||||
|
||||
$actions = id(new PhabricatorActionListView())
|
||||
->setObject($post)
|
||||
->setUser($user);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$user,
|
||||
$post,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$id = $post->getID();
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('edit')
|
||||
->setHref($this->getApplicationURI('post/edit/'.$id.'/'))
|
||||
->setName('Edit Post')
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$can_view_live = $post->getBlog() && !$post->isDraft();
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('world')
|
||||
->setHref($this->getApplicationURI('post/live/'.$id.'/'))
|
||||
->setName(pht('View Live'))
|
||||
->setDisabled(!$can_view_live)
|
||||
->setWorkflow(true));
|
||||
|
||||
if ($post->isDraft()) {
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('world')
|
||||
->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
|
||||
->setName(pht('Preview / Publish')));
|
||||
} else {
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('delete')
|
||||
->setHref($this->getApplicationURI('post/unpublish/'.$id.'/'))
|
||||
->setName(pht('Unpublish'))
|
||||
->setWorkflow(true));
|
||||
}
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('delete')
|
||||
->setHref($this->getApplicationURI('post/delete/'.$id.'/'))
|
||||
->setName('Delete Post')
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(true));
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
private function renderProperties(
|
||||
PhamePost $post,
|
||||
PhabricatorUser $user) {
|
||||
|
||||
$properties = new PhabricatorPropertyListView();
|
||||
|
||||
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
|
||||
$user,
|
||||
$post);
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Blog'),
|
||||
$post->getBlogPHID()
|
||||
? $this->getHandle($post->getBlogPHID())->renderLink()
|
||||
: null);
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Blogger'),
|
||||
$this->getHandle($post->getBloggerPHID())->renderLink());
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Visible To'),
|
||||
$descriptions[PhabricatorPolicyCapability::CAN_VIEW]);
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Published'),
|
||||
$post->isDraft()
|
||||
? pht('Draft')
|
||||
: phabricator_datetime($post->getDatePublished(), $user));
|
||||
|
||||
return $properties;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,18 @@
|
|||
*/
|
||||
final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $blogPHIDs;
|
||||
private $bloggerPHIDs;
|
||||
private $phameTitles;
|
||||
private $visibility;
|
||||
private $phids;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
|
@ -91,6 +97,13 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->ids) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'p.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
|
|
Loading…
Reference in a new issue