misuzu/src/Changelog/ChangelogRoutes.php

161 lines
6.2 KiB
PHP

<?php
namespace Misuzu\Changelog;
use ErrorException;
use RuntimeException;
use Index\Http\Routing\{HttpGet,RouteHandler};
use Misuzu\{Pagination,SiteInfo,Template};
use Misuzu\Auth\AuthInfo;
use Misuzu\Comments\{Comments,CommentsEx};
use Misuzu\Feeds\{Feed,FeedItem,AtomFeedSerializer,RssFeedSerializer};
use Misuzu\URLs\{URLInfo,URLRegistry};
use Misuzu\Users\UsersContext;
final class ChangelogRoutes extends RouteHandler {
public function __construct(
private SiteInfo $siteInfo,
private URLRegistry $urls,
private Changelog $changelog,
private UsersContext $usersCtx,
private AuthInfo $authInfo,
private Comments $comments
) {}
private function getCommentsInfo(string $categoryName): object {
$comments = new CommentsEx($this->authInfo, $this->comments, $this->usersCtx);
return $comments->getCommentsForLayout($categoryName);
}
#[HttpGet('/changelog')]
#[URLInfo('changelog-index', '/changelog', ['date' => '<date>', 'user' => '<user>', 'tags' => '<tags>', 'p' => '<page>'])]
public function getIndex($response, $request) {
$filterDate = (string)$request->getParam('date');
$filterUser = (string)$request->getParam('user', FILTER_SANITIZE_NUMBER_INT);
$filterTags = (string)$request->getParam('tags');
if(empty($filterDate))
$filterDate = null;
else
try {
$dateParts = explode('-', $filterDate, 3);
$filterDate = gmmktime(12, 0, 0, (int)$dateParts[1], (int)$dateParts[2], (int)$dateParts[0]);
} catch(ErrorException $ex) {
return 404;
}
if(empty($filterUser))
$filterUser = null;
else
try {
$filterUser = $this->usersCtx->getUserInfo($filterUser);
} catch(RuntimeException $ex) {
return 404;
}
if(empty($filterTags))
$filterTags = null;
else {
$filterTags = explode(',', $filterTags);
foreach($filterTags as &$tag)
$tag = trim($tag);
}
$count = $this->changelog->countChanges($filterUser, $filterDate, $filterTags);
$pagination = new Pagination($count, 30);
if(!$pagination->hasValidOffset())
return 404;
$changes = [];
$changeInfos = $this->changelog->getChanges(userInfo: $filterUser, dateTime: $filterDate, tags: $filterTags, pagination: $pagination);
$commentsCategoryName = null;
foreach($changeInfos as $changeInfo) {
$userInfo = $changeInfo->hasUserId() ? $this->usersCtx->getUserInfo($changeInfo->getUserId()) : null;
if($commentsCategoryName === null)
$commentsCategoryName = $changeInfo->getCommentsCategoryName();
$changes[] = [
'change' => $changeInfo,
'user' => $userInfo,
'user_colour' => $this->usersCtx->getUserColour($userInfo),
];
}
if(empty($changes))
return 404;
return Template::renderRaw('changelog.index', [
'changelog_infos' => $changes,
'changelog_date' => $filterDate,
'changelog_user' => $filterUser,
'changelog_tags' => $filterTags,
'changelog_pagination' => $pagination,
'comments_info' => empty($filterDate) && $commentsCategoryName !== null ? null : $this->getCommentsInfo($commentsCategoryName),
]);
}
#[HttpGet('/changelog/change/([0-9]+)')]
#[URLInfo('changelog-change', '/changelog/change/<change>')]
#[URLInfo('changelog-change-comments', '/changelog/change/<change>', fragment: 'comments')]
public function getChange($response, $request, string $changeId) {
try {
$changeInfo = $this->changelog->getChange($changeId);
} catch(RuntimeException $ex) {
return 404;
}
$tagInfos = $this->changelog->getTags(changeInfo: $changeInfo);
$userInfo = $changeInfo->hasUserId() ? $this->usersCtx->getUserInfo($changeInfo->getUserId()) : null;
return Template::renderRaw('changelog.change', [
'change_info' => $changeInfo,
'change_tags' => $tagInfos,
'change_user_info' => $userInfo,
'change_user_colour' => $this->usersCtx->getUserColour($userInfo),
'comments_info' => $this->getCommentsInfo($changeInfo->getCommentsCategoryName()),
]);
}
private function createFeed(string $feedMode): Feed {
$siteName = $this->siteInfo->getName();
$changes = $this->changelog->getChanges(pagination: new Pagination(10));
$feed = (new Feed)
->setTitle($siteName . ' » Changelog')
->setDescription('Live feed of changes to ' . $siteName . '.')
->setContentUrl($this->siteInfo->getURL() . $this->urls->format('changelog-index'))
->setFeedUrl($this->siteInfo->getURL() . $this->urls->format("changelog-feed-{$feedMode}"));
foreach($changes as $change) {
$changeUrl = $this->siteInfo->getURL() . $this->urls->format('changelog-change', ['change' => $change->getId()]);
$commentsUrl = $this->siteInfo->getURL() . $this->urls->format('changelog-change-comments', ['change' => $change->getId()]);
$feedItem = (new FeedItem)
->setTitle($change->getActionText() . ': ' . $change->getSummary())
->setCreationDate($change->getCreatedTime())
->setUniqueId($changeUrl)
->setContentUrl($changeUrl)
->setCommentsUrl($commentsUrl);
$feed->addItem($feedItem);
}
return $feed;
}
#[HttpGet('/changelog.rss')]
#[URLInfo('changelog-feed-rss', '/changelog.rss')]
public function getFeedRSS($response) {
$response->setContentType('application/rss+xml; charset=utf-8');
return (new RssFeedSerializer)->serializeFeed($this->createFeed('rss'));
}
#[HttpGet('/changelog.atom')]
#[URLInfo('changelog-feed-atom', '/changelog.atom')]
public function getFeedAtom($response) {
$response->setContentType('application/atom+xml; charset=utf-8');
return (new AtomFeedSerializer)->serializeFeed($this->createFeed('atom'));
}
}