@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Phame - add an "Everyone but Me" view and make published posts truly accessible to the whole world.

Summary:
accessibility covers not only a given post but also the various "published" views.

to keep the code relative clean, this diff also splits up the post list controller logic quite a bit. this also feels like good preparation for some other work around introducing "blogs" which are collections of published posts from bloggers with some fancy features around that.

Test Plan: clicked around various parts of the Phame application as a logged in user, a logged in user with no personal posts, and without any user logged in at all. various views all seemed reasonable.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T1373

Differential Revision: https://secure.phabricator.com/D2898

+390 -112
+6 -2
src/__phutil_library_map__.php
··· 1040 1040 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/PhabricatorXHProfProfileSymbolView.php', 1041 1041 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/PhabricatorXHProfProfileTopLevelView.php', 1042 1042 'PhabricatorXHProfProfileView' => 'applications/xhprof/view/PhabricatorXHProfProfileView.php', 1043 + 'PhameAllBloggersPostListController' => 'applications/phame/controller/post/list/PhameAllBloggersPostListController.php', 1044 + 'PhameBloggerPostListController' => 'applications/phame/controller/post/list/PhameBloggerPostListController.php', 1043 1045 'PhameController' => 'applications/phame/controller/PhameController.php', 1044 1046 'PhameDAO' => 'applications/phame/storage/PhameDAO.php', 1045 1047 'PhameDraftListController' => 'applications/phame/controller/post/list/PhameDraftListController.php', ··· 1048 1050 'PhamePostDetailView' => 'applications/phame/view/PhamePostDetailView.php', 1049 1051 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 1050 1052 'PhamePostListBaseController' => 'applications/phame/controller/post/list/PhamePostListBaseController.php', 1051 - 'PhamePostListController' => 'applications/phame/controller/post/list/PhamePostListController.php', 1052 1053 'PhamePostListView' => 'applications/phame/view/PhamePostListView.php', 1053 1054 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 1054 1055 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 1055 1056 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', 1057 + 'PhameUserPostListController' => 'applications/phame/controller/post/list/PhameUserPostListController.php', 1056 1058 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 1057 1059 'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php', 1058 1060 'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/PhortuneStripePaymentFormView.php', ··· 2001 2003 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 2002 2004 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 2003 2005 'PhabricatorXHProfProfileView' => 'AphrontView', 2006 + 'PhameAllBloggersPostListController' => 'PhamePostListBaseController', 2007 + 'PhameBloggerPostListController' => 'PhamePostListBaseController', 2004 2008 'PhameController' => 'PhabricatorController', 2005 2009 'PhameDAO' => 'PhabricatorLiskDAO', 2006 2010 'PhameDraftListController' => 'PhamePostListBaseController', ··· 2009 2013 'PhamePostDetailView' => 'AphrontView', 2010 2014 'PhamePostEditController' => 'PhameController', 2011 2015 'PhamePostListBaseController' => 'PhameController', 2012 - 'PhamePostListController' => 'PhamePostListBaseController', 2013 2016 'PhamePostListView' => 'AphrontView', 2014 2017 'PhamePostPreviewController' => 'PhameController', 2015 2018 'PhamePostQuery' => 'PhabricatorOffsetPagedQuery', 2016 2019 'PhamePostViewController' => 'PhameController', 2020 + 'PhameUserPostListController' => 'PhamePostListBaseController', 2017 2021 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 2018 2022 'PhortuneStripeBaseController' => 'PhabricatorController', 2019 2023 'PhortuneStripePaymentFormView' => 'AphrontView',
+4 -4
src/aphront/configuration/AphrontDefaultApplicationConfiguration.php
··· 381 381 ), 382 382 383 383 '/phame/' => array( 384 - '' => 'PhamePostListController', 384 + '' => 'PhameAllBloggersPostListController', 385 385 'post/' => array( 386 - '' => 'PhamePostListController', 386 + '' => 'PhameUserPostListController', 387 387 'delete/(?P<phid>[^/]+)/' => 'PhamePostDeleteController', 388 388 'edit/(?P<phid>[^/]+)/' => 'PhamePostEditController', 389 389 'new/' => 'PhamePostEditController', ··· 395 395 'new/' => 'PhamePostEditController', 396 396 ), 397 397 'posts/' => array( 398 - '' => 'PhamePostListController', 399 - '(?P<bloggername>\w+)/' => 'PhamePostListController', 398 + '' => 'PhameUserPostListController', 399 + '(?P<bloggername>\w+)/' => 'PhameBloggerPostListController', 400 400 '(?P<bloggername>\w+)/(?P<phametitle>.+/)' 401 401 => 'PhamePostViewController', 402 402 ),
+8 -3
src/applications/phame/controller/PhameController.php
··· 60 60 } 61 61 62 62 private function renderSideNavFilterView($filter) { 63 + $base_uri = new PhutilURI('/phame/'); 63 64 $nav = new AphrontSideNavFilterView(); 64 - $nav->setBaseURI(new PhutilURI('/phame/')); 65 + $nav->setBaseURI($base_uri); 65 66 $nav->addLabel('Drafts'); 66 67 $nav->addFilter('post/new', 67 68 'New Draft'); ··· 71 72 $nav->addLabel('Posts'); 72 73 $nav->addFilter('post', 73 74 'My Posts'); 75 + $nav->addFilter('everyone', 76 + 'Everyone', 77 + $base_uri); 74 78 foreach ($this->getSideNavExtraPostFilters() as $post_filter) { 75 79 $nav->addFilter($post_filter['key'], 76 - $post_filter['name']); 80 + $post_filter['name'], 81 + idx($post_filter, 'uri')); 77 82 } 78 83 79 - $nav->selectFilter($filter, 'post'); 84 + $nav->selectFilter($filter); 80 85 81 86 return $nav; 82 87 }
+1 -1
src/applications/phame/controller/post/PhamePostEditController.php
··· 99 99 $post = id(new PhamePost()) 100 100 ->setBloggerPHID($user->getPHID()) 101 101 ->setVisibility(PhamePost::VISIBILITY_DRAFT); 102 - $cancel_uri = '/phame'; 102 + $cancel_uri = '/phame/'; 103 103 $submit_button = 'Create Post'; 104 104 $delete_button = null; 105 105 $page_title = 'Create Post';
+6
src/applications/phame/controller/post/PhamePostViewController.php
··· 60 60 return $filters; 61 61 } 62 62 63 + public function shouldRequireLogin() { 64 + // TODO -- get policy logic going 65 + // return PhabricatorEnv::getEnvConfig('policy.allow-public'); 66 + return true; 67 + } 68 + 63 69 public function willProcessRequest(array $data) { 64 70 $this->setPostPHID(idx($data, 'phid')); 65 71 $this->setPhameTitle(idx($data, 'phametitle'));
+95
src/applications/phame/controller/post/list/PhameAllBloggersPostListController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2012 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + /** 20 + * @group phame 21 + */ 22 + final class PhameAllBloggersPostListController 23 + extends PhamePostListBaseController { 24 + 25 + public function shouldRequireLogin() { 26 + return true; 27 + } 28 + 29 + protected function getSideNavFilter() { 30 + return 'everyone'; 31 + } 32 + 33 + protected function getNoticeView() { 34 + $user = $this->getRequest()->getUser(); 35 + 36 + $new_link = phutil_render_tag( 37 + 'a', 38 + array( 39 + 'href' => '/phame/post/new/', 40 + 'class' => 'button green', 41 + ), 42 + 'write a blog post' 43 + ); 44 + 45 + $remarkup_link = phutil_render_tag( 46 + 'a', 47 + array( 48 + 'href' => 49 + PhabricatorEnv::getDoclink('article/Remarkup_Reference.html'), 50 + ), 51 + 'remarkup' 52 + ); 53 + 54 + $guide_link = phutil_render_tag( 55 + 'a', 56 + array( 57 + 'href' => PhabricatorEnv::getDoclink('article/Phame_User_Guide.html'), 58 + ), 59 + 'Phame user guide' 60 + ); 61 + 62 + $notices = array( 63 + 'Seek phame and '.$new_link, 64 + 'Use '.$remarkup_link.' for maximal elegance, grace, and style. ', 65 + 'If you need more help try the '.$guide_link.'.', 66 + ); 67 + 68 + $notice_view = id(new AphrontErrorView()) 69 + ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) 70 + ->setTitle('Meta thoughts and feelings'); 71 + foreach ($notices as $notice) { 72 + $notice_view->appendChild('<p>'.$notice.'</p>'); 73 + } 74 + 75 + return $notice_view; 76 + } 77 + 78 + public function processRequest() { 79 + $user = $this->getRequest()->getUser(); 80 + 81 + $query = new PhamePostQuery(); 82 + $query->withVisibility(PhamePost::VISIBILITY_PUBLISHED); 83 + $this->setPhamePostQuery($query); 84 + 85 + $this->setActions(array('view')); 86 + 87 + $page_title = 'Posts by Everyone'; 88 + $this->setPageTitle($page_title); 89 + 90 + $this->setShowSideNav(true); 91 + 92 + return $this->buildPostListPageResponse(); 93 + } 94 + 95 + }
+74
src/applications/phame/controller/post/list/PhameBloggerPostListController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2012 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + /** 20 + * @group phame 21 + */ 22 + final class PhameBloggerPostListController 23 + extends PhamePostListBaseController { 24 + 25 + private $bloggerName; 26 + 27 + private function setBloggerName($blogger_name) { 28 + $this->bloggerName = $blogger_name; 29 + return $this; 30 + } 31 + private function getBloggerName() { 32 + return $this->bloggerName; 33 + } 34 + 35 + public function shouldRequireLogin() { 36 + // TODO -- get policy logic going 37 + // return PhabricatorEnv::getEnvConfig('policy.allow-public'); 38 + return true; 39 + } 40 + 41 + public function willProcessRequest(array $data) { 42 + $this->setBloggerName(idx($data, 'bloggername')); 43 + } 44 + 45 + public function processRequest() { 46 + $user = $this->getRequest()->getUser(); 47 + 48 + $blogger = id(new PhabricatorUser())->loadOneWhere( 49 + 'username = %s', 50 + $this->getBloggerName()); 51 + if (!$blogger) { 52 + return new Aphront404Response(); 53 + } 54 + $blogger_phid = $blogger->getPHID(); 55 + if ($blogger_phid == $user->getPHID()) { 56 + $actions = array('view', 'edit'); 57 + } else { 58 + $actions = array('view'); 59 + } 60 + $this->setActions($actions); 61 + 62 + $query = new PhamePostQuery(); 63 + $query->withBloggerPHID($blogger_phid); 64 + $query->withVisibility(PhamePost::VISIBILITY_PUBLISHED); 65 + $this->setPhamePostQuery($query); 66 + 67 + $page_title = 'Posts by '.$this->getBloggerName(); 68 + $this->setPageTitle($page_title); 69 + 70 + $this->setShowSideNav(false); 71 + 72 + return $this->buildPostListPageResponse(); 73 + } 74 + }
+28 -2
src/applications/phame/controller/post/list/PhameDraftListController.php
··· 22 22 final class PhameDraftListController 23 23 extends PhamePostListBaseController { 24 24 25 + public function shouldRequireLogin() { 26 + return true; 27 + } 28 + 29 + protected function getSideNavFilter() { 30 + return 'draft'; 31 + } 32 + 33 + protected function isDraft() { 34 + return true; 35 + } 36 + 25 37 public function processRequest() { 26 - $this->setIsDraft(true); 27 - return parent::processRequest(); 38 + $user = $this->getRequest()->getUser(); 39 + $phid = $user->getPHID(); 40 + 41 + $query = new PhamePostQuery(); 42 + $query->withBloggerPHID($phid); 43 + $query->withVisibility(PhamePost::VISIBILITY_DRAFT); 44 + $this->setPhamePostQuery($query); 45 + 46 + $actions = array('view', 'edit'); 47 + $this->setActions($actions); 48 + 49 + $this->setPageTitle('My Drafts'); 50 + 51 + $this->setShowSideNav(true); 52 + 53 + return $this->buildPostListPageResponse(); 28 54 } 29 55 }
+48 -67
src/applications/phame/controller/post/list/PhamePostListBaseController.php
··· 22 22 abstract class PhamePostListBaseController 23 23 extends PhameController { 24 24 25 - private $bloggerName; 26 - private $isDraft; 25 + private $phamePostQuery; 26 + private $actions; 27 + private $pageTitle; 27 28 28 - private function setBloggerName($blogger_name) { 29 - $this->bloggerName = $blogger_name; 29 + protected function setPageTitle($page_title) { 30 + $this->pageTitle = $page_title; 30 31 return $this; 31 32 } 32 - private function getBloggerName() { 33 - return $this->bloggerName; 33 + private function getPageTitle() { 34 + return $this->pageTitle; 34 35 } 35 36 36 - protected function getSideNavExtraPostFilters() { 37 - if ($this->isDraft() || !$this->getBloggerName()) { 38 - return array(); 39 - } 40 - 41 - return 42 - array(array('key' => $this->getSideNavFilter(), 43 - 'name' => 'Posts by '.$this->getBloggerName())); 37 + protected function setActions($actions) { 38 + $this->actions = $actions; 39 + return $this; 44 40 } 45 - 46 - protected function getSideNavFilter() { 47 - if ($this->getBloggerName()) { 48 - $filter = 'posts/'.$this->getBloggerName(); 49 - } else if ($this->isDraft()) { 50 - $filter = 'draft'; 51 - } else { 52 - $filter = 'posts'; 53 - } 54 - return $filter; 41 + private function getActions() { 42 + return $this->actions; 55 43 } 56 44 57 - private function isDraft() { 58 - return (bool) $this->isDraft; 45 + protected function setPhamePostQuery(PhamePostQuery $query) { 46 + $this->phamePostQuery = $query; 47 + return $this; 59 48 } 60 - protected function setIsDraft($is_draft) { 61 - $this->isDraft = $is_draft; 62 - return $this; 49 + private function getPhamePostQuery() { 50 + return $this->phamePostQuery; 63 51 } 64 52 65 - public function willProcessRequest(array $data) { 66 - $this->setBloggerName(idx($data, 'bloggername')); 53 + protected function isDraft() { 54 + return false; 67 55 } 68 56 69 - public function processRequest() { 57 + protected function getPager() { 70 58 $request = $this->getRequest(); 71 - $user = $request->getUser(); 72 59 $pager = new AphrontPagerView(); 73 60 $page_size = 50; 74 61 $pager->setURI($request->getRequestURI(), 'offset'); 75 62 $pager->setPageSize($page_size); 76 63 $pager->setOffset($request->getInt('offset')); 77 64 78 - if ($this->getBloggerName()) { 79 - $blogger = id(new PhabricatorUser())->loadOneWhere( 80 - 'username = %s', 81 - $this->getBloggerName()); 82 - if (!$blogger) { 83 - return new Aphront404Response(); 84 - } 85 - $page_title = 'Posts by '.$this->getBloggerName(); 86 - if ($blogger->getPHID() == $user->getPHID()) { 87 - $actions = array('view', 'edit'); 88 - } else { 89 - $actions = array('view'); 90 - } 91 - $this->setShowSideNav(false); 92 - } else { 93 - $blogger = $user; 94 - $page_title = 'Posts by '.$user->getUserName(); 95 - $actions = array('view', 'edit'); 96 - $this->setShowSideNav(true); 65 + return $pager; 66 + } 67 + 68 + protected function getNoticeView() { 69 + return null; 70 + } 71 + 72 + private function loadBloggersFromPosts(array $posts) { 73 + assert_instances_of($posts, 'PhamePost'); 74 + if (empty($posts)) { 75 + return array(); 97 76 } 98 - $phid = $blogger->getPHID(); 99 - // user gets to see their own unpublished stuff 100 - if ($phid == $user->getPHID() && $this->isDraft()) { 101 - $post_visibility = PhamePost::VISIBILITY_DRAFT; 102 - } else { 103 - $post_visibility = PhamePost::VISIBILITY_PUBLISHED; 104 - } 105 - $query = new PhamePostQuery(); 106 - $query->withBloggerPHID($phid); 107 - $query->withVisibility($post_visibility); 108 - $posts = $query->executeWithPager($pager); 109 - $bloggers = array($blogger->getPHID() => $blogger); 77 + 78 + $blogger_phids = mpull($posts, 'getBloggerPHID', 'getBloggerPHID'); 79 + 80 + return 81 + id(new PhabricatorObjectHandleData($blogger_phids))->loadHandles(); 82 + } 83 + 84 + protected function buildPostListPageResponse() { 85 + $pager = $this->getPager(); 86 + $query = $this->getPhamePostQuery(); 87 + $posts = $query->executeWithPager($pager); 88 + 89 + $bloggers = $this->loadBloggersFromPosts($posts); 110 90 111 91 $panel = id(new PhamePostListView()) 112 - ->setUser($user) 92 + ->setUser($this->getRequest()->getUser()) 113 93 ->setBloggers($bloggers) 114 94 ->setPosts($posts) 115 - ->setActions($actions) 95 + ->setActions($this->getActions()) 116 96 ->setDraftList($this->isDraft()); 117 97 118 98 return $this->buildStandardPageResponse( 119 99 array( 100 + $this->getNoticeView(), 120 101 $panel, 121 102 $pager 122 103 ), 123 104 array( 124 - 'title' => $page_title, 105 + 'title' => $this->getPageTitle(), 125 106 )); 126 107 } 127 108 }
-29
src/applications/phame/controller/post/list/PhamePostListController.php
··· 1 - <?php 2 - 3 - /* 4 - * Copyright 2012 Facebook, Inc. 5 - * 6 - * Licensed under the Apache License, Version 2.0 (the "License"); 7 - * you may not use this file except in compliance with the License. 8 - * You may obtain a copy of the License at 9 - * 10 - * http://www.apache.org/licenses/LICENSE-2.0 11 - * 12 - * Unless required by applicable law or agreed to in writing, software 13 - * distributed under the License is distributed on an "AS IS" BASIS, 14 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 - * See the License for the specific language governing permissions and 16 - * limitations under the License. 17 - */ 18 - 19 - /** 20 - * @group phame 21 - */ 22 - final class PhamePostListController 23 - extends PhamePostListBaseController { 24 - 25 - public function processRequest() { 26 - $this->setIsDraft(false); 27 - return parent::processRequest(); 28 - } 29 - }
+89
src/applications/phame/controller/post/list/PhameUserPostListController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2012 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + /** 20 + * @group phame 21 + */ 22 + final class PhameUserPostListController 23 + extends PhamePostListBaseController { 24 + 25 + public function shouldRequireLogin() { 26 + return true; 27 + } 28 + 29 + protected function getSideNavFilter() { 30 + return 'post'; 31 + } 32 + 33 + protected function getNoticeView() { 34 + $user = $this->getRequest()->getUser(); 35 + 36 + $new_link = phutil_render_tag( 37 + 'a', 38 + array( 39 + 'href' => '/phame/post/new/', 40 + 'class' => 'button green', 41 + ), 42 + 'write another blog post' 43 + ); 44 + 45 + $pretty_uri = PhabricatorEnv::getProductionURI( 46 + '/phame/posts/'.$user->getUserName().'/'); 47 + $pretty_link = phutil_render_tag( 48 + 'a', 49 + array( 50 + 'href' => (string) $pretty_uri 51 + ), 52 + (string) $pretty_uri 53 + ); 54 + 55 + $notices = array( 56 + 'Seek even more phame and '.$new_link, 57 + 'Published posts also appear at the awesome, world-accessible '. 58 + 'URI: '.$pretty_link 59 + ); 60 + 61 + $notice_view = id(new AphrontErrorView()) 62 + ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) 63 + ->setTitle('Meta thoughts and feelings'); 64 + foreach ($notices as $notice) { 65 + $notice_view->appendChild('<p>'.$notice.'</p>'); 66 + } 67 + 68 + return $notice_view; 69 + } 70 + 71 + public function processRequest() { 72 + $user = $this->getRequest()->getUser(); 73 + $phid = $user->getPHID(); 74 + 75 + $query = new PhamePostQuery(); 76 + $query->withBloggerPHID($phid); 77 + $query->withVisibility(PhamePost::VISIBILITY_PUBLISHED); 78 + $this->setPhamePostQuery($query); 79 + 80 + $actions = array('view', 'edit'); 81 + $this->setActions($actions); 82 + 83 + $this->setPageTitle('My Posts'); 84 + 85 + $this->setShowSideNav(true); 86 + 87 + return $this->buildPostListPageResponse(); 88 + } 89 + }
+18
src/applications/phame/query/PhamePostQuery.php
··· 19 19 final class PhamePostQuery extends PhabricatorOffsetPagedQuery { 20 20 21 21 private $bloggerPHID; 22 + private $withoutBloggerPHID; 22 23 private $visibility; 23 24 25 + /** 26 + * Mutually exlusive with @{method:withoutBloggerPHID}. 27 + * 28 + * @{method:withBloggerPHID} wins because being positive and inclusive is 29 + * cool. 30 + */ 24 31 public function withBloggerPHID($blogger_phid) { 25 32 $this->bloggerPHID = $blogger_phid; 26 33 return $this; 27 34 } 35 + public function withoutBloggerPHID($blogger_phid) { 36 + $this->withoutBloggerPHID = $blogger_phid; 37 + return $this; 38 + } 39 + 28 40 public function withVisibility($visibility) { 29 41 $this->visibility = $visibility; 30 42 return $this; ··· 59 71 $conn_r, 60 72 'bloggerPHID = %s', 61 73 $this->bloggerPHID 74 + ); 75 + } else if ($this->withoutBloggerPHID) { 76 + $where[] = qsprintf( 77 + $conn_r, 78 + 'bloggerPHID != %s', 79 + $this->withoutBloggerPHID 62 80 ); 63 81 } 64 82
+9 -1
src/applications/phame/view/PhamePostDetailView.php
··· 79 79 $uri = '/phame/draft/'; 80 80 $label = 'Back to Your Drafts'; 81 81 } else { 82 - $uri = '/phame/posts/'.$blogger->getUsername(); 82 + $uri = '/phame/posts/'.$blogger->getUsername().'/'; 83 83 $label = 'More Posts by '.phutil_escape_html($blogger->getUsername()); 84 84 } 85 85 $button = phutil_render_tag( ··· 101 101 phabricator_datetime($post->getDateModified(), 102 102 $user); 103 103 } 104 + $caption .= ' by '.phutil_render_tag( 105 + 'a', 106 + array( 107 + 'href' => new PhutilURI('/p/'.$blogger->getUsername().'/'), 108 + ), 109 + phutil_escape_html($blogger->getUsername()) 110 + ).'.'; 111 + 104 112 if ($this->isPreview()) { 105 113 $width = AphrontPanelView::WIDTH_FULL; 106 114 } else {
+4 -3
src/applications/phame/view/PhamePostListView.php
··· 59 59 return $this->posts; 60 60 } 61 61 public function setBloggers(array $bloggers) { 62 - assert_instances_of($bloggers, 'PhabricatorUser'); 62 + assert_instances_of($bloggers, 'PhabricatorObjectHandle'); 63 63 $this->bloggers = $bloggers; 64 64 return $this; 65 65 } ··· 99 99 foreach ($posts as $post) { 100 100 $blogger_phid = $post->getBloggerPHID(); 101 101 $blogger = $bloggers[$blogger_phid]; 102 + $blogger_link = $blogger->renderLink(); 102 103 $updated = phabricator_datetime($post->getDateModified(), 103 104 $user); 104 105 $body = $engine->markupText($post->getBody()); 105 106 $panel = id(new AphrontPanelView()) 106 107 ->setHeader(phutil_escape_html($post->getTitle())) 107 - ->setCaption('Last updated '.$updated) 108 + ->setCaption('Last updated '.$updated.' by '.$blogger_link.'.') 108 109 ->appendChild('<div class="phabricator-remarkup">'.$body.'</div>'); 109 110 foreach ($actions as $action) { 110 111 switch ($action) { 111 112 case 'view': 112 - $uri = $post->getViewURI($blogger->getUsername()); 113 + $uri = $post->getViewURI($blogger->getName()); 113 114 $label = 'View '.$noun; 114 115 break; 115 116 case 'edit':