context->getNews(); $users = $this->context->getUsers(); $comments = $this->context->getComments(); $posts = []; $userInfos = []; $userColours = []; foreach($postInfos as $postInfo) { $userId = $postInfo->getUserId(); $categoryId = $postInfo->getCategoryId(); if(array_key_exists($userId, $userInfos)) { $userInfo = $userInfos[$userId]; $userColour = $userColours[$userId]; } else { try { $userInfo = $users->getUser($userId, 'id'); $userColour = $users->getUserColour($userInfo); } catch(RuntimeException $ex) { $userInfo = null; $userColour = null; } $userInfos[$userId] = $userInfo; $userColours[$userId] = $userColour; } if(array_key_exists($categoryId, $categoryInfos)) $categoryInfo = $categoryInfos[$categoryId]; else $categoryInfos[$categoryId] = $categoryInfo = $news->getCategoryByPost($postInfo); $commentsCount = $postInfo->hasCommentsCategoryId() ? $comments->countPosts($postInfo->getCommentsCategoryId(), includeReplies: true) : 0; $posts[] = [ 'post' => $postInfo, 'category' => $categoryInfo, 'user' => $userInfo, 'user_colour' => $userColour, 'comments_count' => $commentsCount, ]; } return $posts; } public function index($response, $request) { $news = $this->context->getNews(); $categories = $news->getAllCategories(); $pagination = new Pagination($news->countAllPosts(onlyFeatured: true), 5); if(!$pagination->hasValidOffset()) return 404; $postInfos = $news->getAllPosts(onlyFeatured: true, pagination: $pagination); $posts = $this->fetchPostInfo($postInfos); $response->setContent(Template::renderRaw('news.index', [ 'news_categories' => $categories, 'news_posts' => $posts, 'news_pagination' => $pagination, ])); } public function viewCategory($response, $request, string $fileName) { $news = $this->context->getNews(); $categoryId = pathinfo($fileName, PATHINFO_FILENAME); $type = pathinfo($fileName, PATHINFO_EXTENSION); try { $categoryInfo = $news->getCategoryById($categoryId); } catch(RuntimeException $ex) { return 404; } if($type === 'atom') return $this->feedCategoryAtom($response, $request, $categoryInfo); elseif($type === 'rss') return $this->feedCategoryRss($response, $request, $categoryInfo); elseif($type !== '') return 404; $pagination = new Pagination($news->countPostsByCategory($categoryInfo), 5); if(!$pagination->hasValidOffset()) return 404; $postInfos = $news->getPostsByCategory($categoryInfo, pagination: $pagination); $posts = $this->fetchPostInfo($postInfos, [$categoryInfo->getId() => $categoryInfo]); $response->setContent(Template::renderRaw('news.category', [ 'news_category' => $categoryInfo, 'news_posts' => $posts, 'news_pagination' => $pagination, ])); } public function viewPost($response, $request, string $postId) { $news = $this->context->getNews(); $users = $this->context->getUsers(); $comments = $this->context->getComments(); try { $postInfo = $news->getPostById($postId); } catch(RuntimeException $ex) { return 404; } if(!$postInfo->isPublished() || $postInfo->isDeleted()) return 404; $categoryInfo = $news->getCategoryByPost($postInfo); $comments = $this->context->getComments(); if($postInfo->hasCommentsCategoryId()) try { $commentsCategory = $comments->getCategoryById($postInfo->getCommentsCategoryId()); } catch(RuntimeException $ex) {} if(!isset($commentsCategory)) { $commentsCategory = $comments->ensureCategory($postInfo->getCommentsCategoryName()); $news->updatePostCommentCategory($postInfo, $commentsCategory); } $userInfo = null; $userColour = null; if($postInfo->hasUserId()) try { $userInfo = $users->getUser($postInfo->getUserId(), 'id'); $userColour = $users->getUserColour($userInfo); } catch(RuntimeException $ex) {} $comments = new CommentsEx($this->context, $comments, $users); $response->setContent(Template::renderRaw('news.post', [ 'post_info' => $postInfo, 'post_category_info' => $categoryInfo, 'post_user_info' => $userInfo, 'post_user_colour' => $userColour, 'comments_info' => $comments->getCommentsForLayout($commentsCategory), ])); } private function createFeed(string $feedMode, ?NewsCategoryInfo $categoryInfo, array $posts): Feed { $hasCategory = $categoryInfo !== null; $siteName = $this->context->getConfig()->getString('site.name', 'Misuzu'); $feed = (new Feed) ->setTitle($siteName . ' ยป ' . ($hasCategory ? $categoryInfo->getName() : 'Featured News')) ->setDescription($hasCategory ? $categoryInfo->getDescription() : 'A live featured news feed.') ->setContentUrl(url_prefix(false) . ($hasCategory ? url('news-category', ['category' => $categoryInfo->getId()]) : url('news-index'))) ->setFeedUrl(url_prefix(false) . ($hasCategory ? url("news-category-feed-{$feedMode}", ['category' => $categoryInfo->getId()]) : url("news-feed-{$feedMode}"))); foreach($posts as $post) { $postInfo = $post['post']; $userInfo = $post['user']; $userId = 0; $userName = 'Author'; if($userInfo !== null) { $userId = $userInfo->getId(); $userName = $userInfo->getName(); } $postUrl = url_prefix(false) . url('news-post', ['post' => $postInfo->getId()]); $commentsUrl = url_prefix(false) . url('news-post-comments', ['post' => $postInfo->getId()]); $authorUrl = url_prefix(false) . url('user-profile', ['user' => $userId]); $feedItem = (new FeedItem) ->setTitle($postInfo->getTitle()) ->setSummary($postInfo->getFirstParagraph()) ->setContent(Parser::instance(Parser::MARKDOWN)->parseText($postInfo->getBody())) ->setCreationDate($postInfo->getCreatedTime()) ->setUniqueId($postUrl) ->setContentUrl($postUrl) ->setCommentsUrl($commentsUrl) ->setAuthorName($userName) ->setAuthorUrl($authorUrl); if(!$feed->hasLastUpdate() || $feed->getLastUpdate() < $feedItem->getCreationDate()) $feed->setLastUpdate($feedItem->getCreationDate()); $feed->addItem($feedItem); } return $feed; } private function fetchPostInfoForFeed(array $postInfos): array { $news = $this->context->getNews(); $users = $this->context->getUsers(); $posts = []; $userInfos = []; foreach($postInfos as $postInfo) { $userId = $postInfo->getUserId(); if(array_key_exists($userId, $userInfos)) { $userInfo = $userInfos[$userId]; } else { try { $userInfo = $users->getUser($userId, 'id'); } catch(RuntimeException $ex) { $userInfo = null; } $userInfos[$userId] = $userInfo; } $posts[] = [ 'post' => $postInfo, 'user' => $userInfo, ]; } return $posts; } private function getFeaturedPostsForFeed(): array { return $this->fetchPostInfoForFeed( $this->context->getNews()->getAllPosts( onlyFeatured: true, pagination: new Pagination(10) ) ); } public function feedIndexAtom($response, $request) { $response->setContentType('application/atom+xml; charset=utf-8'); return (new AtomFeedSerializer)->serializeFeed( self::createFeed('atom', null, $this->getFeaturedPostsForFeed()) ); } public function feedIndexRss($response, $request) { $response->setContentType('application/rss+xml; charset=utf-8'); return (new RssFeedSerializer)->serializeFeed( self::createFeed('rss', null, $this->getFeaturedPostsForFeed()) ); } private function getCategoryPostsForFeed(NewsCategoryInfo $categoryInfo): array { return $this->fetchPostInfoForFeed( $this->context->getNews()->getPostsByCategory($categoryInfo, pagination: new Pagination(10)) ); } public function feedCategoryAtom($response, $request, NewsCategoryInfo $categoryInfo) { $response->setContentType('application/atom+xml; charset=utf-8'); return (new AtomFeedSerializer)->serializeFeed( self::createFeed('atom', $categoryInfo, $this->getCategoryPostsForFeed($categoryInfo)) ); } public function feedCategoryRss($response, $request, NewsCategoryInfo $categoryInfo) { $response->setContentType('application/rss+xml; charset=utf-8'); return (new RssFeedSerializer)->serializeFeed( self::createFeed('rss', $categoryInfo, $this->getCategoryPostsForFeed($categoryInfo)) ); } }