1
0
Fork 0
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:
epriestley 2012-10-15 14:50:45 -07:00
parent c37202dd48
commit 0e07ef8d56
14 changed files with 520 additions and 340 deletions

View file

@ -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',

View file

@ -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',

View file

@ -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())

View file

@ -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);

View file

@ -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');
}

View file

@ -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'];
}

View file

@ -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);
}

View file

@ -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,
));
}

View file

@ -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;
}
}

View file

@ -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,
));
}
}

View file

@ -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().'/'),
),
''));
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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,