diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index cd786089ed..b2564116cb 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1040,6 +1040,8 @@ phutil_register_library_map(array( 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/PhabricatorXHProfProfileSymbolView.php', 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/PhabricatorXHProfProfileTopLevelView.php', 'PhabricatorXHProfProfileView' => 'applications/xhprof/view/PhabricatorXHProfProfileView.php', + 'PhameAllBloggersPostListController' => 'applications/phame/controller/post/list/PhameAllBloggersPostListController.php', + 'PhameBloggerPostListController' => 'applications/phame/controller/post/list/PhameBloggerPostListController.php', 'PhameController' => 'applications/phame/controller/PhameController.php', 'PhameDAO' => 'applications/phame/storage/PhameDAO.php', 'PhameDraftListController' => 'applications/phame/controller/post/list/PhameDraftListController.php', @@ -1048,11 +1050,11 @@ phutil_register_library_map(array( 'PhamePostDetailView' => 'applications/phame/view/PhamePostDetailView.php', 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 'PhamePostListBaseController' => 'applications/phame/controller/post/list/PhamePostListBaseController.php', - 'PhamePostListController' => 'applications/phame/controller/post/list/PhamePostListController.php', 'PhamePostListView' => 'applications/phame/view/PhamePostListView.php', 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', + 'PhameUserPostListController' => 'applications/phame/controller/post/list/PhameUserPostListController.php', 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php', 'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/PhortuneStripePaymentFormView.php', @@ -2001,6 +2003,8 @@ phutil_register_library_map(array( 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileView' => 'AphrontView', + 'PhameAllBloggersPostListController' => 'PhamePostListBaseController', + 'PhameBloggerPostListController' => 'PhamePostListBaseController', 'PhameController' => 'PhabricatorController', 'PhameDAO' => 'PhabricatorLiskDAO', 'PhameDraftListController' => 'PhamePostListBaseController', @@ -2009,11 +2013,11 @@ phutil_register_library_map(array( 'PhamePostDetailView' => 'AphrontView', 'PhamePostEditController' => 'PhameController', 'PhamePostListBaseController' => 'PhameController', - 'PhamePostListController' => 'PhamePostListBaseController', 'PhamePostListView' => 'AphrontView', 'PhamePostPreviewController' => 'PhameController', 'PhamePostQuery' => 'PhabricatorOffsetPagedQuery', 'PhamePostViewController' => 'PhameController', + 'PhameUserPostListController' => 'PhamePostListBaseController', 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 'PhortuneStripeBaseController' => 'PhabricatorController', 'PhortuneStripePaymentFormView' => 'AphrontView', diff --git a/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php index 300dcdd3eb..c250beaf12 100644 --- a/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php @@ -381,9 +381,9 @@ class AphrontDefaultApplicationConfiguration ), '/phame/' => array( - '' => 'PhamePostListController', + '' => 'PhameAllBloggersPostListController', 'post/' => array( - '' => 'PhamePostListController', + '' => 'PhameUserPostListController', 'delete/(?P[^/]+)/' => 'PhamePostDeleteController', 'edit/(?P[^/]+)/' => 'PhamePostEditController', 'new/' => 'PhamePostEditController', @@ -395,8 +395,8 @@ class AphrontDefaultApplicationConfiguration 'new/' => 'PhamePostEditController', ), 'posts/' => array( - '' => 'PhamePostListController', - '(?P\w+)/' => 'PhamePostListController', + '' => 'PhameUserPostListController', + '(?P\w+)/' => 'PhameBloggerPostListController', '(?P\w+)/(?P.+/)' => 'PhamePostViewController', ), diff --git a/src/applications/phame/controller/PhameController.php b/src/applications/phame/controller/PhameController.php index 67ce808a90..2f5c451667 100644 --- a/src/applications/phame/controller/PhameController.php +++ b/src/applications/phame/controller/PhameController.php @@ -60,8 +60,9 @@ abstract class PhameController extends PhabricatorController { } private function renderSideNavFilterView($filter) { + $base_uri = new PhutilURI('/phame/'); $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI('/phame/')); + $nav->setBaseURI($base_uri); $nav->addLabel('Drafts'); $nav->addFilter('post/new', 'New Draft'); @@ -71,12 +72,16 @@ abstract class PhameController extends PhabricatorController { $nav->addLabel('Posts'); $nav->addFilter('post', 'My Posts'); + $nav->addFilter('everyone', + 'Everyone', + $base_uri); foreach ($this->getSideNavExtraPostFilters() as $post_filter) { $nav->addFilter($post_filter['key'], - $post_filter['name']); + $post_filter['name'], + idx($post_filter, 'uri')); } - $nav->selectFilter($filter, 'post'); + $nav->selectFilter($filter); return $nav; } diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php index 6b80fdc42f..3d1c005c96 100644 --- a/src/applications/phame/controller/post/PhamePostEditController.php +++ b/src/applications/phame/controller/post/PhamePostEditController.php @@ -99,7 +99,7 @@ extends PhameController { $post = id(new PhamePost()) ->setBloggerPHID($user->getPHID()) ->setVisibility(PhamePost::VISIBILITY_DRAFT); - $cancel_uri = '/phame'; + $cancel_uri = '/phame/'; $submit_button = 'Create Post'; $delete_button = null; $page_title = 'Create Post'; diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php index 94db9b16ad..9122ea682e 100644 --- a/src/applications/phame/controller/post/PhamePostViewController.php +++ b/src/applications/phame/controller/post/PhamePostViewController.php @@ -60,6 +60,12 @@ extends PhameController { return $filters; } + public function shouldRequireLogin() { + // TODO -- get policy logic going + // return PhabricatorEnv::getEnvConfig('policy.allow-public'); + return true; + } + public function willProcessRequest(array $data) { $this->setPostPHID(idx($data, 'phid')); $this->setPhameTitle(idx($data, 'phametitle')); diff --git a/src/applications/phame/controller/post/list/PhameAllBloggersPostListController.php b/src/applications/phame/controller/post/list/PhameAllBloggersPostListController.php new file mode 100644 index 0000000000..c851ca092a --- /dev/null +++ b/src/applications/phame/controller/post/list/PhameAllBloggersPostListController.php @@ -0,0 +1,95 @@ +getRequest()->getUser(); + + $new_link = phutil_render_tag( + 'a', + array( + 'href' => '/phame/post/new/', + 'class' => 'button green', + ), + 'write a blog post' + ); + + $remarkup_link = phutil_render_tag( + 'a', + array( + 'href' => + PhabricatorEnv::getDoclink('article/Remarkup_Reference.html'), + ), + 'remarkup' + ); + + $guide_link = phutil_render_tag( + 'a', + array( + 'href' => PhabricatorEnv::getDoclink('article/Phame_User_Guide.html'), + ), + 'Phame user guide' + ); + + $notices = array( + 'Seek phame and '.$new_link, + 'Use '.$remarkup_link.' for maximal elegance, grace, and style. ', + 'If you need more help try the '.$guide_link.'.', + ); + + $notice_view = id(new AphrontErrorView()) + ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) + ->setTitle('Meta thoughts and feelings'); + foreach ($notices as $notice) { + $notice_view->appendChild('

'.$notice.'

'); + } + + return $notice_view; + } + + public function processRequest() { + $user = $this->getRequest()->getUser(); + + $query = new PhamePostQuery(); + $query->withVisibility(PhamePost::VISIBILITY_PUBLISHED); + $this->setPhamePostQuery($query); + + $this->setActions(array('view')); + + $page_title = 'Posts by Everyone'; + $this->setPageTitle($page_title); + + $this->setShowSideNav(true); + + return $this->buildPostListPageResponse(); + } + +} diff --git a/src/applications/phame/controller/post/list/PhameBloggerPostListController.php b/src/applications/phame/controller/post/list/PhameBloggerPostListController.php new file mode 100644 index 0000000000..d6932caa4f --- /dev/null +++ b/src/applications/phame/controller/post/list/PhameBloggerPostListController.php @@ -0,0 +1,74 @@ +bloggerName = $blogger_name; + return $this; + } + private function getBloggerName() { + return $this->bloggerName; + } + + public function shouldRequireLogin() { + // TODO -- get policy logic going + // return PhabricatorEnv::getEnvConfig('policy.allow-public'); + return true; + } + + public function willProcessRequest(array $data) { + $this->setBloggerName(idx($data, 'bloggername')); + } + + public function processRequest() { + $user = $this->getRequest()->getUser(); + + $blogger = id(new PhabricatorUser())->loadOneWhere( + 'username = %s', + $this->getBloggerName()); + if (!$blogger) { + return new Aphront404Response(); + } + $blogger_phid = $blogger->getPHID(); + if ($blogger_phid == $user->getPHID()) { + $actions = array('view', 'edit'); + } else { + $actions = array('view'); + } + $this->setActions($actions); + + $query = new PhamePostQuery(); + $query->withBloggerPHID($blogger_phid); + $query->withVisibility(PhamePost::VISIBILITY_PUBLISHED); + $this->setPhamePostQuery($query); + + $page_title = 'Posts by '.$this->getBloggerName(); + $this->setPageTitle($page_title); + + $this->setShowSideNav(false); + + return $this->buildPostListPageResponse(); + } +} diff --git a/src/applications/phame/controller/post/list/PhameDraftListController.php b/src/applications/phame/controller/post/list/PhameDraftListController.php index c8bb668944..7eccbf9f14 100644 --- a/src/applications/phame/controller/post/list/PhameDraftListController.php +++ b/src/applications/phame/controller/post/list/PhameDraftListController.php @@ -22,8 +22,34 @@ final class PhameDraftListController extends PhamePostListBaseController { + public function shouldRequireLogin() { + return true; + } + + protected function getSideNavFilter() { + return 'draft'; + } + + protected function isDraft() { + return true; + } + public function processRequest() { - $this->setIsDraft(true); - return parent::processRequest(); + $user = $this->getRequest()->getUser(); + $phid = $user->getPHID(); + + $query = new PhamePostQuery(); + $query->withBloggerPHID($phid); + $query->withVisibility(PhamePost::VISIBILITY_DRAFT); + $this->setPhamePostQuery($query); + + $actions = array('view', 'edit'); + $this->setActions($actions); + + $this->setPageTitle('My Drafts'); + + $this->setShowSideNav(true); + + return $this->buildPostListPageResponse(); } } diff --git a/src/applications/phame/controller/post/list/PhamePostListBaseController.php b/src/applications/phame/controller/post/list/PhamePostListBaseController.php index 00f8d053bb..21da11b2a5 100644 --- a/src/applications/phame/controller/post/list/PhamePostListBaseController.php +++ b/src/applications/phame/controller/post/list/PhamePostListBaseController.php @@ -22,106 +22,87 @@ abstract class PhamePostListBaseController extends PhameController { - private $bloggerName; - private $isDraft; + private $phamePostQuery; + private $actions; + private $pageTitle; - private function setBloggerName($blogger_name) { - $this->bloggerName = $blogger_name; + protected function setPageTitle($page_title) { + $this->pageTitle = $page_title; return $this; } - private function getBloggerName() { - return $this->bloggerName; + private function getPageTitle() { + return $this->pageTitle; } - protected function getSideNavExtraPostFilters() { - if ($this->isDraft() || !$this->getBloggerName()) { - return array(); - } - - return - array(array('key' => $this->getSideNavFilter(), - 'name' => 'Posts by '.$this->getBloggerName())); - } - - protected function getSideNavFilter() { - if ($this->getBloggerName()) { - $filter = 'posts/'.$this->getBloggerName(); - } else if ($this->isDraft()) { - $filter = 'draft'; - } else { - $filter = 'posts'; - } - return $filter; - } - - private function isDraft() { - return (bool) $this->isDraft; - } - protected function setIsDraft($is_draft) { - $this->isDraft = $is_draft; + protected function setActions($actions) { + $this->actions = $actions; return $this; } - - public function willProcessRequest(array $data) { - $this->setBloggerName(idx($data, 'bloggername')); + private function getActions() { + return $this->actions; } - public function processRequest() { + protected function setPhamePostQuery(PhamePostQuery $query) { + $this->phamePostQuery = $query; + return $this; + } + private function getPhamePostQuery() { + return $this->phamePostQuery; + } + + protected function isDraft() { + return false; + } + + protected function getPager() { $request = $this->getRequest(); - $user = $request->getUser(); $pager = new AphrontPagerView(); $page_size = 50; $pager->setURI($request->getRequestURI(), 'offset'); $pager->setPageSize($page_size); $pager->setOffset($request->getInt('offset')); - if ($this->getBloggerName()) { - $blogger = id(new PhabricatorUser())->loadOneWhere( - 'username = %s', - $this->getBloggerName()); - if (!$blogger) { - return new Aphront404Response(); - } - $page_title = 'Posts by '.$this->getBloggerName(); - if ($blogger->getPHID() == $user->getPHID()) { - $actions = array('view', 'edit'); - } else { - $actions = array('view'); - } - $this->setShowSideNav(false); - } else { - $blogger = $user; - $page_title = 'Posts by '.$user->getUserName(); - $actions = array('view', 'edit'); - $this->setShowSideNav(true); + return $pager; + } + + protected function getNoticeView() { + return null; + } + + private function loadBloggersFromPosts(array $posts) { + assert_instances_of($posts, 'PhamePost'); + if (empty($posts)) { + return array(); } - $phid = $blogger->getPHID(); - // user gets to see their own unpublished stuff - if ($phid == $user->getPHID() && $this->isDraft()) { - $post_visibility = PhamePost::VISIBILITY_DRAFT; - } else { - $post_visibility = PhamePost::VISIBILITY_PUBLISHED; - } - $query = new PhamePostQuery(); - $query->withBloggerPHID($phid); - $query->withVisibility($post_visibility); - $posts = $query->executeWithPager($pager); - $bloggers = array($blogger->getPHID() => $blogger); + + $blogger_phids = mpull($posts, 'getBloggerPHID', 'getBloggerPHID'); + + return + id(new PhabricatorObjectHandleData($blogger_phids))->loadHandles(); + } + + protected function buildPostListPageResponse() { + $pager = $this->getPager(); + $query = $this->getPhamePostQuery(); + $posts = $query->executeWithPager($pager); + + $bloggers = $this->loadBloggersFromPosts($posts); $panel = id(new PhamePostListView()) - ->setUser($user) + ->setUser($this->getRequest()->getUser()) ->setBloggers($bloggers) ->setPosts($posts) - ->setActions($actions) + ->setActions($this->getActions()) ->setDraftList($this->isDraft()); return $this->buildStandardPageResponse( array( + $this->getNoticeView(), $panel, $pager ), array( - 'title' => $page_title, + 'title' => $this->getPageTitle(), )); } } diff --git a/src/applications/phame/controller/post/list/PhamePostListController.php b/src/applications/phame/controller/post/list/PhamePostListController.php deleted file mode 100644 index 7923e52b56..0000000000 --- a/src/applications/phame/controller/post/list/PhamePostListController.php +++ /dev/null @@ -1,29 +0,0 @@ -setIsDraft(false); - return parent::processRequest(); - } -} diff --git a/src/applications/phame/controller/post/list/PhameUserPostListController.php b/src/applications/phame/controller/post/list/PhameUserPostListController.php new file mode 100644 index 0000000000..ea25cf6390 --- /dev/null +++ b/src/applications/phame/controller/post/list/PhameUserPostListController.php @@ -0,0 +1,89 @@ +getRequest()->getUser(); + + $new_link = phutil_render_tag( + 'a', + array( + 'href' => '/phame/post/new/', + 'class' => 'button green', + ), + 'write another blog post' + ); + + $pretty_uri = PhabricatorEnv::getProductionURI( + '/phame/posts/'.$user->getUserName().'/'); + $pretty_link = phutil_render_tag( + 'a', + array( + 'href' => (string) $pretty_uri + ), + (string) $pretty_uri + ); + + $notices = array( + 'Seek even more phame and '.$new_link, + 'Published posts also appear at the awesome, world-accessible '. + 'URI: '.$pretty_link + ); + + $notice_view = id(new AphrontErrorView()) + ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) + ->setTitle('Meta thoughts and feelings'); + foreach ($notices as $notice) { + $notice_view->appendChild('

'.$notice.'

'); + } + + return $notice_view; + } + + public function processRequest() { + $user = $this->getRequest()->getUser(); + $phid = $user->getPHID(); + + $query = new PhamePostQuery(); + $query->withBloggerPHID($phid); + $query->withVisibility(PhamePost::VISIBILITY_PUBLISHED); + $this->setPhamePostQuery($query); + + $actions = array('view', 'edit'); + $this->setActions($actions); + + $this->setPageTitle('My Posts'); + + $this->setShowSideNav(true); + + return $this->buildPostListPageResponse(); + } +} diff --git a/src/applications/phame/query/PhamePostQuery.php b/src/applications/phame/query/PhamePostQuery.php index aa3f95c150..31c587efcb 100644 --- a/src/applications/phame/query/PhamePostQuery.php +++ b/src/applications/phame/query/PhamePostQuery.php @@ -19,12 +19,24 @@ final class PhamePostQuery extends PhabricatorOffsetPagedQuery { private $bloggerPHID; + private $withoutBloggerPHID; private $visibility; + /** + * Mutually exlusive with @{method:withoutBloggerPHID}. + * + * @{method:withBloggerPHID} wins because being positive and inclusive is + * cool. + */ public function withBloggerPHID($blogger_phid) { $this->bloggerPHID = $blogger_phid; return $this; } + public function withoutBloggerPHID($blogger_phid) { + $this->withoutBloggerPHID = $blogger_phid; + return $this; + } + public function withVisibility($visibility) { $this->visibility = $visibility; return $this; @@ -60,6 +72,12 @@ final class PhamePostQuery extends PhabricatorOffsetPagedQuery { 'bloggerPHID = %s', $this->bloggerPHID ); + } else if ($this->withoutBloggerPHID) { + $where[] = qsprintf( + $conn_r, + 'bloggerPHID != %s', + $this->withoutBloggerPHID + ); } if ($this->visibility !== null) { diff --git a/src/applications/phame/view/PhamePostDetailView.php b/src/applications/phame/view/PhamePostDetailView.php index e010dd1918..ebf5089acb 100644 --- a/src/applications/phame/view/PhamePostDetailView.php +++ b/src/applications/phame/view/PhamePostDetailView.php @@ -79,7 +79,7 @@ final class PhamePostDetailView extends AphrontView { $uri = '/phame/draft/'; $label = 'Back to Your Drafts'; } else { - $uri = '/phame/posts/'.$blogger->getUsername(); + $uri = '/phame/posts/'.$blogger->getUsername().'/'; $label = 'More Posts by '.phutil_escape_html($blogger->getUsername()); } $button = phutil_render_tag( @@ -101,6 +101,14 @@ final class PhamePostDetailView extends AphrontView { phabricator_datetime($post->getDateModified(), $user); } + $caption .= ' by '.phutil_render_tag( + 'a', + array( + 'href' => new PhutilURI('/p/'.$blogger->getUsername().'/'), + ), + phutil_escape_html($blogger->getUsername()) + ).'.'; + if ($this->isPreview()) { $width = AphrontPanelView::WIDTH_FULL; } else { diff --git a/src/applications/phame/view/PhamePostListView.php b/src/applications/phame/view/PhamePostListView.php index ebda5bde9f..5726cdafea 100644 --- a/src/applications/phame/view/PhamePostListView.php +++ b/src/applications/phame/view/PhamePostListView.php @@ -59,7 +59,7 @@ final class PhamePostListView extends AphrontView { return $this->posts; } public function setBloggers(array $bloggers) { - assert_instances_of($bloggers, 'PhabricatorUser'); + assert_instances_of($bloggers, 'PhabricatorObjectHandle'); $this->bloggers = $bloggers; return $this; } @@ -99,17 +99,18 @@ final class PhamePostListView extends AphrontView { foreach ($posts as $post) { $blogger_phid = $post->getBloggerPHID(); $blogger = $bloggers[$blogger_phid]; + $blogger_link = $blogger->renderLink(); $updated = phabricator_datetime($post->getDateModified(), $user); $body = $engine->markupText($post->getBody()); $panel = id(new AphrontPanelView()) ->setHeader(phutil_escape_html($post->getTitle())) - ->setCaption('Last updated '.$updated) + ->setCaption('Last updated '.$updated.' by '.$blogger_link.'.') ->appendChild('
'.$body.'
'); foreach ($actions as $action) { switch ($action) { case 'view': - $uri = $post->getViewURI($blogger->getUsername()); + $uri = $post->getViewURI($blogger->getName()); $label = 'View '.$noun; break; case 'edit':