1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 00:32:42 +01:00

Modernize blog UI

Summary:
Cleans up some of the mess I made in D3694. Basically:

  - All blogs have an "internal" view with posts that uses mobile-friendly UIs, etc., so we don't have to do as much work with skins -- they just have to look pretty.
  - Blogs now have a separate "live" view that we use to handle domains / skins.
  - Simplified some views and use IDs in some URLs for consistency.
  - Delete a bunch of edge/blogger/multi-blog code that's now obsolete.

Test Plan: Will attach screenshots.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1373

Differential Revision: https://secure.phabricator.com/D3695
This commit is contained in:
epriestley 2012-10-15 14:50:12 -07:00
parent a50b8e39b1
commit b072e937b5
23 changed files with 524 additions and 751 deletions

View file

@ -218,6 +218,9 @@ $action_map = array(
'subscribe-auto' => 'icon/unsubscribe.png', 'subscribe-auto' => 'icon/unsubscribe.png',
'subscribe-add' => 'icon/subscribe.png', 'subscribe-add' => 'icon/subscribe.png',
'subscribe-delete' => 'icon/unsubscribe.png', 'subscribe-delete' => 'icon/unsubscribe.png',
'new' => 'icon/page_white_put.png',
'world' => 'icon/world.png',
'delete' => 'icon/delete.png',
); );
foreach ($action_map as $icon => $source) { foreach ($action_map as $icon => $source) {

View file

@ -51,8 +51,8 @@ celerity_register_resource_map(array(
), ),
'/rsrc/image/autosprite.png' => '/rsrc/image/autosprite.png' =>
array( array(
'hash' => '005c7630a31cb2ef6b1782d4eca08cd7', 'hash' => 'b1a2597ab1d245a52e5c8783dffa5e26',
'uri' => '/res/005c7630/rsrc/image/autosprite.png', 'uri' => '/res/b1a2597a/rsrc/image/autosprite.png',
'disk' => '/rsrc/image/autosprite.png', 'disk' => '/rsrc/image/autosprite.png',
'type' => 'png', 'type' => 'png',
), ),
@ -462,27 +462,6 @@ celerity_register_resource_map(array(
'disk' => '/rsrc/image/nyan.gif', 'disk' => '/rsrc/image/nyan.gif',
'type' => 'gif', 'type' => 'gif',
), ),
'/rsrc/image/phacility/phacility_logo.jpg' =>
array(
'hash' => '88000de28b8741acc584b24560bd3d4f',
'uri' => '/res/88000de2/rsrc/image/phacility/phacility_logo.jpg',
'disk' => '/rsrc/image/phacility/phacility_logo.jpg',
'type' => 'jpg',
),
'/rsrc/image/phacility/sprites.png' =>
array(
'hash' => 'b018a070d120f689a2beb8ece67e1b1e',
'uri' => '/res/b018a070/rsrc/image/phacility/sprites.png',
'disk' => '/rsrc/image/phacility/sprites.png',
'type' => 'png',
),
'/rsrc/image/phacility/tactile_noise.png' =>
array(
'hash' => '7fb4ca90b8b0919153770b6badb982f0',
'uri' => '/res/7fb4ca90/rsrc/image/phacility/tactile_noise.png',
'disk' => '/rsrc/image/phacility/tactile_noise.png',
'type' => 'png',
),
'/rsrc/image/search.png' => '/rsrc/image/search.png' =>
array( array(
'hash' => 'ff7da044e6f923b8f569dec11f97e5e5', 'hash' => 'ff7da044e6f923b8f569dec11f97e5e5',
@ -678,7 +657,7 @@ celerity_register_resource_map(array(
), ),
'autosprite-css' => 'autosprite-css' =>
array( array(
'uri' => '/res/6c0c2948/rsrc/css/autosprite.css', 'uri' => '/res/95e8f847/rsrc/css/autosprite.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(
@ -1633,17 +1612,6 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/application/core/behavior-watch-anchor.js', 'disk' => '/rsrc/js/application/core/behavior-watch-anchor.js',
), ),
'javelin-behavior-phame-post-blogs' =>
array(
'uri' => '/res/a7f7756c/rsrc/js/application/phame/phame-post-blogs.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/phame/phame-post-blogs.js',
),
'javelin-behavior-phame-post-preview' => 'javelin-behavior-phame-post-preview' =>
array( array(
'uri' => '/res/ac4c503a/rsrc/js/application/phame/phame-post-preview.js', 'uri' => '/res/ac4c503a/rsrc/js/application/phame/phame-post-preview.js',
@ -2203,15 +2171,6 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/javelin/lib/Workflow.js', 'disk' => '/rsrc/js/javelin/lib/Workflow.js',
), ),
'jquery-js' =>
array(
'uri' => '/res/7f0dd213/rsrc/js/application/phame/skins/phacility/jquery/jquery.min.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/application/phame/skins/phacility/jquery/jquery.min.js',
),
'maniphest-batch-editor' => 'maniphest-batch-editor' =>
array( array(
'uri' => '/res/fb15d744/rsrc/css/application/maniphest/batch-editor.css', 'uri' => '/res/fb15d744/rsrc/css/application/maniphest/batch-editor.css',
@ -2918,38 +2877,9 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/application/uiexample/ReactorSendPropertiesExample.js', 'disk' => '/rsrc/js/application/uiexample/ReactorSendPropertiesExample.js',
), ),
'phacility-bootstrap-css' =>
array(
'uri' => '/res/28f0ad0e/rsrc/css/application/phame/skins/phacility/bootstrap/bootstrap.min.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/phame/skins/phacility/bootstrap/bootstrap.min.css',
),
'phacility-css' =>
array(
'uri' => '/res/f55275c2/rsrc/css/application/phame/skins/phacility/phacility.css',
'type' => 'css',
'requires' =>
array(
0 => 'phacility-bootstrap-css',
),
'disk' => '/rsrc/css/application/phame/skins/phacility/phacility.css',
),
'phacility-js' =>
array(
'uri' => '/res/f441bc88/rsrc/js/application/phame/skins/phacility/bootstrap/bootstrap.min.js',
'type' => 'js',
'requires' =>
array(
0 => 'jquery-js',
),
'disk' => '/rsrc/js/application/phame/skins/phacility/bootstrap/bootstrap.min.js',
),
'phame-css' => 'phame-css' =>
array( array(
'uri' => '/res/2d18adca/rsrc/css/application/phame/phame.css', 'uri' => '/res/2e4c86eb/rsrc/css/application/phame/phame.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(

View file

@ -1147,14 +1147,13 @@ phutil_register_library_map(array(
'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php', 'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php',
'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php', 'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php',
'PhabricatorXHProfSampleListView' => 'applications/xhprof/view/PhabricatorXHProfSampleListView.php', 'PhabricatorXHProfSampleListView' => 'applications/xhprof/view/PhabricatorXHProfSampleListView.php',
'PhameAllBlogListController' => 'applications/phame/controller/blog/list/PhameAllBlogListController.php',
'PhameAllPostListController' => 'applications/phame/controller/post/list/PhameAllPostListController.php', 'PhameAllPostListController' => 'applications/phame/controller/post/list/PhameAllPostListController.php',
'PhameBlog' => 'applications/phame/storage/PhameBlog.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php', 'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php',
'PhameBlogDetailView' => 'applications/phame/view/PhameBlogDetailView.php', 'PhameBlogDetailView' => 'applications/phame/view/PhameBlogDetailView.php',
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
'PhameBlogListBaseController' => 'applications/phame/controller/blog/list/PhameBlogListBaseController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php', 'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
'PhameBlogSkin' => 'applications/phame/view/skins/PhameBlogSkin.php', 'PhameBlogSkin' => 'applications/phame/view/skins/PhameBlogSkin.php',
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php', 'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
@ -1171,7 +1170,6 @@ phutil_register_library_map(array(
'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php',
'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php',
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
'PhameUserBlogListController' => 'applications/phame/controller/blog/list/PhameUserBlogListController.php',
'PhameUserPostListController' => 'applications/phame/controller/post/list/PhameUserPostListController.php', 'PhameUserPostListController' => 'applications/phame/controller/post/list/PhameUserPostListController.php',
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php', 'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php',
@ -2274,7 +2272,6 @@ phutil_register_library_map(array(
'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO', 'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO',
'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController', 'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController',
'PhabricatorXHProfSampleListView' => 'AphrontView', 'PhabricatorXHProfSampleListView' => 'AphrontView',
'PhameAllBlogListController' => 'PhameBlogListBaseController',
'PhameAllPostListController' => 'PhamePostListBaseController', 'PhameAllPostListController' => 'PhamePostListBaseController',
'PhameBlog' => 'PhameBlog' =>
array( array(
@ -2284,8 +2281,8 @@ phutil_register_library_map(array(
'PhameBlogDeleteController' => 'PhameController', 'PhameBlogDeleteController' => 'PhameController',
'PhameBlogDetailView' => 'AphrontView', 'PhameBlogDetailView' => 'AphrontView',
'PhameBlogEditController' => 'PhameController', 'PhameBlogEditController' => 'PhameController',
'PhameBlogListBaseController' => 'PhameController', 'PhameBlogListController' => 'PhameController',
'PhameBlogListView' => 'AphrontView', 'PhameBlogLiveController' => 'PhameController',
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhameBlogSkin' => 'AphrontView', 'PhameBlogSkin' => 'AphrontView',
'PhameBlogViewController' => 'PhameController', 'PhameBlogViewController' => 'PhameController',
@ -2293,16 +2290,19 @@ phutil_register_library_map(array(
'PhameController' => 'PhabricatorController', 'PhameController' => 'PhabricatorController',
'PhameDAO' => 'PhabricatorLiskDAO', 'PhameDAO' => 'PhabricatorLiskDAO',
'PhameDraftListController' => 'PhamePostListBaseController', 'PhameDraftListController' => 'PhamePostListBaseController',
'PhamePost' => 'PhameDAO', 'PhamePost' =>
array(
0 => 'PhameDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhamePostDeleteController' => 'PhameController', 'PhamePostDeleteController' => 'PhameController',
'PhamePostDetailView' => 'AphrontView', 'PhamePostDetailView' => 'AphrontView',
'PhamePostEditController' => 'PhameController', 'PhamePostEditController' => 'PhameController',
'PhamePostListBaseController' => 'PhameController', 'PhamePostListBaseController' => 'PhameController',
'PhamePostListView' => 'AphrontView', 'PhamePostListView' => 'AphrontView',
'PhamePostPreviewController' => 'PhameController', 'PhamePostPreviewController' => 'PhameController',
'PhamePostQuery' => 'PhabricatorOffsetPagedQuery', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhamePostViewController' => 'PhameController', 'PhamePostViewController' => 'PhameController',
'PhameUserBlogListController' => 'PhameBlogListBaseController',
'PhameUserPostListController' => 'PhamePostListBaseController', 'PhameUserPostListController' => 'PhamePostListBaseController',
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
'PhortuneStripeBaseController' => 'PhabricatorController', 'PhortuneStripeBaseController' => 'PhabricatorController',

View file

@ -140,7 +140,7 @@ abstract class AphrontApplicationConfiguration {
try { try {
$blog = id(new PhameBlogQuery()) $blog = id(new PhameBlogQuery())
->setViewer($request->getUser()) ->setViewer(new PhabricatorUser())
->withDomain($host) ->withDomain($host)
->executeOne(); ->executeOne();
} catch (PhabricatorPolicyException $ex) { } catch (PhabricatorPolicyException $ex) {
@ -161,18 +161,10 @@ abstract class AphrontApplicationConfiguration {
); );
} }
// 2 basic cases // TODO: Make this more flexible and modular so any application can
// -- looking at a list of blog posts, path is nothing or '/' // do crazy stuff here if it wants.
// -- we have to fudge the URI in this case
// -- looking at an actual blog post, path is like
// /phame/posts/<author>/post_title
// NOTE: it is possible to get other phame pages, we just do
// not link to them at this time.
if (!$path || $path == '/') {
$path = $blog->getViewURI();
}
PhameBlog::setRequestBlog($blog); $path = '/phame/blog/live/'.$blog->getID().'/'.$path;
$celerity = CelerityAPI::getStaticResourceResponse(); $celerity = CelerityAPI::getStaticResourceResponse();
$celerity->setUseFullURI(true); $celerity->setUseFullURI(true);

View file

@ -58,13 +58,13 @@ final class PhabricatorApplicationPhame extends PhabricatorApplication {
'' => 'PhameDraftListController', '' => 'PhameDraftListController',
'new/' => 'PhamePostEditController', 'new/' => 'PhamePostEditController',
), ),
'blog/(?:(?P<filter>user|all)/)?' => 'PhameBlogListController',
'blog/' => array( 'blog/' => array(
'' => 'PhameUserBlogListController', 'delete/(?P<id>[^/]+)/' => 'PhameBlogDeleteController',
'all/' => 'PhameAllBlogListController', 'edit/(?P<id>[^/]+)/' => 'PhameBlogEditController',
'view/(?P<id>[^/]+)/' => 'PhameBlogViewController',
'live/(?P<id>[^/]+)/(?P<more>.*)' => 'PhameBlogLiveController',
'new/' => 'PhameBlogEditController', 'new/' => 'PhameBlogEditController',
'delete/(?P<phid>[^/]+)/' => 'PhameBlogDeleteController',
'edit/(?P<phid>[^/]+)/' => 'PhameBlogEditController',
'view/(?P<phid>[^/]+)/' => 'PhameBlogViewController',
), ),
'posts/' => array( 'posts/' => array(
'' => 'PhameUserPostListController', '' => 'PhameUserPostListController',

View file

@ -71,13 +71,16 @@ abstract class PhameController extends PhabricatorController {
return $response->setContent($page->render()); return $response->setContent($page->render());
} }
private function renderSideNavFilterView($filter) { protected function renderSideNavFilterView($filter) {
$base_uri = new PhutilURI('/phame/'); $base_uri = new PhutilURI('/phame/');
$nav = new AphrontSideNavFilterView(); $nav = new AphrontSideNavFilterView();
$nav->setBaseURI($base_uri); $nav->setBaseURI($base_uri);
$nav->addLabel('Drafts'); $nav->addLabel('Create');
$nav->addFilter('post/new', $nav->addFilter('post/new', 'New Draft');
'New Draft'); $nav->addFilter('blog/new', 'New Blog');
$nav->addSpacer();
$nav->addLabel('Posts');
$nav->addFilter('draft', $nav->addFilter('draft',
'My Drafts'); 'My Drafts');
foreach ($this->getSideNavExtraDraftFilters() as $draft_filter) { foreach ($this->getSideNavExtraDraftFilters() as $draft_filter) {
@ -85,9 +88,6 @@ abstract class PhameController extends PhabricatorController {
$draft_filter['name'], $draft_filter['name'],
idx($draft_filter, 'uri')); idx($draft_filter, 'uri'));
} }
$nav->addSpacer();
$nav->addLabel('Posts');
$nav->addFilter('post', $nav->addFilter('post',
'My Posts'); 'My Posts');
$nav->addFilter('post/all', $nav->addFilter('post/all',
@ -123,7 +123,7 @@ abstract class PhameController extends PhabricatorController {
protected function getSideNavBlogFilters() { protected function getSideNavBlogFilters() {
return array( return array(
array( array(
'key' => 'blog', 'key' => 'blog/user',
'name' => 'My Blogs', 'name' => 'My Blogs',
), ),
array( array(
@ -154,4 +154,24 @@ abstract class PhameController extends PhabricatorController {
->setTitle('Meta thoughts and feelings'); ->setTitle('Meta thoughts and feelings');
return $notice_view; return $notice_view;
} }
protected function renderPostList(
array $posts,
PhabricatorUser $user,
$nodata) {
assert_instances_of($posts, 'PhamePost');
$list = id(new PhabricatorObjectItemListView())
->setNoDataString($nodata);
foreach ($posts as $post) {
$item = id(new PhabricatorObjectItemView())
->setHeader($post->getTitle())
->setHref($this->getApplicationURI('post/view/'.$post->getPHID()));
$list->addItem($item);
}
return $list;
}
} }

View file

@ -19,18 +19,10 @@
/** /**
* @group phame * @group phame
*/ */
final class PhameBlogDeleteController final class PhameBlogDeleteController extends PhameController {
extends PhameController {
private $phid; private $id;
private function setBlogPHID($phid) {
$this->phid = $phid;
return $this;
}
private function getBlogPHID() {
return $this->phid;
}
protected function getSideNavFilter() { protected function getSideNavFilter() {
return 'blog/delete/'.$this->getBlogPHID(); return 'blog/delete/'.$this->getBlogPHID();
@ -46,8 +38,7 @@ extends PhameController {
} }
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$phid = $data['phid']; $this->id = $data['id'];
$this->setBlogPHID($phid);
} }
public function processRequest() { public function processRequest() {
@ -56,13 +47,12 @@ extends PhameController {
$blog = id(new PhameBlogQuery()) $blog = id(new PhameBlogQuery())
->setViewer($user) ->setViewer($user)
->withPHIDs(array($this->getBlogPHID())) ->withIDs(array($this->id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->executeOne(); ->executeOne();
if (!$blog) { if (!$blog) {
return new Aphront404Response(); return new Aphront404Response();
} }
@ -70,15 +60,20 @@ extends PhameController {
if ($request->isFormPost()) { if ($request->isFormPost()) {
$blog->delete(); $blog->delete();
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI('/phame/blog/?deleted'); ->setURI($this->getApplicationURI());
} }
$cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/');
$dialog = id(new AphrontDialogView()) $dialog = id(new AphrontDialogView())
->setUser($user) ->setUser($user)
->setTitle('Delete blog?') ->setTitle(pht('Delete blog?'))
->appendChild('Really delete this blog? It will be gone forever.') ->appendChild(
->addSubmitButton('Delete') pht(
->addCancelButton($blog->getEditURI()); 'Really delete the blog "%s"? It will be gone forever.',
$blog->getName()))
->addSubmitButton(pht('Delete'))
->addCancelButton($cancel_uri);
return id(new AphrontDialogResponse())->setDialog($dialog); return id(new AphrontDialogResponse())->setDialog($dialog);
} }

View file

@ -22,69 +22,25 @@
final class PhameBlogEditController final class PhameBlogEditController
extends PhameController { extends PhameController {
private $phid; private $id;
private $isBlogEdit;
private function setBlogPHID($phid) {
$this->phid = $phid;
return $this;
}
private function getBlogPHID() {
return $this->phid;
}
private function setIsBlogEdit($is_blog_edit) {
$this->isBlogEdit = $is_blog_edit;
return $this;
}
private function isBlogEdit() {
return $this->isBlogEdit;
}
protected function getSideNavFilter() { protected function getSideNavFilter() {
if ($this->isBlogEdit()) { return 'blog/edit/'.$this->id;
$filter = 'blog/edit/'.$this->getBlogPHID();
} else {
$filter = 'blog/new';
}
return $filter;
} }
protected function getSideNavBlogFilters() {
$filters = parent::getSideNavBlogFilters();
if ($this->isBlogEdit()) {
$filter =
array('key' => 'blog/edit/'.$this->getBlogPHID(),
'name' => 'Edit Blog');
$filters[] = $filter;
} else {
$filter =
array('key' => 'blog/new',
'name' => 'New Blog');
array_unshift($filters, $filter);
}
return $filters;
}
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$phid = idx($data, 'phid'); $this->id = idx($data, 'id');
$this->setBlogPHID($phid);
$this->setIsBlogEdit((bool)$phid);
} }
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$e_name = true; if ($this->id) {
$e_custom_domain = null;
$errors = array();
if ($this->isBlogEdit()) {
$blog = id(new PhameBlogQuery()) $blog = id(new PhameBlogQuery())
->setViewer($user) ->setViewer($user)
->withPHIDs(array($this->getBlogPHID())) ->withIDs(array($this->id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_EDIT PhabricatorPolicyCapability::CAN_EDIT
@ -94,25 +50,26 @@ final class PhameBlogEditController
return new Aphront404Response(); return new Aphront404Response();
} }
$submit_button = 'Save Changes'; $submit_button = pht('Save Changes');
$delete_button = javelin_render_tag( $page_title = pht('Edit Blog');
'a', $cancel_uri = $this->getApplicationURI('blog/view/'.$blog->getID().'/');
array(
'href' => $blog->getDeleteURI(),
'class' => 'grey button',
'sigil' => 'workflow',
),
'Delete Blog');
$page_title = 'Edit Blog';
} else { } else {
$blog = id(new PhameBlog()) $blog = id(new PhameBlog())
->setCreatorPHID($user->getPHID()); ->setCreatorPHID($user->getPHID());
$blogger_tokens = array($user->getPHID() => $user->getFullName());
$submit_button = 'Create Blog'; $blog->setViewPolicy(PhabricatorPolicies::POLICY_USER);
$delete_button = null; $blog->setEditPolicy(PhabricatorPolicies::POLICY_USER);
$page_title = 'Create Blog'; $blog->setJoinPolicy(PhabricatorPolicies::POLICY_USER);
$submit_button = pht('Create Blog');
$page_title = pht('Create Blog');
$cancel_uri = $this->getApplicationURI();
} }
$e_name = true;
$e_custom_domain = null;
$errors = array();
if ($request->isFormPost()) { if ($request->isFormPost()) {
$name = $request->getStr('name'); $name = $request->getStr('name');
$description = $request->getStr('description'); $description = $request->getStr('description');
@ -122,9 +79,13 @@ final class PhameBlogEditController
if (empty($name)) { if (empty($name)) {
$errors[] = 'You must give the blog a name.'; $errors[] = 'You must give the blog a name.';
$e_name = 'Required'; $e_name = 'Required';
} else {
$e_name = null;
} }
$blog->setName($name); $blog->setName($name);
$blog->setDescription($description); $blog->setDescription($description);
if (!empty($custom_domain)) { if (!empty($custom_domain)) {
$error = $blog->validateCustomDomain($custom_domain); $error = $blog->validateCustomDomain($custom_domain);
if ($error) { if ($error) {
@ -147,25 +108,11 @@ final class PhameBlogEditController
if (!$errors) { if (!$errors) {
$blog->save(); $blog->save();
$uri = new PhutilURI($blog->getViewURI());
if ($this->isBlogEdit()) {
$uri->setQueryParam('edit', true);
} else {
$uri->setQueryParam('new', true);
}
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI($uri); ->setURI($this->getApplicationURI('blog/view/'.$blog->getID().'/'));
} }
} }
$panel = new AphrontPanelView();
$panel->setHeader($page_title);
$panel->setWidth(AphrontPanelView::WIDTH_FULL);
if ($delete_button) {
$panel->addButton($delete_button);
}
$policies = id(new PhabricatorPolicyQuery()) $policies = id(new PhabricatorPolicyQuery())
->setViewer($user) ->setViewer($user)
->setObject($blog) ->setObject($blog)
@ -173,6 +120,7 @@ final class PhameBlogEditController
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($user) ->setUser($user)
->setFlexible(true)
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel('Name') ->setLabel('Name')
@ -227,12 +175,10 @@ final class PhameBlogEditController
) )
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())
->addCancelButton('/phame/blog/') ->addCancelButton($cancel_uri)
->setValue($submit_button) ->setValue($submit_button)
); );
$panel->appendChild($form);
if ($errors) { if ($errors) {
$error_view = id(new AphrontErrorView()) $error_view = id(new AphrontErrorView())
->setTitle('Form Errors') ->setTitle('Form Errors')
@ -241,12 +187,15 @@ final class PhameBlogEditController
$error_view = null; $error_view = null;
} }
$this->setShowSideNav(true); $nav = $this->renderSideNavFilterView(null);
return $this->buildStandardPageResponse( $nav->appendChild(
array( array(
$error_view, $error_view,
$panel, $form,
), ));
return $this->buildApplicationPage(
$nav,
array( array(
'title' => $page_title, 'title' => $page_title,
)); ));

View file

@ -0,0 +1,105 @@
<?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 PhameBlogListController extends PhameController {
private $filter;
public function willProcessRequest(array $data) {
$this->filter = idx($data, 'filter');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$nav = $this->renderSideNavFilterView(null);
$filter = $nav->selectFilter('blog/'.$this->filter, 'blog/user');
$query = id(new PhameBlogQuery())
->setViewer($user);
switch ($filter) {
case 'blog/all':
$title = 'All Blogs';
$nodata = 'No blogs have been created.';
break;
case 'blog/user':
$title = 'My Blogs';
$nodata = 'There are no blogs you can contribute to.';
$query->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_JOIN,
));
break;
default:
throw new Exception("Unknown filter '{$filter}'!");
}
$pager = id(new AphrontPagerView())
->setURI($request->getRequestURI(), 'offset')
->setOffset($request->getInt('offset'));
$blogs = $query->executeWithOffsetPager($pager);
$header = id(new PhabricatorHeaderView())
->setHeader($title);
$blog_list = $this->renderBlogList($blogs, $user, $nodata);
$blog_list->setPager($pager);
$nav->appendChild(
array(
$header,
$blog_list,
));
return $this->buildApplicationPage(
$nav,
array(
'title' => $title,
'device' => true,
));
}
private function renderBlogList(
array $blogs,
PhabricatorUser $user,
$nodata) {
$view = new PhabricatorObjectItemListView();
$view->setNoDataString($nodata);
foreach ($blogs as $blog) {
$item = id(new PhabricatorObjectItemView())
->setHeader($blog->getName())
->setHref($this->getApplicationURI('blog/view/'.$blog->getID().'/'))
->addDetail(
'Custom Domain',
phutil_escape_html($blog->getDomain()));
$view->addItem($item);
}
return $view;
}
}

View file

@ -0,0 +1,115 @@
<?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 PhameBlogLiveController extends PhameController {
private $id;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
// NOTE: We're loading with the logged-out user so we can raise the right
// error if the blog permissions aren't set correctly.
$blog = null;
$policy_exception = null;
try {
$blog = id(new PhameBlogQuery())
->setViewer(new PhabricatorUser())
->withIDs(array($this->id))
->executeOne();
} catch (PhabricatorPolicyException $ex) {
$policy_exception = $ex;
}
if (!$blog && !$policy_exception) {
return new Aphront404Response();
}
$errors = array();
if ($policy_exception) {
$errors[] = pht('"Visible To" must be set to "Public".');
}
if ($blog && !$blog->getDomain()) {
$errors[] = pht('You must configure a custom domain.');
}
if ($errors) {
if ($blog) {
$cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID());
} else {
$cancel_uri = $this->getApplicationURI();
}
$dialog = id(new AphrontDialogView())
->setUser($user)
->addCancelButton($cancel_uri)
->setTitle(pht('Live Blog Unavailable'));
foreach ($errors as $error) {
$dialog->appendChild('<p>'.$error.'</p>');
}
return id(new AphrontDialogResponse())->setDialog($dialog);
}
if ($request->getHost() != $blog->getDomain()) {
$uri = 'http://'.$blog->getDomain().'/';
return id(new AphrontRedirectResponse())->setURI($uri);
}
$pager = id(new AphrontCursorPagerView())
->readFromRequest($request);
$posts = id(new PhamePostQuery())
->setViewer($user)
->withBlogPHIDs(array($blog->getPHID()))
->executeWithCursorPager($pager);
$skin = $blog->getSkinRenderer();
$skin
->setUser($user)
->setPosts($posts)
->setBloggers($this->loadViewerHandles(mpull($posts, 'getBloggerPHID')))
->setBlog($blog)
->setRequestURI($this->getRequest()->getRequestURI());
$page = $this->buildStandardPageView();
$page->appendChild($skin);
$page->setShowChrome(false);
$response = new AphrontWebpageResponse();
$response->setContent($page->render());
return $response;
}
}

View file

@ -21,15 +21,7 @@
*/ */
final class PhameBlogViewController extends PhameController { final class PhameBlogViewController extends PhameController {
private $blogPHID; private $id;
private function setBlogPHID($blog_phid) {
$this->blogPHID = $blog_phid;
return $this;
}
private function getBlogPHID() {
return $this->blogPHID;
}
protected function getSideNavFilter() { protected function getSideNavFilter() {
$filter = 'blog/view/'.$this->getBlogPHID(); $filter = 'blog/view/'.$this->getBlogPHID();
@ -45,7 +37,7 @@ final class PhameBlogViewController extends PhameController {
} }
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->setBlogPHID(idx($data, 'phid')); $this->id = $data['id'];
} }
public function processRequest() { public function processRequest() {
@ -54,36 +46,128 @@ final class PhameBlogViewController extends PhameController {
$blog = id(new PhameBlogQuery()) $blog = id(new PhameBlogQuery())
->setViewer($user) ->setViewer($user)
->withPHIDs(array($this->getBlogPHID())) ->withIDs(array($this->id))
->executeOne(); ->executeOne();
if (!$blog) { if (!$blog) {
return new Aphront404Response(); return new Aphront404Response();
} }
$pager = id(new AphrontCursorPagerView())
->readFromRequest($request);
$posts = id(new PhamePostQuery()) $posts = id(new PhamePostQuery())
->setViewer($user) ->setViewer($user)
->withBlogPHIDs(array($blog->getPHID())) ->withBlogPHIDs(array($blog->getPHID()))
->execute(); ->executeWithCursorPager($pager);
$skin = $blog->getSkinRenderer(); $nav = $this->renderSideNavFilterView(null);
$skin
->setUser($this->getRequest()->getUser())
->setBloggers($this->loadViewerHandles(mpull($posts, 'getBloggerPHID')))
->setPosts($posts)
->setBlog($blog)
->setRequestURI($this->getRequest()->getRequestURI());
$this->setShowSideNav(false); $header = id(new PhabricatorHeaderView())
$this->setShowChrome($skin->getShowChrome()); ->setHeader($blog->getName());
$this->setDeviceReady($skin->getDeviceReady());
$skin->setIsExternalDomain($blog->getDomain() == $request->getHost());
return $this->buildStandardPageResponse( $actions = $this->renderActions($blog, $user);
$properties = $this->renderProperties($blog, $user);
$post_list = $this->renderPostList(
$posts,
$user,
pht('This blog has no visible posts.'));
$nav->appendChild(
array( array(
$skin $header,
), $actions,
$properties,
$post_list,
));
return $this->buildApplicationPage(
$nav,
array( array(
'device' => true,
'title' => $blog->getName(), 'title' => $blog->getName(),
)); ));
} }
private function renderProperties(PhameBlog $blog, PhabricatorUser $user) {
$properties = new PhabricatorPropertyListView();
$properties->addProperty(
pht('Skin'),
phutil_escape_html($blog->getSkin()));
$properties->addProperty(
pht('Domain'),
phutil_escape_html($blog->getDomain()));
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$user,
$blog);
$properties->addProperty(
pht('Visible To'),
$descriptions[PhabricatorPolicyCapability::CAN_VIEW]);
$properties->addProperty(
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
$properties->addProperty(
pht('Joinable By'),
$descriptions[PhabricatorPolicyCapability::CAN_JOIN]);
return $properties;
}
private function renderActions(PhameBlog $blog, PhabricatorUser $user) {
$actions = id(new PhabricatorActionListView())
->setObject($blog)
->setUser($user);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$blog,
PhabricatorPolicyCapability::CAN_EDIT);
$can_join = PhabricatorPolicyFilter::hasCapability(
$user,
$blog,
PhabricatorPolicyCapability::CAN_JOIN);
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('new')
->setHref($this->getApplicationURI('post/new/?blog='.$blog->getID()))
->setName(pht('Write Post'))
->setDisabled(!$can_join)
->setWorkflow(!$can_join));
$has_domain = $blog->getDomain();
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('world')
->setHref($this->getApplicationURI('blog/live/'.$blog->getID().'/'))
->setName(pht('View Live'))
->setDisabled(!$has_domain)
->setWorkflow(true));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('edit')
->setHref($this->getApplicationURI('blog/edit/'.$blog->getID().'/'))
->setName('Edit Blog')
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('delete')
->setHref($this->getApplicationURI('blog/delete/'.$blog->getID().'/'))
->setName('Delete Blog')
->setDisabled(!$can_edit)
->setWorkflow(true));
return $actions;
}
} }

View file

@ -1,49 +0,0 @@
<?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 PhameAllBlogListController
extends PhameBlogListBaseController {
protected function getSideNavFilter() {
return 'blog/all';
}
public function processRequest() {
$user = $this->getRequest()->getUser();
$pager = id(new AphrontCursorPagerView())
->readFromRequest($this->getRequest());
$blogs = id(new PhameBlogQuery())
->setViewer($user)
->needBloggers(true)
->executeWithCursorPager($pager);
$this->setBlogs($blogs);
$page_title = 'All Blogs';
$this->setPageTitle($page_title);
$this->setShowSideNav(true);
return $this->buildBlogListPageResponse();
}
}

View file

@ -1,71 +0,0 @@
<?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
*/
abstract class PhameBlogListBaseController
extends PhameController {
private $blogs;
private $pageTitle;
protected function setBlogs(array $blogs) {
assert_instances_of($blogs, 'PhameBlog');
$this->blogs = $blogs;
return $this;
}
private function getBlogs() {
return $this->blogs;
}
protected function setPageTitle($page_title) {
$this->pageTitle = $page_title;
return $this;
}
private function getPageTitle() {
return $this->pageTitle;
}
protected function getNoticeView() {
return null;
}
private function getBlogListPanel() {
$blogs = $this->getBlogs();
$panel = id(new PhameBlogListView())
->setUser($this->getRequest()->getUser())
->setBlogs($blogs)
->setHeader($this->getPageTitle());
return $panel;
}
protected function buildBlogListPageResponse() {
return $this->buildStandardPageResponse(
array(
$this->getNoticeView(),
$this->getBlogListPanel(),
$this->getPager(),
),
array(
'title' => $this->getPageTitle(),
));
}
}

View file

@ -1,69 +0,0 @@
<?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 PhameUserBlogListController
extends PhameBlogListBaseController {
protected function getNoticeView() {
$request = $this->getRequest();
if ($request->getExists('deleted')) {
$notice_view = $this->buildNoticeView()
->appendChild('Successfully deleted blog.');
} else {
$notice_view = null;
}
return $notice_view;
}
protected function getSideNavFilter() {
return 'blog';
}
public function processRequest() {
$user = $this->getRequest()->getUser();
$phid = $user->getPHID();
$blog_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$phid,
PhabricatorEdgeConfig::TYPE_BLOGGER_HAS_BLOG
);
$pager = id(new AphrontCursorPagerView())
->readFromRequest($this->getRequest());
$blogs = id(new PhameBlogQuery())
->setViewer($user)
->withPHIDs($blog_phids)
->needBloggers(true)
->executeWithCursorPager($pager);
$this->setBlogs($blogs);
$this->setPageTitle('My Blogs');
$this->setShowSideNav(true);
return $this->buildBlogListPageResponse();
}
}

View file

@ -140,16 +140,28 @@ final class PhamePostEditController
'Delete '.$post_noun); 'Delete '.$post_noun);
$page_title = 'Edit '.$post_noun; $page_title = 'Edit '.$post_noun;
} else { } else {
$blog = id(new PhameBlogQuery())
->setViewer($user)
->withIDs(array($request->getInt('blog')))
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
$post = id(new PhamePost()) $post = id(new PhamePost())
->setBloggerPHID($user->getPHID()) ->setBloggerPHID($user->getPHID())
->setBlog($blog)
->setBlogPHID($blog->getPHID())
->setVisibility(PhamePost::VISIBILITY_DRAFT); ->setVisibility(PhamePost::VISIBILITY_DRAFT);
$cancel_uri = '/phame/draft/'; $cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/');
$submit_button = 'Create Draft';
$submit_button = pht('Create Draft');
$delete_button = null; $delete_button = null;
$page_title = 'Create Draft'; $page_title = pht('Create Draft');
} }
$this->setPost($post); $this->setPost($post);
$this->loadEdgesAndBlogs();
if ($request->isFormPost()) { if ($request->isFormPost()) {
$saved = true; $saved = true;
@ -182,48 +194,19 @@ final class PhamePostEditController
$e_title = 'Required'; $e_title = 'Required';
} }
$blogs_published = array_keys($this->getPostBlogs()); if (!$errors) {
$blogs_to_publish = array();
$blogs_to_depublish = array();
if ($visibility == PhamePost::VISIBILITY_PUBLISHED) {
$blogs_arr = $request->getArr('blogs');
$blogs_to_publish = array_values($blogs_arr);
$blogs_to_depublish = array_diff($blogs_published,
$blogs_to_publish);
} else {
$blogs_to_depublish = $blogs_published;
}
if (empty($errors)) {
try { try {
$post->save(); $post->save();
$editor = new PhabricatorEdgeEditor();
$edge_type = PhabricatorEdgeConfig::TYPE_POST_HAS_BLOG;
$editor->setActor($user);
foreach ($blogs_to_publish as $phid) {
$editor->addEdge($post->getPHID(), $edge_type, $phid);
}
foreach ($blogs_to_depublish as $phid) {
$editor->removeEdge($post->getPHID(), $edge_type, $phid);
}
$editor->save();
} catch (AphrontQueryDuplicateKeyException $e) {
$saved = false;
$e_phame_title = 'Not Unique';
$errors[] = 'Another post already uses this slug. '.
'Each post must have a unique slug.';
}
} else {
$saved = false;
}
if ($saved) {
$uri = new PhutilURI($post->getViewURI($user->getUsername())); $uri = new PhutilURI($post->getViewURI($user->getUsername()));
$uri->setQueryParam('saved', true); $uri->setQueryParam('saved', true);
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI($uri); ->setURI($uri);
} catch (AphrontQueryDuplicateKeyException $e) {
$e_phame_title = 'Not Unique';
$errors[] = 'Another post already uses this slug. '.
'Each post must have a unique slug.';
}
} }
} }
@ -234,8 +217,16 @@ final class PhamePostEditController
$panel->addButton($delete_button); $panel->addButton($delete_button);
} }
$handle = PhabricatorObjectHandleData::loadOneHandle(
$post->getBlogPHID(),
$user);
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($user) ->setUser($user)
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Blog')
->setValue($handle->renderLink()))
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel('Title') ->setLabel('Title')
@ -271,9 +262,6 @@ final class PhamePostEditController
->setOptions(PhamePost::getVisibilityOptionsForSelect()) ->setOptions(PhamePost::getVisibilityOptionsForSelect())
->setID('post-visibility') ->setID('post-visibility')
) )
->appendChild(
$this->getBlogCheckboxControl($post)
)
->appendChild( ->appendChild(
id(new AphrontFormSelectControl()) id(new AphrontFormSelectControl())
->setLabel('Comments Widget') ->setLabel('Comments Widget')
@ -312,26 +300,6 @@ final class PhamePostEditController
'uri' => '/phame/post/preview/', 'uri' => '/phame/post/preview/',
)); ));
$visibility_data = array(
'select_id' => 'post-visibility',
'current' => $post->getVisibility(),
'published' => PhamePost::VISIBILITY_PUBLISHED,
'draft' => PhamePost::VISIBILITY_DRAFT,
'change_uri' => $post->getChangeVisibilityURI(),
);
$blogs_data = array(
'checkbox_id' => 'post-blogs',
'have_published' => (bool) count($this->getPostBlogs())
);
Javelin::initBehavior(
'phame-post-blogs',
array(
'blogs' => $blogs_data,
'visibility' => $visibility_data,
));
if ($errors) { if ($errors) {
$error_view = id(new AphrontErrorView()) $error_view = id(new AphrontErrorView())
->setTitle('Errors saving post.') ->setTitle('Errors saving post.')
@ -352,76 +320,4 @@ final class PhamePostEditController
)); ));
} }
private function getBlogCheckboxControl(PhamePost $post) {
if ($post->getVisibility() == PhamePost::VISIBILITY_PUBLISHED) {
$control_style = null;
} else {
$control_style = 'display: none';
}
$control = id(new AphrontFormCheckboxControl())
->setLabel('Blogs')
->setControlID('post-blogs')
->setControlStyle($control_style);
$post_blogs = $this->getPostBlogs();
$user_blogs = $this->getUserBlogs();
$all_blogs = $post_blogs + $user_blogs;
$all_blogs = msort($all_blogs, 'getName');
foreach ($all_blogs as $phid => $blog) {
$control->addCheckbox(
'blogs[]',
$blog->getPHID(),
$blog->getName(),
isset($post_blogs[$phid])
);
}
return $control;
}
private function loadEdgesAndBlogs() {
$edge_types = array(PhabricatorEdgeConfig::TYPE_BLOGGER_HAS_BLOG);
$blogger_phid = $this->getRequest()->getUser()->getPHID();
$phids = array($blogger_phid);
if ($this->isPostEdit()) {
$edge_types[] = PhabricatorEdgeConfig::TYPE_POST_HAS_BLOG;
$phids[] = $this->getPostPHID();
}
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($phids)
->withEdgeTypes($edge_types)
->execute();
$all_blogs_assoc = array();
foreach ($phids as $phid) {
foreach ($edge_types as $type) {
$all_blogs_assoc += $edges[$phid][$type];
}
}
$blogs = id(new PhameBlogQuery())
->setViewer($this->getRequest()->getUser())
->withPHIDs(array_keys($all_blogs_assoc))
->execute();
$blogs = mpull($blogs, null, 'getPHID');
$user_blogs = array_intersect_key(
$blogs,
$edges[$blogger_phid][PhabricatorEdgeConfig::TYPE_BLOGGER_HAS_BLOG]
);
if ($this->isPostEdit()) {
$post_blogs = array_intersect_key(
$blogs,
$edges[$this->getPostPHID()][PhabricatorEdgeConfig::TYPE_POST_HAS_BLOG]
);
} else {
$post_blogs = array();
}
$this->setUserBlogs($user_blogs);
$this->setPostBlogs($post_blogs);
}
} }

View file

@ -155,14 +155,8 @@ final class PhamePostViewController extends PhameController {
$actions[] = 'edit'; $actions[] = 'edit';
} }
$blog = PhameBlog::getRequestBlog();
if ($blog) {
$skin = $blog->getSkinRenderer();
$skin->setBlog($blog);
$skin->setIsExternalDomain(true);
} else {
$skin = new PhabricatorBlogSkin(); $skin = new PhabricatorBlogSkin();
}
$skin $skin
->setUser($user) ->setUser($user)
->setRequestURI($request->getRequestURI()) ->setRequestURI($request->getRequestURI())

View file

@ -21,11 +21,17 @@
*/ */
final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids; private $phids;
private $domain; private $domain;
private $needBloggers; private $needBloggers;
public function withPHIDs($phids) { public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids; $this->phids = $phids;
return $this; return $this;
} }
@ -35,11 +41,6 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return $this; return $this;
} }
public function needBloggers($need_bloggers) {
$this->needBloggers = $need_bloggers;
return $this;
}
public function loadPage() { public function loadPage() {
$table = new PhameBlog(); $table = new PhameBlog();
$conn_r = $table->establishConnection('r'); $conn_r = $table->establishConnection('r');
@ -58,46 +59,19 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
$blogs = $table->loadAllFromArray($data); $blogs = $table->loadAllFromArray($data);
if ($blogs) {
if ($this->needBloggers) {
$this->loadBloggers($blogs);
}
}
return $blogs; return $blogs;
} }
private function loadBloggers(array $blogs) {
assert_instances_of($blogs, 'PhameBlog');
$blog_phids = mpull($blogs, 'getPHID');
$edge_types = array(PhabricatorEdgeConfig::TYPE_BLOG_HAS_BLOGGER);
$query = new PhabricatorEdgeQuery();
$query->withSourcePHIDs($blog_phids)
->withEdgeTypes($edge_types)
->execute();
$all_blogger_phids = $query->getDestinationPHIDs(
$blog_phids,
$edge_types
);
$handles = id(new PhabricatorObjectHandleData($all_blogger_phids))
->loadHandles();
foreach ($blogs as $blog) {
$blogger_phids = $query->getDestinationPHIDs(
array($blog->getPHID()),
$edge_types
);
$blog->attachBloggers(array_select_keys($handles, $blogger_phids));
}
}
private function buildWhereClause($conn_r) { private function buildWhereClause($conn_r) {
$where = array(); $where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ls)',
$this->ids);
}
if ($this->phids) { if ($this->phids) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn_r,

View file

@ -186,10 +186,6 @@ final class PhameBlog extends PhameDAO implements PhabricatorPolicyInterface {
return $this->getActionURI('posts'); return $this->getActionURI('posts');
} }
public function getViewURI() {
return $this->getActionURI('view');
}
public function getEditURI() { public function getEditURI() {
return $this->getActionURI('edit'); return $this->getActionURI('edit');
} }

