diff --git a/src/applications/phame/controller/PhameHomeController.php b/src/applications/phame/controller/PhameHomeController.php index 349ff563b1..037026fa80 100644 --- a/src/applications/phame/controller/PhameHomeController.php +++ b/src/applications/phame/controller/PhameHomeController.php @@ -1,131 +1,132 @@ setViewer($this->getViewer()) ->addActionToCrumbs($crumbs); return $crumbs; } public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $blogs = id(new PhameBlogQuery()) ->setViewer($viewer) ->withStatuses(array(PhameBlog::STATUS_ACTIVE)) ->needProfileImage(true) ->execute(); $post_list = null; if ($blogs) { $blog_phids = mpull($blogs, 'getPHID'); $pager = id(new AphrontCursorPagerView()) ->readFromRequest($request); $posts = id(new PhamePostQuery()) ->setViewer($viewer) ->withBlogPHIDs($blog_phids) ->withVisibility(array(PhameConstants::VISIBILITY_PUBLISHED)) + ->setOrder('datePublished') ->executeWithCursorPager($pager); if ($posts) { $post_list = id(new PhamePostListView()) ->setPosts($posts) ->setViewer($viewer) ->showBlog(true); } else { $post_list = id(new PHUIBigInfoView()) ->setIcon('fa-star') ->setTitle('No Visible Posts') ->setDescription( pht('There aren\'t any visible blog posts.')); } } else { $create_button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Create a Blog')) ->setHref('/phame/blog/edit/') ->setColor(PHUIButtonView::GREEN); $post_list = id(new PHUIBigInfoView()) ->setIcon('fa-star') ->setTitle('Welcome to Phame') ->setDescription( pht('There aren\'t any visible blog posts.')) ->addAction($create_button); } $view_all = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('View All')) ->setHref($this->getApplicationURI('post/')) ->setIcon('fa-list-ul'); $title = pht('Recent Posts'); $header = id(new PHUIHeaderView()) ->setHeader($title) ->addActionLink($view_all); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); $crumbs->addTextCrumb( pht('Recent Posts'), $this->getApplicationURI('post/')); $page = id(new PHUIDocumentViewPro()) ->setHeader($header) ->appendChild($post_list); $blog_list = id(new PhameBlogListView()) ->setBlogs($blogs) ->setViewer($viewer); $draft_list = null; if ($viewer->isLoggedIn() && $blogs) { $drafts = id(new PhamePostQuery()) ->setViewer($viewer) ->withBloggerPHIDs(array($viewer->getPHID())) ->withBlogPHIDs(mpull($blogs, 'getPHID')) ->withVisibility(array(PhameConstants::VISIBILITY_DRAFT)) ->setLimit(5) ->execute(); $draft_list = id(new PhameDraftListView()) ->setPosts($drafts) ->setBlogs($blogs) ->setViewer($viewer); } $phame_view = id(new PHUITwoColumnView()) ->setMainColumn(array( $page, )) ->setSideColumn(array( $blog_list, $draft_list, )) ->addClass('phame-home-container'); $phame_home = phutil_tag_div('phame-home-view', $phame_view); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild( array( $phame_home, )); } } diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index f2210b452b..0230b0703e 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -1,154 +1,155 @@ setupLiveEnvironment(); if ($response) { return $response; } $viewer = $this->getViewer(); $blog = $this->getBlog(); $is_live = $this->getIsLive(); $is_external = $this->getIsExternal(); $pager = id(new AphrontCursorPagerView()) ->readFromRequest($request); $post_query = id(new PhamePostQuery()) ->setViewer($viewer) ->withBlogPHIDs(array($blog->getPHID())) + ->setOrder('datePublished') ->withVisibility(array( PhameConstants::VISIBILITY_PUBLISHED, PhameConstants::VISIBILITY_DRAFT, )); if ($is_live) { $post_query->withVisibility(array(PhameConstants::VISIBILITY_PUBLISHED)); } $posts = $post_query->executeWithCursorPager($pager); $header = id(new PHUIHeaderView()) ->setHeader($blog->getName()) ->setUser($viewer); if (!$is_external) { if ($blog->isArchived()) { $header_icon = 'fa-ban'; $header_name = pht('Archived'); $header_color = 'dark'; } else { $header_icon = 'fa-check'; $header_name = pht('Active'); $header_color = 'bluegrey'; } $header->setStatus($header_icon, $header_color, $header_name); $actions = $this->renderActions($blog); $header->setActionList($actions); $header->setPolicyObject($blog); } if ($posts) { $post_list = id(new PhamePostListView()) ->setPosts($posts) ->setViewer($viewer) ->setIsExternal($is_external) ->setIsLive($is_live) ->setNodata(pht('This blog has no visible posts.')); } else { $create_button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Write a Post')) ->setHref($this->getApplicationURI('post/edit/?blog='.$blog->getID())) ->setColor(PHUIButtonView::GREEN); $post_list = id(new PHUIBigInfoView()) ->setIcon('fa-star') ->setTitle($blog->getName()) ->setDescription( pht('No one has written any blog posts yet.')); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $blog, PhabricatorPolicyCapability::CAN_EDIT); if ($can_edit) { $post_list->addAction($create_button); } } $page = id(new PHUIDocumentViewPro()) ->setHeader($header) ->appendChild($post_list); $description = null; if (strlen($blog->getDescription())) { $description = new PHUIRemarkupView( $viewer, $blog->getDescription()); } else { $description = phutil_tag('em', array(), pht('No description.')); } $about = id(new PhameDescriptionView()) ->setTitle(pht('About %s', $blog->getName())) ->setDescription($description) ->setImage($blog->getProfileImageURI()); $crumbs = $this->buildApplicationCrumbs(); $page = $this->newPage() ->setTitle($blog->getName()) ->setPageObjectPHIDs(array($blog->getPHID())) ->setCrumbs($crumbs) ->appendChild( array( $page, $about, )); return $page; } private function renderActions(PhameBlog $blog) { $viewer = $this->getViewer(); $actions = id(new PhabricatorActionListView()) ->setObject($blog) ->setUser($viewer); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $blog, PhabricatorPolicyCapability::CAN_EDIT); $actions->addAction( id(new PhabricatorActionView()) ->setIcon('fa-plus') ->setHref($this->getApplicationURI('post/edit/?blog='.$blog->getID())) ->setName(pht('Write Post')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $actions->addAction( id(new PhabricatorActionView()) ->setUser($viewer) ->setIcon('fa-globe') ->setHref($blog->getLiveURI()) ->setName(pht('View Live'))); $actions->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI('blog/manage/'.$blog->getID().'/')) ->setName(pht('Manage Blog'))); return $actions; } } diff --git a/src/applications/phame/query/PhamePostQuery.php b/src/applications/phame/query/PhamePostQuery.php index 22b04bcd99..1a29eda869 100644 --- a/src/applications/phame/query/PhamePostQuery.php +++ b/src/applications/phame/query/PhamePostQuery.php @@ -1,130 +1,160 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withBloggerPHIDs(array $blogger_phids) { $this->bloggerPHIDs = $blogger_phids; return $this; } public function withBlogPHIDs(array $blog_phids) { $this->blogPHIDs = $blog_phids; return $this; } public function withVisibility(array $visibility) { $this->visibility = $visibility; return $this; } public function withPublishedAfter($time) { $this->publishedAfter = $time; return $this; } public function newResultObject() { return new PhamePost(); } protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } protected function willFilterPage(array $posts) { // We require blogs to do visibility checks, so load them unconditionally. $blog_phids = mpull($posts, 'getBlogPHID'); $blogs = id(new PhameBlogQuery()) ->setViewer($this->getViewer()) ->needProfileImage(true) ->withPHIDs($blog_phids) ->execute(); $blogs = mpull($blogs, null, 'getPHID'); foreach ($posts as $key => $post) { $blog_phid = $post->getBlogPHID(); $blog = idx($blogs, $blog_phid); if (!$blog) { $this->didRejectResult($post); unset($posts[$key]); continue; } $post->attachBlog($blog); } return $posts; } protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->ids) { $where[] = qsprintf( $conn, 'id IN (%Ld)', $this->ids); } if ($this->phids) { $where[] = qsprintf( $conn, 'phid IN (%Ls)', $this->phids); } if ($this->bloggerPHIDs) { $where[] = qsprintf( $conn, 'bloggerPHID IN (%Ls)', $this->bloggerPHIDs); } if ($this->visibility) { $where[] = qsprintf( $conn, 'visibility IN (%Ld)', $this->visibility); } if ($this->publishedAfter !== null) { $where[] = qsprintf( $conn, 'datePublished > %d', $this->publishedAfter); } if ($this->blogPHIDs !== null) { $where[] = qsprintf( $conn, 'blogPHID in (%Ls)', $this->blogPHIDs); } return $where; } + public function getBuiltinOrders() { + return array( + 'datePublished' => array( + 'vector' => array('datePublished', 'id'), + 'name' => pht('Publish Date'), + ), + ) + parent::getBuiltinOrders(); + } + + public function getOrderableColumns() { + return parent::getOrderableColumns() + array( + 'datePublished' => array( + 'column' => 'datePublished', + 'type' => 'int', + 'reverse' => false, + ), + ); + } + + protected function getPagingValueMap($cursor, array $keys) { + $post = $this->loadCursorObject($cursor); + + $map = array( + 'datePublished' => $post->getDatePublished(), + 'id' => $post->getID(), + ); + + return $map; + } + public function getQueryApplicationClass() { // TODO: Does setting this break public blogs? return null; } }