From b072e937b5fccd17d91f312635e99fbcc03362f7 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 15 Oct 2012 14:50:12 -0700 Subject: [PATCH] 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 --- scripts/celerity/generate_sprites.php | 3 + src/__celerity_resource_map__.php | 78 +-------- src/__phutil_library_map__.php | 20 +-- .../AphrontApplicationConfiguration.php | 16 +- .../PhabricatorApplicationPhame.php | 12 +- .../phame/controller/PhameController.php | 36 +++- .../blog/PhameBlogDeleteController.php | 33 ++-- .../blog/PhameBlogEditController.php | 121 ++++--------- .../blog/PhameBlogListController.php | 105 ++++++++++++ .../blog/PhameBlogLiveController.php | 115 +++++++++++++ .../blog/PhameBlogViewController.php | 138 ++++++++++++--- .../blog/list/PhameAllBlogListController.php | 49 ------ .../blog/list/PhameBlogListBaseController.php | 71 -------- .../blog/list/PhameUserBlogListController.php | 69 -------- .../post/PhamePostEditController.php | 162 ++++-------------- .../post/PhamePostViewController.php | 10 +- .../phame/query/PhameBlogQuery.php | 54 ++---- src/applications/phame/storage/PhameBlog.php | 4 - .../phame/view/PhameBlogListView.php | 103 ----------- .../handle/PhabricatorObjectHandleData.php | 23 +++ webroot/rsrc/css/autosprite.css | 30 +++- webroot/rsrc/image/autosprite.png | Bin 143424 -> 145081 bytes .../js/application/phame/phame-post-blogs.js | 23 --- 23 files changed, 524 insertions(+), 751 deletions(-) create mode 100644 src/applications/phame/controller/blog/PhameBlogListController.php create mode 100644 src/applications/phame/controller/blog/PhameBlogLiveController.php delete mode 100644 src/applications/phame/controller/blog/list/PhameAllBlogListController.php delete mode 100644 src/applications/phame/controller/blog/list/PhameBlogListBaseController.php delete mode 100644 src/applications/phame/controller/blog/list/PhameUserBlogListController.php delete mode 100644 src/applications/phame/view/PhameBlogListView.php delete mode 100644 webroot/rsrc/js/application/phame/phame-post-blogs.js diff --git a/scripts/celerity/generate_sprites.php b/scripts/celerity/generate_sprites.php index 84b3337be0..a6f2b109b5 100755 --- a/scripts/celerity/generate_sprites.php +++ b/scripts/celerity/generate_sprites.php @@ -218,6 +218,9 @@ $action_map = array( 'subscribe-auto' => 'icon/unsubscribe.png', 'subscribe-add' => 'icon/subscribe.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) { diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 0299ad68c8..3226054bca 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -51,8 +51,8 @@ celerity_register_resource_map(array( ), '/rsrc/image/autosprite.png' => array( - 'hash' => '005c7630a31cb2ef6b1782d4eca08cd7', - 'uri' => '/res/005c7630/rsrc/image/autosprite.png', + 'hash' => 'b1a2597ab1d245a52e5c8783dffa5e26', + 'uri' => '/res/b1a2597a/rsrc/image/autosprite.png', 'disk' => '/rsrc/image/autosprite.png', 'type' => 'png', ), @@ -462,27 +462,6 @@ celerity_register_resource_map(array( 'disk' => '/rsrc/image/nyan.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' => array( 'hash' => 'ff7da044e6f923b8f569dec11f97e5e5', @@ -678,7 +657,7 @@ celerity_register_resource_map(array( ), 'autosprite-css' => array( - 'uri' => '/res/6c0c2948/rsrc/css/autosprite.css', + 'uri' => '/res/95e8f847/rsrc/css/autosprite.css', 'type' => 'css', 'requires' => array( @@ -1633,17 +1612,6 @@ celerity_register_resource_map(array( ), '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' => array( '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', ), - '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' => array( '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', ), - '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' => array( - 'uri' => '/res/2d18adca/rsrc/css/application/phame/phame.css', + 'uri' => '/res/2e4c86eb/rsrc/css/application/phame/phame.css', 'type' => 'css', 'requires' => array( diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 2a4a80544d..26ca311dbb 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1147,14 +1147,13 @@ phutil_register_library_map(array( 'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php', 'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php', 'PhabricatorXHProfSampleListView' => 'applications/xhprof/view/PhabricatorXHProfSampleListView.php', - 'PhameAllBlogListController' => 'applications/phame/controller/blog/list/PhameAllBlogListController.php', 'PhameAllPostListController' => 'applications/phame/controller/post/list/PhameAllPostListController.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', 'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php', 'PhameBlogDetailView' => 'applications/phame/view/PhameBlogDetailView.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', - 'PhameBlogListBaseController' => 'applications/phame/controller/blog/list/PhameBlogListBaseController.php', - 'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php', + 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', + 'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogSkin' => 'applications/phame/view/skins/PhameBlogSkin.php', 'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php', @@ -1171,7 +1170,6 @@ phutil_register_library_map(array( 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', - 'PhameUserBlogListController' => 'applications/phame/controller/blog/list/PhameUserBlogListController.php', 'PhameUserPostListController' => 'applications/phame/controller/post/list/PhameUserPostListController.php', 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php', @@ -2274,7 +2272,6 @@ phutil_register_library_map(array( 'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO', 'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController', 'PhabricatorXHProfSampleListView' => 'AphrontView', - 'PhameAllBlogListController' => 'PhameBlogListBaseController', 'PhameAllPostListController' => 'PhamePostListBaseController', 'PhameBlog' => array( @@ -2284,8 +2281,8 @@ phutil_register_library_map(array( 'PhameBlogDeleteController' => 'PhameController', 'PhameBlogDetailView' => 'AphrontView', 'PhameBlogEditController' => 'PhameController', - 'PhameBlogListBaseController' => 'PhameController', - 'PhameBlogListView' => 'AphrontView', + 'PhameBlogListController' => 'PhameController', + 'PhameBlogLiveController' => 'PhameController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogSkin' => 'AphrontView', 'PhameBlogViewController' => 'PhameController', @@ -2293,16 +2290,19 @@ phutil_register_library_map(array( 'PhameController' => 'PhabricatorController', 'PhameDAO' => 'PhabricatorLiskDAO', 'PhameDraftListController' => 'PhamePostListBaseController', - 'PhamePost' => 'PhameDAO', + 'PhamePost' => + array( + 0 => 'PhameDAO', + 1 => 'PhabricatorPolicyInterface', + ), 'PhamePostDeleteController' => 'PhameController', 'PhamePostDetailView' => 'AphrontView', 'PhamePostEditController' => 'PhameController', 'PhamePostListBaseController' => 'PhameController', 'PhamePostListView' => 'AphrontView', 'PhamePostPreviewController' => 'PhameController', - 'PhamePostQuery' => 'PhabricatorOffsetPagedQuery', + 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhamePostViewController' => 'PhameController', - 'PhameUserBlogListController' => 'PhameBlogListBaseController', 'PhameUserPostListController' => 'PhamePostListBaseController', 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 'PhortuneStripeBaseController' => 'PhabricatorController', diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php index a78555189f..dabe7e40e1 100644 --- a/src/aphront/configuration/AphrontApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontApplicationConfiguration.php @@ -140,7 +140,7 @@ abstract class AphrontApplicationConfiguration { try { $blog = id(new PhameBlogQuery()) - ->setViewer($request->getUser()) + ->setViewer(new PhabricatorUser()) ->withDomain($host) ->executeOne(); } catch (PhabricatorPolicyException $ex) { @@ -161,18 +161,10 @@ abstract class AphrontApplicationConfiguration { ); } - // 2 basic cases - // -- looking at a list of blog posts, path is nothing or '/' - // -- we have to fudge the URI in this case - // -- looking at an actual blog post, path is like - // /phame/posts//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(); - } + // TODO: Make this more flexible and modular so any application can + // do crazy stuff here if it wants. - PhameBlog::setRequestBlog($blog); + $path = '/phame/blog/live/'.$blog->getID().'/'.$path; $celerity = CelerityAPI::getStaticResourceResponse(); $celerity->setUseFullURI(true); diff --git a/src/applications/phame/application/PhabricatorApplicationPhame.php b/src/applications/phame/application/PhabricatorApplicationPhame.php index 5038c1cd9f..3ceb07f00c 100644 --- a/src/applications/phame/application/PhabricatorApplicationPhame.php +++ b/src/applications/phame/application/PhabricatorApplicationPhame.php @@ -58,13 +58,13 @@ final class PhabricatorApplicationPhame extends PhabricatorApplication { '' => 'PhameDraftListController', 'new/' => 'PhamePostEditController', ), + 'blog/(?:(?Puser|all)/)?' => 'PhameBlogListController', 'blog/' => array( - '' => 'PhameUserBlogListController', - 'all/' => 'PhameAllBlogListController', - 'new/' => 'PhameBlogEditController', - 'delete/(?P[^/]+)/' => 'PhameBlogDeleteController', - 'edit/(?P[^/]+)/' => 'PhameBlogEditController', - 'view/(?P[^/]+)/' => 'PhameBlogViewController', + 'delete/(?P[^/]+)/' => 'PhameBlogDeleteController', + 'edit/(?P[^/]+)/' => 'PhameBlogEditController', + 'view/(?P[^/]+)/' => 'PhameBlogViewController', + 'live/(?P[^/]+)/(?P.*)' => 'PhameBlogLiveController', + 'new/' => 'PhameBlogEditController', ), 'posts/' => array( '' => 'PhameUserPostListController', diff --git a/src/applications/phame/controller/PhameController.php b/src/applications/phame/controller/PhameController.php index c6d7f39b54..2b571f98cc 100644 --- a/src/applications/phame/controller/PhameController.php +++ b/src/applications/phame/controller/PhameController.php @@ -71,13 +71,16 @@ abstract class PhameController extends PhabricatorController { return $response->setContent($page->render()); } - private function renderSideNavFilterView($filter) { + protected function renderSideNavFilterView($filter) { $base_uri = new PhutilURI('/phame/'); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI($base_uri); - $nav->addLabel('Drafts'); - $nav->addFilter('post/new', - 'New Draft'); + $nav->addLabel('Create'); + $nav->addFilter('post/new', 'New Draft'); + $nav->addFilter('blog/new', 'New Blog'); + + $nav->addSpacer(); + $nav->addLabel('Posts'); $nav->addFilter('draft', 'My Drafts'); foreach ($this->getSideNavExtraDraftFilters() as $draft_filter) { @@ -85,9 +88,6 @@ abstract class PhameController extends PhabricatorController { $draft_filter['name'], idx($draft_filter, 'uri')); } - - $nav->addSpacer(); - $nav->addLabel('Posts'); $nav->addFilter('post', 'My Posts'); $nav->addFilter('post/all', @@ -123,7 +123,7 @@ abstract class PhameController extends PhabricatorController { protected function getSideNavBlogFilters() { return array( array( - 'key' => 'blog', + 'key' => 'blog/user', 'name' => 'My Blogs', ), array( @@ -154,4 +154,24 @@ abstract class PhameController extends PhabricatorController { ->setTitle('Meta thoughts and feelings'); 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; + } } diff --git a/src/applications/phame/controller/blog/PhameBlogDeleteController.php b/src/applications/phame/controller/blog/PhameBlogDeleteController.php index 1e1d22a99c..f0f60269b6 100644 --- a/src/applications/phame/controller/blog/PhameBlogDeleteController.php +++ b/src/applications/phame/controller/blog/PhameBlogDeleteController.php @@ -19,18 +19,10 @@ /** * @group phame */ -final class PhameBlogDeleteController -extends PhameController { +final class PhameBlogDeleteController extends PhameController { - private $phid; + private $id; - private function setBlogPHID($phid) { - $this->phid = $phid; - return $this; - } - private function getBlogPHID() { - return $this->phid; - } protected function getSideNavFilter() { return 'blog/delete/'.$this->getBlogPHID(); @@ -46,8 +38,7 @@ extends PhameController { } public function willProcessRequest(array $data) { - $phid = $data['phid']; - $this->setBlogPHID($phid); + $this->id = $data['id']; } public function processRequest() { @@ -56,13 +47,12 @@ extends PhameController { $blog = id(new PhameBlogQuery()) ->setViewer($user) - ->withPHIDs(array($this->getBlogPHID())) + ->withIDs(array($this->id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); - if (!$blog) { return new Aphront404Response(); } @@ -70,15 +60,20 @@ extends PhameController { if ($request->isFormPost()) { $blog->delete(); return id(new AphrontRedirectResponse()) - ->setURI('/phame/blog/?deleted'); + ->setURI($this->getApplicationURI()); } + $cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/'); + $dialog = id(new AphrontDialogView()) ->setUser($user) - ->setTitle('Delete blog?') - ->appendChild('Really delete this blog? It will be gone forever.') - ->addSubmitButton('Delete') - ->addCancelButton($blog->getEditURI()); + ->setTitle(pht('Delete blog?')) + ->appendChild( + pht( + 'Really delete the blog "%s"? It will be gone forever.', + $blog->getName())) + ->addSubmitButton(pht('Delete')) + ->addCancelButton($cancel_uri); return id(new AphrontDialogResponse())->setDialog($dialog); } diff --git a/src/applications/phame/controller/blog/PhameBlogEditController.php b/src/applications/phame/controller/blog/PhameBlogEditController.php index db5a4592ab..754e810fde 100644 --- a/src/applications/phame/controller/blog/PhameBlogEditController.php +++ b/src/applications/phame/controller/blog/PhameBlogEditController.php @@ -22,69 +22,25 @@ final class PhameBlogEditController extends PhameController { - private $phid; - 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; - } + private $id; protected function getSideNavFilter() { - if ($this->isBlogEdit()) { - $filter = 'blog/edit/'.$this->getBlogPHID(); - } else { - $filter = 'blog/new'; - } - return $filter; + return 'blog/edit/'.$this->id; } - 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) { - $phid = idx($data, 'phid'); - $this->setBlogPHID($phid); - $this->setIsBlogEdit((bool)$phid); + $this->id = idx($data, 'id'); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); - $e_name = true; - $e_custom_domain = null; - $errors = array(); - - if ($this->isBlogEdit()) { + if ($this->id) { $blog = id(new PhameBlogQuery()) ->setViewer($user) - ->withPHIDs(array($this->getBlogPHID())) + ->withIDs(array($this->id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_EDIT @@ -94,25 +50,26 @@ final class PhameBlogEditController return new Aphront404Response(); } - $submit_button = 'Save Changes'; - $delete_button = javelin_render_tag( - 'a', - array( - 'href' => $blog->getDeleteURI(), - 'class' => 'grey button', - 'sigil' => 'workflow', - ), - 'Delete Blog'); - $page_title = 'Edit Blog'; + $submit_button = pht('Save Changes'); + $page_title = pht('Edit Blog'); + $cancel_uri = $this->getApplicationURI('blog/view/'.$blog->getID().'/'); } else { $blog = id(new PhameBlog()) ->setCreatorPHID($user->getPHID()); - $blogger_tokens = array($user->getPHID() => $user->getFullName()); - $submit_button = 'Create Blog'; - $delete_button = null; - $page_title = 'Create Blog'; + + $blog->setViewPolicy(PhabricatorPolicies::POLICY_USER); + $blog->setEditPolicy(PhabricatorPolicies::POLICY_USER); + $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()) { $name = $request->getStr('name'); $description = $request->getStr('description'); @@ -121,10 +78,14 @@ final class PhameBlogEditController if (empty($name)) { $errors[] = 'You must give the blog a name.'; - $e_name = 'Required'; + $e_name = 'Required'; + } else { + $e_name = null; } + $blog->setName($name); $blog->setDescription($description); + if (!empty($custom_domain)) { $error = $blog->validateCustomDomain($custom_domain); if ($error) { @@ -147,25 +108,11 @@ final class PhameBlogEditController if (!$errors) { $blog->save(); - - $uri = new PhutilURI($blog->getViewURI()); - if ($this->isBlogEdit()) { - $uri->setQueryParam('edit', true); - } else { - $uri->setQueryParam('new', true); - } 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()) ->setViewer($user) ->setObject($blog) @@ -173,6 +120,7 @@ final class PhameBlogEditController $form = id(new AphrontFormView()) ->setUser($user) + ->setFlexible(true) ->appendChild( id(new AphrontFormTextControl()) ->setLabel('Name') @@ -227,12 +175,10 @@ final class PhameBlogEditController ) ->appendChild( id(new AphrontFormSubmitControl()) - ->addCancelButton('/phame/blog/') + ->addCancelButton($cancel_uri) ->setValue($submit_button) ); - $panel->appendChild($form); - if ($errors) { $error_view = id(new AphrontErrorView()) ->setTitle('Form Errors') @@ -241,12 +187,15 @@ final class PhameBlogEditController $error_view = null; } - $this->setShowSideNav(true); - return $this->buildStandardPageResponse( + $nav = $this->renderSideNavFilterView(null); + $nav->appendChild( array( $error_view, - $panel, - ), + $form, + )); + + return $this->buildApplicationPage( + $nav, array( 'title' => $page_title, )); diff --git a/src/applications/phame/controller/blog/PhameBlogListController.php b/src/applications/phame/controller/blog/PhameBlogListController.php new file mode 100644 index 0000000000..fb8665c1fa --- /dev/null +++ b/src/applications/phame/controller/blog/PhameBlogListController.php @@ -0,0 +1,105 @@ +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; + } + +} diff --git a/src/applications/phame/controller/blog/PhameBlogLiveController.php b/src/applications/phame/controller/blog/PhameBlogLiveController.php new file mode 100644 index 0000000000..7982b06d18 --- /dev/null +++ b/src/applications/phame/controller/blog/PhameBlogLiveController.php @@ -0,0 +1,115 @@ +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('

'.$error.'

'); + } + + 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; + } + +} diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index 6be892a40c..68bf5f6f98 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -21,15 +21,7 @@ */ final class PhameBlogViewController extends PhameController { - private $blogPHID; - - private function setBlogPHID($blog_phid) { - $this->blogPHID = $blog_phid; - return $this; - } - private function getBlogPHID() { - return $this->blogPHID; - } + private $id; protected function getSideNavFilter() { $filter = 'blog/view/'.$this->getBlogPHID(); @@ -45,7 +37,7 @@ final class PhameBlogViewController extends PhameController { } public function willProcessRequest(array $data) { - $this->setBlogPHID(idx($data, 'phid')); + $this->id = $data['id']; } public function processRequest() { @@ -54,36 +46,128 @@ final class PhameBlogViewController extends PhameController { $blog = id(new PhameBlogQuery()) ->setViewer($user) - ->withPHIDs(array($this->getBlogPHID())) + ->withIDs(array($this->id)) ->executeOne(); if (!$blog) { return new Aphront404Response(); } + $pager = id(new AphrontCursorPagerView()) + ->readFromRequest($request); + $posts = id(new PhamePostQuery()) ->setViewer($user) ->withBlogPHIDs(array($blog->getPHID())) - ->execute(); + ->executeWithCursorPager($pager); - $skin = $blog->getSkinRenderer(); - $skin - ->setUser($this->getRequest()->getUser()) - ->setBloggers($this->loadViewerHandles(mpull($posts, 'getBloggerPHID'))) - ->setPosts($posts) - ->setBlog($blog) - ->setRequestURI($this->getRequest()->getRequestURI()); + $nav = $this->renderSideNavFilterView(null); - $this->setShowSideNav(false); - $this->setShowChrome($skin->getShowChrome()); - $this->setDeviceReady($skin->getDeviceReady()); - $skin->setIsExternalDomain($blog->getDomain() == $request->getHost()); + $header = id(new PhabricatorHeaderView()) + ->setHeader($blog->getName()); - 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( - $skin - ), + $header, + $actions, + $properties, + $post_list, + )); + + return $this->buildApplicationPage( + $nav, array( - 'title' => $blog->getName(), + 'device' => true, + '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; + } + } diff --git a/src/applications/phame/controller/blog/list/PhameAllBlogListController.php b/src/applications/phame/controller/blog/list/PhameAllBlogListController.php deleted file mode 100644 index 04010f4aa5..0000000000 --- a/src/applications/phame/controller/blog/list/PhameAllBlogListController.php +++ /dev/null @@ -1,49 +0,0 @@ -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(); - } - -} diff --git a/src/applications/phame/controller/blog/list/PhameBlogListBaseController.php b/src/applications/phame/controller/blog/list/PhameBlogListBaseController.php deleted file mode 100644 index 5c509410a3..0000000000 --- a/src/applications/phame/controller/blog/list/PhameBlogListBaseController.php +++ /dev/null @@ -1,71 +0,0 @@ -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(), - )); - } -} diff --git a/src/applications/phame/controller/blog/list/PhameUserBlogListController.php b/src/applications/phame/controller/blog/list/PhameUserBlogListController.php deleted file mode 100644 index 2059423607..0000000000 --- a/src/applications/phame/controller/blog/list/PhameUserBlogListController.php +++ /dev/null @@ -1,69 +0,0 @@ -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(); - } - -} diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php index 5cf23497b6..68e03c6ba7 100644 --- a/src/applications/phame/controller/post/PhamePostEditController.php +++ b/src/applications/phame/controller/post/PhamePostEditController.php @@ -140,16 +140,28 @@ final class PhamePostEditController 'Delete '.$post_noun); $page_title = 'Edit '.$post_noun; } 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()) ->setVisibility(PhamePost::VISIBILITY_DRAFT); - $cancel_uri = '/phame/draft/'; - $submit_button = 'Create Draft'; + $cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/'); + + $submit_button = pht('Create Draft'); $delete_button = null; - $page_title = 'Create Draft'; + $page_title = pht('Create Draft'); } + $this->setPost($post); - $this->loadEdgesAndBlogs(); if ($request->isFormPost()) { $saved = true; @@ -182,48 +194,19 @@ final class PhamePostEditController $e_title = 'Required'; } - $blogs_published = array_keys($this->getPostBlogs()); - $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)) { + if (!$errors) { try { $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(); - + $uri = new PhutilURI($post->getViewURI($user->getUsername())); + $uri->setQueryParam('saved', true); + return id(new AphrontRedirectResponse()) + ->setURI($uri); } 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->setQueryParam('saved', true); - return id(new AphrontRedirectResponse()) - ->setURI($uri); } } @@ -234,8 +217,16 @@ final class PhamePostEditController $panel->addButton($delete_button); } + $handle = PhabricatorObjectHandleData::loadOneHandle( + $post->getBlogPHID(), + $user); + $form = id(new AphrontFormView()) ->setUser($user) + ->appendChild( + id(new AphrontFormMarkupControl()) + ->setLabel('Blog') + ->setValue($handle->renderLink())) ->appendChild( id(new AphrontFormTextControl()) ->setLabel('Title') @@ -271,9 +262,6 @@ final class PhamePostEditController ->setOptions(PhamePost::getVisibilityOptionsForSelect()) ->setID('post-visibility') ) - ->appendChild( - $this->getBlogCheckboxControl($post) - ) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel('Comments Widget') @@ -312,26 +300,6 @@ final class PhamePostEditController '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) { $error_view = id(new AphrontErrorView()) ->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); - } } diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php index 0f225d1599..02c17a8f71 100644 --- a/src/applications/phame/controller/post/PhamePostViewController.php +++ b/src/applications/phame/controller/post/PhamePostViewController.php @@ -155,14 +155,8 @@ final class PhamePostViewController extends PhameController { $actions[] = 'edit'; } - $blog = PhameBlog::getRequestBlog(); - if ($blog) { - $skin = $blog->getSkinRenderer(); - $skin->setBlog($blog); - $skin->setIsExternalDomain(true); - } else { - $skin = new PhabricatorBlogSkin(); - } + $skin = new PhabricatorBlogSkin(); + $skin ->setUser($user) ->setRequestURI($request->getRequestURI()) diff --git a/src/applications/phame/query/PhameBlogQuery.php b/src/applications/phame/query/PhameBlogQuery.php index ae58c28c1b..8dff47795c 100644 --- a/src/applications/phame/query/PhameBlogQuery.php +++ b/src/applications/phame/query/PhameBlogQuery.php @@ -21,11 +21,17 @@ */ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { + private $ids; private $phids; private $domain; private $needBloggers; - public function withPHIDs($phids) { + public function withIDs(array $ids) { + $this->ids = $ids; + return $this; + } + + public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } @@ -35,11 +41,6 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { return $this; } - public function needBloggers($need_bloggers) { - $this->needBloggers = $need_bloggers; - return $this; - } - public function loadPage() { $table = new PhameBlog(); $conn_r = $table->establishConnection('r'); @@ -58,46 +59,19 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { $blogs = $table->loadAllFromArray($data); - if ($blogs) { - if ($this->needBloggers) { - $this->loadBloggers($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) { $where = array(); + if ($this->ids) { + $where[] = qsprintf( + $conn_r, + 'id IN (%Ls)', + $this->ids); + } + if ($this->phids) { $where[] = qsprintf( $conn_r, diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php index 83ac1f074b..16905a813d 100644 --- a/src/applications/phame/storage/PhameBlog.php +++ b/src/applications/phame/storage/PhameBlog.php @@ -186,10 +186,6 @@ final class PhameBlog extends PhameDAO implements PhabricatorPolicyInterface { return $this->getActionURI('posts'); } - public function getViewURI() { - return $this->getActionURI('view'); - } - public function getEditURI() { return $this->getActionURI('edit'); } diff --git a/src/applications/phame/view/PhameBlogListView.php b/src/applications/phame/view/PhameBlogListView.php deleted file mode 100644 index 997aa8618c..0000000000 --- a/src/applications/phame/view/PhameBlogListView.php +++ /dev/null @@ -1,103 +0,0 @@ -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(); - } -} diff --git a/src/applications/phid/handle/PhabricatorObjectHandleData.php b/src/applications/phid/handle/PhabricatorObjectHandleData.php index 1d1beb0b98..636c02b302 100644 --- a/src/applications/phid/handle/PhabricatorObjectHandleData.php +++ b/src/applications/phid/handle/PhabricatorObjectHandleData.php @@ -516,6 +516,29 @@ final class PhabricatorObjectHandleData { $handles[$phid] = $handle; } 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: $loader = null; if (isset($external_loaders[$type])) { diff --git a/webroot/rsrc/css/autosprite.css b/webroot/rsrc/css/autosprite.css index 233b280681..e26de1e87e 100644 --- a/webroot/rsrc/css/autosprite.css +++ b/webroot/rsrc/css/autosprite.css @@ -748,38 +748,50 @@ background-position: 0px -7308px; } -.remarkup-assist-b { +.action-new { 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 { - background-position: 0px -7340px; + background-position: 0px -7391px; } .remarkup-assist-i { - background-position: 0px -7355px; + background-position: 0px -7406px; } .remarkup-assist-image { - background-position: 0px -7370px; + background-position: 0px -7421px; } .remarkup-assist-ol { - background-position: 0px -7385px; + background-position: 0px -7436px; } .remarkup-assist-tag { - background-position: 0px -7400px; + background-position: 0px -7451px; } .remarkup-assist-tt { - background-position: 0px -7415px; + background-position: 0px -7466px; } .remarkup-assist-ul { - background-position: 0px -7430px; + background-position: 0px -7481px; } .remarkup-assist-help { - background-position: 0px -7445px; + background-position: 0px -7496px; } diff --git a/webroot/rsrc/image/autosprite.png b/webroot/rsrc/image/autosprite.png index c8a56e236738b76b6eeef112c3e5e14c9fc63f3e..35b9978462331503b68147e952b1cc66fd37e7e6 100644 GIT binary patch delta 5001 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