View file

@ -1,103 +0,0 @@
<?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 PhameBlogListView extends AphrontView {
private $user;
private $blogs;
private $header;
public function setHeader($header) {
$this->header = $header;
return $this;
}
private function getHeader() {
return $this->header;
}
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
private function getUser() {
return $this->user;
}
public function setBlogs(array $blogs) {
assert_instances_of($blogs, 'PhameBlog');
$this->blogs = $blogs;
return $this;
}
private function getBlogs() {
return $this->blogs;
}
public function render() {
$user = $this->getUser();
$blogs = $this->getBlogs();
$panel = new AphrontPanelView();
if (empty($blogs)) {
$panel = id(new AphrontPanelView())
->setHeader('No blogs... Yet!')
->setCaption('Will you answer the call to phame?')
->setCreateButton('New Blog',
'/phame/blog/new');
return $panel->render();
}
$view = new PhabricatorObjectItemListView();
foreach ($blogs as $blog) {
$bloggers = $blog->getBloggers();
$item = id(new PhabricatorObjectItemView())
->setHeader($blog->getName())
->setHref($blog->getViewURI())
->addDetail(
'Custom Domain',
phutil_escape_html($blog->getDomain()));
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$blog,
PhabricatorPolicyCapability::CAN_EDIT);
if ($can_edit) {
$item->addAttribute(
phutil_render_tag(
'a',
array(
'class' => 'button small grey',
'href' => $blog->getEditURI(),
),
'Edit'));
}
$view->addItem($item);
}
$panel->setCreateButton('Create a Blog', '/phame/blog/new/');
$panel->setHeader($this->getHeader());
$panel->appendChild($view);
return $panel->render();
}
}

