From 72c57d36a30c6607192988e222309769910c44f3 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 13 Jun 2016 10:34:13 -0700 Subject: [PATCH] Ability to archive Phame Posts Summary: Ref T9897. Adds ability to Archive a Phame Post (only visible under ApplicationSearch). Test Plan: Archive a post, re-publish it, search for it, archive it again. View Home, Blog, Live pages. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T9897 Differential Revision: https://secure.phabricator.com/D16104 --- src/__phutil_library_map__.php | 2 + .../PhabricatorPhameApplication.php | 1 + .../phame/constants/PhameConstants.php | 5 +- .../phame/controller/PhameHomeController.php | 4 +- .../phame/controller/PhameLiveController.php | 3 +- .../blog/PhameBlogFeedController.php | 2 +- .../blog/PhameBlogViewController.php | 8 ++- .../post/PhamePostArchiveController.php | 56 +++++++++++++++++++ .../post/PhamePostViewController.php | 50 ++++++++++++++--- .../phame/editor/PhamePostEditor.php | 3 + .../phame/query/PhamePostQuery.php | 6 +- .../phame/query/PhamePostSearchEngine.php | 11 +++- src/applications/phame/storage/PhamePost.php | 11 +++- .../phame/storage/PhamePostTransaction.php | 11 ++++ 14 files changed, 153 insertions(+), 20 deletions(-) create mode 100644 src/applications/phame/controller/post/PhamePostArchiveController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index bd8c8c1476..6e29d196c5 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3771,6 +3771,7 @@ phutil_register_library_map(array( 'PhameLiveController' => 'applications/phame/controller/PhameLiveController.php', 'PhameNextPostView' => 'applications/phame/view/PhameNextPostView.php', 'PhamePost' => 'applications/phame/storage/PhamePost.php', + 'PhamePostArchiveController' => 'applications/phame/controller/post/PhamePostArchiveController.php', 'PhamePostCommentController' => 'applications/phame/controller/post/PhamePostCommentController.php', 'PhamePostController' => 'applications/phame/controller/post/PhamePostController.php', 'PhamePostEditConduitAPIMethod' => 'applications/phame/conduit/PhamePostEditConduitAPIMethod.php', @@ -8627,6 +8628,7 @@ phutil_register_library_map(array( 'PhabricatorTokenReceiverInterface', 'PhabricatorConduitResultInterface', ), + 'PhamePostArchiveController' => 'PhamePostController', 'PhamePostCommentController' => 'PhamePostController', 'PhamePostController' => 'PhameController', 'PhamePostEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', diff --git a/src/applications/phame/application/PhabricatorPhameApplication.php b/src/applications/phame/application/PhabricatorPhameApplication.php index 9138961214..24d1a05b31 100644 --- a/src/applications/phame/application/PhabricatorPhameApplication.php +++ b/src/applications/phame/application/PhabricatorPhameApplication.php @@ -55,6 +55,7 @@ final class PhabricatorPhameApplication extends PhabricatorApplication { 'preview/' => 'PhabricatorMarkupPreviewController', 'framed/(?P\d+)/' => 'PhamePostFramedController', 'move/(?P\d+)/' => 'PhamePostMoveController', + 'archive/(?P\d+)/' => 'PhamePostArchiveController', 'comment/(?P[1-9]\d*)/' => 'PhamePostCommentController', ), 'blog/' => array( diff --git a/src/applications/phame/constants/PhameConstants.php b/src/applications/phame/constants/PhameConstants.php index c9444411f0..39f35f71ce 100644 --- a/src/applications/phame/constants/PhameConstants.php +++ b/src/applications/phame/constants/PhameConstants.php @@ -2,13 +2,15 @@ final class PhameConstants extends Phobject { - const VISIBILITY_DRAFT = 0; + const VISIBILITY_DRAFT = 0; const VISIBILITY_PUBLISHED = 1; + const VISIBILITY_ARCHIVED = 2; public static function getPhamePostStatusMap() { return array( self::VISIBILITY_PUBLISHED => pht('Published'), self::VISIBILITY_DRAFT => pht('Draft'), + self::VISIBILITY_ARCHIVED => pht('Archived'), ); } @@ -16,6 +18,7 @@ final class PhameConstants extends Phobject { $map = array( self::VISIBILITY_PUBLISHED => pht('Published'), self::VISIBILITY_DRAFT => pht('Draft'), + self::VISIBILITY_ARCHIVED => pht('Archived'), ); return idx($map, $status, pht('Unknown')); } diff --git a/src/applications/phame/controller/PhameHomeController.php b/src/applications/phame/controller/PhameHomeController.php index 95d1544abe..349ff563b1 100644 --- a/src/applications/phame/controller/PhameHomeController.php +++ b/src/applications/phame/controller/PhameHomeController.php @@ -35,7 +35,7 @@ final class PhameHomeController extends PhamePostController { $posts = id(new PhamePostQuery()) ->setViewer($viewer) ->withBlogPHIDs($blog_phids) - ->withVisibility(PhameConstants::VISIBILITY_PUBLISHED) + ->withVisibility(array(PhameConstants::VISIBILITY_PUBLISHED)) ->executeWithCursorPager($pager); if ($posts) { @@ -97,7 +97,7 @@ final class PhameHomeController extends PhamePostController { ->setViewer($viewer) ->withBloggerPHIDs(array($viewer->getPHID())) ->withBlogPHIDs(mpull($blogs, 'getPHID')) - ->withVisibility(PhameConstants::VISIBILITY_DRAFT) + ->withVisibility(array(PhameConstants::VISIBILITY_DRAFT)) ->setLimit(5) ->execute(); diff --git a/src/applications/phame/controller/PhameLiveController.php b/src/applications/phame/controller/PhameLiveController.php index 57ac875465..e2f1789a6c 100644 --- a/src/applications/phame/controller/PhameLiveController.php +++ b/src/applications/phame/controller/PhameLiveController.php @@ -97,7 +97,8 @@ abstract class PhameLiveController extends PhameController { // Only show published posts on external domains. if ($is_external) { - $post_query->withVisibility(PhameConstants::VISIBILITY_PUBLISHED); + $post_query->withVisibility( + array(PhameConstants::VISIBILITY_PUBLISHED)); } $post = $post_query->executeOne(); diff --git a/src/applications/phame/controller/blog/PhameBlogFeedController.php b/src/applications/phame/controller/blog/PhameBlogFeedController.php index b8b47c019f..c0c6e60cc4 100644 --- a/src/applications/phame/controller/blog/PhameBlogFeedController.php +++ b/src/applications/phame/controller/blog/PhameBlogFeedController.php @@ -21,7 +21,7 @@ final class PhameBlogFeedController extends PhameBlogController { $posts = id(new PhamePostQuery()) ->setViewer($viewer) ->withBlogPHIDs(array($blog->getPHID())) - ->withVisibility(PhameConstants::VISIBILITY_PUBLISHED) + ->withVisibility(array(PhameConstants::VISIBILITY_PUBLISHED)) ->execute(); $blog_uri = PhabricatorEnv::getProductionURI( diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index da027d584b..f2210b452b 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -19,10 +19,14 @@ final class PhameBlogViewController extends PhameLiveController { $post_query = id(new PhamePostQuery()) ->setViewer($viewer) - ->withBlogPHIDs(array($blog->getPHID())); + ->withBlogPHIDs(array($blog->getPHID())) + ->withVisibility(array( + PhameConstants::VISIBILITY_PUBLISHED, + PhameConstants::VISIBILITY_DRAFT, + )); if ($is_live) { - $post_query->withVisibility(PhameConstants::VISIBILITY_PUBLISHED); + $post_query->withVisibility(array(PhameConstants::VISIBILITY_PUBLISHED)); } $posts = $post_query->executeWithCursorPager($pager); diff --git a/src/applications/phame/controller/post/PhamePostArchiveController.php b/src/applications/phame/controller/post/PhamePostArchiveController.php new file mode 100644 index 0000000000..5a3b32944a --- /dev/null +++ b/src/applications/phame/controller/post/PhamePostArchiveController.php @@ -0,0 +1,56 @@ +getViewer(); + + $id = $request->getURIData('id'); + $post = id(new PhamePostQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$post) { + return new Aphront404Response(); + } + + $cancel_uri = $post->getViewURI(); + + if ($request->isFormPost()) { + $xactions = array(); + + $new_value = PhameConstants::VISIBILITY_ARCHIVED; + $xactions[] = id(new PhamePostTransaction()) + ->setTransactionType(PhamePostTransaction::TYPE_VISIBILITY) + ->setNewValue($new_value); + + id(new PhamePostEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($post, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($cancel_uri); + } + + $title = pht('Archive Post'); + $body = pht( + 'This post will revert to archived status and no longer be visible '. + 'to other users or members of this blog.'); + $button = pht('Archive Post'); + + return $this->newDialog() + ->setTitle($title) + ->appendParagraph($body) + ->addSubmitButton($button) + ->addCancelButton($cancel_uri); + } + +} diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php index fdbaf139c2..d28f1b5150 100644 --- a/src/applications/phame/controller/post/PhamePostViewController.php +++ b/src/applications/phame/controller/post/PhamePostViewController.php @@ -48,6 +48,16 @@ final class PhamePostViewController 'Use "Publish" to publish this post.'))); } + if ($post->isArchived()) { + $document->appendChild( + id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_ERROR) + ->setTitle(pht('Archived Post')) + ->appendChild( + pht('Only you can see this archived post until you publish it. '. + 'Use "Publish" to publish this post.'))); + } + if (!$post->getBlog()) { $document->appendChild( id(new PHUIInfoView()) @@ -92,6 +102,8 @@ final class PhamePostViewController $date = phabricator_datetime($post->getDatePublished(), $viewer); if ($post->isDraft()) { $subtitle = pht('Unpublished draft by %s.', $author); + } else if ($post->isArchived()) { + $subtitle = pht('Archived post by %s.', $author); } else { $subtitle = pht('Written by %s on %s.', $author, $date); } @@ -207,6 +219,21 @@ final class PhamePostViewController ->setName(pht('Publish')) ->setDisabled(!$can_edit) ->setWorkflow(true)); + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-ban') + ->setHref($this->getApplicationURI('post/archive/'.$id.'/')) + ->setName(pht('Archive')) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } else if ($post->isArchived()) { + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-eye') + ->setHref($this->getApplicationURI('post/publish/'.$id.'/')) + ->setName(pht('Publish')) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); } else { $actions->addAction( id(new PhabricatorActionView()) @@ -215,6 +242,13 @@ final class PhamePostViewController ->setName(pht('Unpublish')) ->setDisabled(!$can_edit) ->setWorkflow(true)); + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-ban') + ->setHref($this->getApplicationURI('post/archive/'.$id.'/')) + ->setName(pht('Archive')) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); } if ($post->isDraft()) { @@ -223,12 +257,14 @@ final class PhamePostViewController $live_name = pht('View Live'); } - $actions->addAction( - id(new PhabricatorActionView()) - ->setUser($viewer) - ->setIcon('fa-globe') - ->setHref($post->getLiveURI()) - ->setName($live_name)); + if (!$post->isArchived()) { + $actions->addAction( + id(new PhabricatorActionView()) + ->setUser($viewer) + ->setIcon('fa-globe') + ->setHref($post->getLiveURI()) + ->setName($live_name)); + } return $actions; } @@ -255,7 +291,7 @@ final class PhamePostViewController $query = id(new PhamePostQuery()) ->setViewer($viewer) - ->withVisibility(PhameConstants::VISIBILITY_PUBLISHED) + ->withVisibility(array(PhameConstants::VISIBILITY_PUBLISHED)) ->withBlogPHIDs(array($post->getBlog()->getPHID())) ->setLimit(1); diff --git a/src/applications/phame/editor/PhamePostEditor.php b/src/applications/phame/editor/PhamePostEditor.php index fa43a131ff..96f2c2016f 100644 --- a/src/applications/phame/editor/PhamePostEditor.php +++ b/src/applications/phame/editor/PhamePostEditor.php @@ -66,6 +66,9 @@ final class PhamePostEditor case PhamePostTransaction::TYPE_VISIBILITY: if ($xaction->getNewValue() == PhameConstants::VISIBILITY_DRAFT) { $object->setDatePublished(0); + } else if ($xaction->getNewValue() == + PhameConstants::VISIBILITY_ARCHIVED) { + $object->setDatePublished(0); } else { $object->setDatePublished(PhabricatorTime::getNow()); } diff --git a/src/applications/phame/query/PhamePostQuery.php b/src/applications/phame/query/PhamePostQuery.php index d2a1feb2c1..22b04bcd99 100644 --- a/src/applications/phame/query/PhamePostQuery.php +++ b/src/applications/phame/query/PhamePostQuery.php @@ -29,7 +29,7 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery { return $this; } - public function withVisibility($visibility) { + public function withVisibility(array $visibility) { $this->visibility = $visibility; return $this; } @@ -98,10 +98,10 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery { $this->bloggerPHIDs); } - if ($this->visibility !== null) { + if ($this->visibility) { $where[] = qsprintf( $conn, - 'visibility = %d', + 'visibility IN (%Ld)', $this->visibility); } diff --git a/src/applications/phame/query/PhamePostSearchEngine.php b/src/applications/phame/query/PhamePostSearchEngine.php index a7a331fbdf..83f11436ea 100644 --- a/src/applications/phame/query/PhamePostSearchEngine.php +++ b/src/applications/phame/query/PhamePostSearchEngine.php @@ -19,7 +19,7 @@ final class PhamePostSearchEngine $query = $this->newQuery(); if (strlen($map['visibility'])) { - $query->withVisibility($map['visibility']); + $query->withVisibility(array($map['visibility'])); } return $query; @@ -35,6 +35,7 @@ final class PhamePostSearchEngine '' => pht('All'), PhameConstants::VISIBILITY_PUBLISHED => pht('Published'), PhameConstants::VISIBILITY_DRAFT => pht('Draft'), + PhameConstants::VISIBILITY_ARCHIVED => pht('Archived'), )), ); } @@ -48,6 +49,7 @@ final class PhamePostSearchEngine 'all' => pht('All Posts'), 'live' => pht('Published Posts'), 'draft' => pht('Draft Posts'), + 'archived' => pht('Archived Posts'), ); return $names; } @@ -65,6 +67,9 @@ final class PhamePostSearchEngine case 'draft': return $query->setParameter( 'visibility', PhameConstants::VISIBILITY_DRAFT); + case 'archived': + return $query->setParameter( + 'visibility', PhameConstants::VISIBILITY_ARCHIVED); } return parent::buildSavedQueryFromBuiltin($query_key); @@ -100,6 +105,10 @@ final class PhamePostSearchEngine $item->setStatusIcon('fa-star-o grey'); $item->setDisabled(true); $item->addIcon('none', pht('Draft Post')); + } else if ($post->isArchived()) { + $item->setStatusIcon('fa-ban grey'); + $item->setDisabled(true); + $item->addIcon('none', pht('Archived Post')); } else { $date = $post->getDatePublished(); $item->setEpoch($date); diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php index fb2e8058dc..f77032ffab 100644 --- a/src/applications/phame/storage/PhamePost.php +++ b/src/applications/phame/storage/PhamePost.php @@ -53,7 +53,8 @@ final class PhamePost extends PhameDAO public function getLiveURI() { $blog = $this->getBlog(); $is_draft = $this->isDraft(); - if (strlen($blog->getDomain()) && !$is_draft) { + $is_archived = $this->isArchived(); + if (strlen($blog->getDomain()) && !$is_draft && !$is_archived) { return $this->getExternalLiveURI(); } else { return $this->getInternalLiveURI(); @@ -92,6 +93,10 @@ final class PhamePost extends PhameDAO return ($this->getVisibility() == PhameConstants::VISIBILITY_DRAFT); } + public function isArchived() { + return ($this->getVisibility() == PhameConstants::VISIBILITY_ARCHIVED); + } + protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, @@ -165,7 +170,7 @@ final class PhamePost extends PhameDAO switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: - if (!$this->isDraft() && $this->getBlog()) { + if (!$this->isDraft() && !$this->isArchived() && $this->getBlog()) { return $this->getBlog()->getViewPolicy(); } else if ($this->getBlog()) { return $this->getBlog()->getEditPolicy(); @@ -319,6 +324,8 @@ final class PhamePost extends PhameDAO public function getFieldValuesForConduit() { if ($this->isDraft()) { $date_published = null; + } else if ($this->isArchived()) { + $date_published = null; } else { $date_published = (int)$this->getDatePublished(); } diff --git a/src/applications/phame/storage/PhamePostTransaction.php b/src/applications/phame/storage/PhamePostTransaction.php index be5dbfd8b5..a1efb584b0 100644 --- a/src/applications/phame/storage/PhamePostTransaction.php +++ b/src/applications/phame/storage/PhamePostTransaction.php @@ -73,6 +73,8 @@ final class PhamePostTransaction case self::TYPE_VISIBILITY: if ($new == PhameConstants::VISIBILITY_PUBLISHED) { return 'fa-globe'; + } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { + return 'fa-ban'; } else { return 'fa-eye-slash'; } @@ -144,6 +146,10 @@ final class PhamePostTransaction return pht( '%s marked this post as a draft.', $this->renderHandleLink($author_phid)); + } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { + return pht( + '%s archived this post.', + $this->renderHandleLink($author_phid)); } else { return pht( '%s published this post.', @@ -201,6 +207,11 @@ final class PhamePostTransaction '%s marked %s as a draft.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); + } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { + return pht( + '%s marked %s as archived.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); } else { return pht( '%s published %s.',