3 final class PhamePostViewController
4 extends PhameLiveController
{
6 public function handleRequest(AphrontRequest
$request) {
7 $response = $this->setupLiveEnvironment();
12 $viewer = $request->getViewer();
13 $moved = $request->getStr('moved');
15 $post = $this->getPost();
16 $blog = $this->getBlog();
18 $is_live = $this->getIsLive();
19 $is_external = $this->getIsExternal();
21 $header = id(new PHUIHeaderView())
22 ->addClass('phame-header-bar')
25 $hero = $this->buildPhamePostHeader($post);
27 if (!$is_external && $viewer->isLoggedIn()) {
28 $actions = $this->renderActions($post);
29 $header->setPolicyObject($post);
30 $header->setActionList($actions);
33 $document = id(new PHUIDocumentView())
37 $document->appendChild(
38 id(new PHUIInfoView())
39 ->setSeverity(PHUIInfoView
::SEVERITY_NOTICE
)
40 ->appendChild(pht('Post moved successfully.')));
43 if ($post->isDraft()) {
44 $document->appendChild(
45 id(new PHUIInfoView())
46 ->setSeverity(PHUIInfoView
::SEVERITY_NOTICE
)
47 ->setTitle(pht('Draft Post'))
50 'This is a draft, and is only visible to you and other users '.
51 'who can edit %s. Use "Publish" to publish this post.',
52 $viewer->renderHandle($post->getBlogPHID()))));
55 if ($post->isArchived()) {
56 $document->appendChild(
57 id(new PHUIInfoView())
58 ->setSeverity(PHUIInfoView
::SEVERITY_ERROR
)
59 ->setTitle(pht('Archived Post'))
62 'This post has been archived, and is only visible to you and '.
63 'other users who can edit %s.',
64 $viewer->renderHandle($post->getBlogPHID()))));
67 if (!$post->getBlog()) {
68 $document->appendChild(
69 id(new PHUIInfoView())
70 ->setSeverity(PHUIInfoView
::SEVERITY_WARNING
)
71 ->setTitle(pht('Not On A Blog'))
73 pht('This post is not associated with a blog (the blog may have '.
74 'been deleted). Use "Move Post" to move it to a new blog.')));
77 $engine = id(new PhabricatorMarkupEngine())
79 ->addObject($post, PhamePost
::MARKUP_FIELD_BODY
)
82 $document->appendChild(
86 'class' => 'phabricator-remarkup',
88 $engine->getOutput($post, PhamePost
::MARKUP_FIELD_BODY
)));
90 $blogger = id(new PhabricatorPeopleQuery())
92 ->withPHIDs(array($post->getBloggerPHID()))
93 ->needProfileImage(true)
95 $blogger_profile = $blogger->loadUserProfile();
98 $author_uri = '/p/'.$blogger->getUsername().'/';
99 $author_uri = PhabricatorEnv
::getURI($author_uri);
101 $author = phutil_tag(
104 'href' => $author_uri,
106 $blogger->getUsername());
108 $date = phabricator_datetime($post->getDatePublished(), $viewer);
109 if ($post->isDraft()) {
110 $subtitle = pht('Unpublished draft by %s.', $author);
111 } else if ($post->isArchived()) {
112 $subtitle = pht('Archived post by %s.', $author);
114 $subtitle = pht('Written by %s on %s.', $author, $date);
117 $user_icon = $blogger_profile->getIcon();
118 $user_icon = PhabricatorPeopleIconSet
::getIconIcon($user_icon);
119 $user_icon = id(new PHUIIconView())->setIcon($user_icon);
121 $about = id(new PhameDescriptionView())
122 ->setTitle($subtitle)
127 $blogger_profile->getDisplayTitle(),
129 ->setImage($blogger->getProfileImageURI())
130 ->setImageHref($author_uri);
132 $monogram = $post->getMonogram();
133 $timeline = $this->buildTransactionTimeline(
135 id(new PhamePostTransactionQuery())
136 ->withTransactionTypes(array(PhabricatorTransactions
::TYPE_COMMENT
)));
137 $timeline->setQuoteRef($monogram);
139 if ($is_external ||
!$viewer->isLoggedIn()) {
142 $add_comment = $this->buildCommentForm($post, $timeline);
143 $add_comment = phutil_tag_div('mlb mlt phame-comment-view', $add_comment);
146 $timeline = phutil_tag_div('phui-document-view-pro-box', $timeline);
148 list($prev, $next) = $this->loadAdjacentPosts($post);
150 $properties = id(new PHUIPropertyListView())
154 $is_live = $this->getIsLive();
155 $is_external = $this->getIsExternal();
156 $next_view = new PhameNextPostView();
158 $next_view->setNext($next->getTitle(),
159 $next->getBestURI($is_live, $is_external));
162 $next_view->setPrevious($prev->getTitle(),
163 $prev->getBestURI($is_live, $is_external));
166 $document->setFoot($next_view);
167 $crumbs = $this->buildApplicationCrumbs();
168 $properties = phutil_tag_div('phui-document-view-pro-box', $properties);
170 $page = $this->newPage()
171 ->setTitle($post->getTitle())
172 ->setPageObjectPHIDs(array($post->getPHID()))
186 ->setShowChrome(false)
187 ->setShowFooter(false);
193 private function renderActions(PhamePost
$post) {
194 $viewer = $this->getViewer();
196 $actions = id(new PhabricatorActionListView())
200 $can_edit = PhabricatorPolicyFilter
::hasCapability(
203 PhabricatorPolicyCapability
::CAN_EDIT
);
205 $id = $post->getID();
208 id(new PhabricatorActionView())
209 ->setIcon('fa-pencil')
210 ->setHref($this->getApplicationURI('post/edit/'.$id.'/'))
211 ->setName(pht('Edit Post'))
212 ->setDisabled(!$can_edit));
215 id(new PhabricatorActionView())
216 ->setIcon('fa-camera-retro')
217 ->setHref($this->getApplicationURI('post/header/'.$id.'/'))
218 ->setName(pht('Edit Header Image'))
219 ->setDisabled(!$can_edit));
222 id(new PhabricatorActionView())
223 ->setIcon('fa-arrows')
224 ->setHref($this->getApplicationURI('post/move/'.$id.'/'))
225 ->setName(pht('Move Post'))
226 ->setDisabled(!$can_edit)
227 ->setWorkflow(true));
230 id(new PhabricatorActionView())
231 ->setIcon('fa-history')
232 ->setHref($this->getApplicationURI('post/history/'.$id.'/'))
233 ->setName(pht('View History')));
235 if ($post->isDraft()) {
237 id(new PhabricatorActionView())
239 ->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
240 ->setName(pht('Publish'))
241 ->setDisabled(!$can_edit)
242 ->setWorkflow(true));
244 id(new PhabricatorActionView())
246 ->setHref($this->getApplicationURI('post/archive/'.$id.'/'))
247 ->setName(pht('Archive'))
248 ->setDisabled(!$can_edit)
249 ->setWorkflow(true));
250 } else if ($post->isArchived()) {
252 id(new PhabricatorActionView())
254 ->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
255 ->setName(pht('Publish'))
256 ->setDisabled(!$can_edit)
257 ->setWorkflow(true));
260 id(new PhabricatorActionView())
261 ->setIcon('fa-eye-slash')
262 ->setHref($this->getApplicationURI('post/unpublish/'.$id.'/'))
263 ->setName(pht('Unpublish'))
264 ->setDisabled(!$can_edit)
265 ->setWorkflow(true));
267 id(new PhabricatorActionView())
269 ->setHref($this->getApplicationURI('post/archive/'.$id.'/'))
270 ->setName(pht('Archive'))
271 ->setDisabled(!$can_edit)
272 ->setWorkflow(true));
275 if ($post->isDraft()) {
276 $live_name = pht('Preview');
278 $live_name = pht('View Live');
281 if (!$post->isArchived()) {
283 id(new PhabricatorActionView())
285 ->setIcon('fa-globe')
286 ->setHref($post->getLiveURI())
287 ->setName($live_name));
293 private function buildCommentForm(PhamePost
$post, $timeline) {
294 $viewer = $this->getViewer();
296 $box = id(new PhamePostEditEngine())
298 ->buildEditEngineCommentView($post)
299 ->setTransactionTimeline($timeline);
301 return phutil_tag_div('phui-document-view-pro-box', $box);
304 private function loadAdjacentPosts(PhamePost
$post) {
305 $viewer = $this->getViewer();
307 $pager = id(new AphrontCursorPagerView())
310 $prev_pager = id(clone $pager)
311 ->setAfterID($post->getID());
313 $next_pager = id(clone $pager)
314 ->setBeforeID($post->getID());
316 $query = id(new PhamePostQuery())
318 ->withVisibility(array(PhameConstants
::VISIBILITY_PUBLISHED
))
319 ->withBlogPHIDs(array($post->getBlog()->getPHID()))
322 $prev = id(clone $query)
323 ->executeWithCursorPager($prev_pager);
325 $next = id(clone $query)
326 ->executeWithCursorPager($next_pager);
328 return array(head($prev), head($next));
331 private function buildPhamePostHeader(
335 if ($post->getHeaderImagePHID()) {
339 'class' => 'phame-header-hero',
344 'src' => $post->getHeaderImageURI(),
345 'class' => 'phame-header-image',
349 $title = phutil_tag_div('phame-header-title', $post->getTitle());
351 if ($post->getSubtitle()) {
352 $subtitle = phutil_tag_div('phame-header-subtitle', $post->getSubtitle());
355 return phutil_tag_div(
356 'phame-mega-header', array($image, $title, $subtitle));