View file

@ -516,6 +516,29 @@ final class PhabricatorObjectHandleData {
$handles[$phid] = $handle; $handles[$phid] = $handle;
} }
break; break;
case PhabricatorPHIDConstants::PHID_TYPE_BLOG:
$blogs = id(new PhameBlogQuery())
->withPHIDs($phids)
->setViewer($this->viewer)
->execute();
$blogs = mpull($blogs, null, 'getPHID');
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($blogs[$phid])) {
$handle->setName('Unknown Blog');
} else {
$blog = $blogs[$phid];
$handle->setName($blog->getName());
$handle->setFullName($blog->getName());
$handle->setURI('/phame/blog/view/'.$blog->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
default: default:
$loader = null; $loader = null;
if (isset($external_loaders[$type])) { if (isset($external_loaders[$type])) {

View file

@ -748,38 +748,50 @@
background-position: 0px -7308px; background-position: 0px -7308px;
} }
.remarkup-assist-b { .action-new {
background-position: 0px -7325px; background-position: 0px -7325px;
} }
.action-world {
background-position: 0px -7342px;
}
.action-delete {
background-position: 0px -7359px;
}
.remarkup-assist-b {
background-position: 0px -7376px;
}
.remarkup-assist-code { .remarkup-assist-code {
background-position: 0px -7340px; background-position: 0px -7391px;
} }
.remarkup-assist-i { .remarkup-assist-i {
background-position: 0px -7355px; background-position: 0px -7406px;
} }
.remarkup-assist-image { .remarkup-assist-image {
background-position: 0px -7370px; background-position: 0px -7421px;
} }
.remarkup-assist-ol { .remarkup-assist-ol {
background-position: 0px -7385px; background-position: 0px -7436px;
} }
.remarkup-assist-tag { .remarkup-assist-tag {
background-position: 0px -7400px; background-position: 0px -7451px;
} }
.remarkup-assist-tt { .remarkup-assist-tt {
background-position: 0px -7415px; background-position: 0px -7466px;
} }
.remarkup-assist-ul { .remarkup-assist-ul {
background-position: 0px -7430px; background-position: 0px -7481px;
} }
.remarkup-assist-help { .remarkup-assist-help {
background-position: 0px -7445px; background-position: 0px -7496px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 142 KiB

View file

@ -1,23 +0,0 @@
/**
* @provides javelin-behavior-phame-post-blogs
* @requires javelin-behavior
* javelin-dom
*/
JX.behavior('phame-post-blogs', function(config) {
var visibility_select = JX.$(config.visibility.select_id);
var blogs_widget = JX.$(config.blogs.checkbox_id);
var visibilityCallback = function(e) {
if (visibility_select.value == config.visibility.published) {
JX.DOM.show(blogs_widget);
} else {
JX.DOM.hide(blogs_widget);
}
e.kill();
}
JX.DOM.listen(visibility_select, 'change', null, visibilityCallback);
});