Rewrote the Pagination handler.

This commit is contained in:
flash 2024-12-19 01:22:26 +00:00
parent 02adfa1f4f
commit d3f9c299af
38 changed files with 135 additions and 147 deletions

View file

@ -32,13 +32,13 @@ if($categoryInfo->isLink) {
return; return;
} }
$forumPagination = new Pagination($msz->forumCtx->topics->countTopics( $forumPagination = Pagination::fromInput($msz->forumCtx->topics->countTopics(
categoryInfo: $categoryInfo, categoryInfo: $categoryInfo,
global: true, global: true,
deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false
), 20); ), 20);
if(!$forumPagination->hasValidOffset()) if(!$forumPagination->validOffset)
Template::throwError(404); Template::throwError(404);
$children = []; $children = [];

View file

@ -101,18 +101,18 @@ $topicPosts = $topicInfo->postsCount;
if($canDeleteAny) if($canDeleteAny)
$topicPosts += $topicInfo->deletedPostsCount; $topicPosts += $topicInfo->deletedPostsCount;
$topicPagination = new Pagination($topicPosts, 10, 'page');
if(isset($preceedingPostCount)) if(isset($preceedingPostCount))
$topicPagination->setPage((int)floor($preceedingPostCount / $topicPagination->getRange()), true); $pagination = Pagination::fromPage($topicPosts, (int)floor($preceedingPostCount / 10), 10, 0);
else
$pagination = Pagination::fromInput($topicPosts, 10, 'page');
if(!$topicPagination->hasValidOffset()) if(!$pagination->validOffset)
Template::throwError(404); Template::throwError(404);
$postInfos = $msz->forumCtx->posts->getPosts( $postInfos = $msz->forumCtx->posts->getPosts(
topicInfo: $topicInfo, topicInfo: $topicInfo,
deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false, deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false,
pagination: $topicPagination, pagination: $pagination,
); );
if(empty($postInfos)) if(empty($postInfos))
@ -163,7 +163,7 @@ Template::render('forum.topic', [
'category_info' => $categoryInfo, 'category_info' => $categoryInfo,
'topic_posts' => $posts, 'topic_posts' => $posts,
'can_reply' => $canReply, 'can_reply' => $canReply,
'topic_pagination' => $topicPagination, 'topic_pagination' => $pagination,
'topic_can_delete' => $canDelete, 'topic_can_delete' => $canDelete,
'topic_can_delete_any' => $canDeleteAny, 'topic_can_delete_any' => $canDeleteAny,
'topic_can_nuke_or_restore' => $canNukeOrRestore, 'topic_can_nuke_or_restore' => $canNukeOrRestore,

View file

@ -9,8 +9,8 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('global')->check(Perm::G_CL_CHANGES_MANAGE)) if(!$msz->authInfo->getPerms('global')->check(Perm::G_CL_CHANGES_MANAGE))
Template::throwError(403); Template::throwError(403);
$pagination = new Pagination($msz->changelog->countChanges(), 30); $pagination = Pagination::fromInput($msz->changelog->countChanges(), 30);
if(!$pagination->hasValidOffset()) if(!$pagination->validOffset)
Template::throwError(404); Template::throwError(404);
$changeInfos = $msz->changelog->getChanges(pagination: $pagination); $changeInfos = $msz->changelog->getChanges(pagination: $pagination);

View file

@ -31,8 +31,8 @@ if(filter_input(INPUT_GET, 'm') === 'explode') {
return; return;
} }
$pagination = new Pagination($msz->forumCtx->topicRedirects->countTopicRedirects(), 20); $pagination = Pagination::fromInput($msz->forumCtx->topicRedirects->countTopicRedirects(), 20);
if(!$pagination->hasValidOffset()) if(!$pagination->validOffset)
Template::throwError(404); Template::throwError(404);
$redirs = $msz->forumCtx->topicRedirects->getTopicRedirects(pagination: $pagination); $redirs = $msz->forumCtx->topicRedirects->getTopicRedirects(pagination: $pagination);

View file

@ -9,9 +9,8 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('global')->check(Perm::G_LOGS_VIEW)) if(!$msz->authInfo->getPerms('global')->check(Perm::G_LOGS_VIEW))
Template::throwError(403); Template::throwError(403);
$pagination = new Pagination($msz->auditLog->countLogs(), 50); $pagination = Pagination::fromInput($msz->auditLog->countLogs(), 50);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$logs = iterator_to_array($msz->auditLog->getLogs(pagination: $pagination)); $logs = iterator_to_array($msz->auditLog->getLogs(pagination: $pagination));

View file

@ -7,9 +7,8 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('global')->check(Perm::G_NEWS_CATEGORIES_MANAGE)) if(!$msz->authInfo->getPerms('global')->check(Perm::G_NEWS_CATEGORIES_MANAGE))
Template::throwError(403); Template::throwError(403);
$pagination = new Pagination($msz->news->countCategories(), 15); $pagination = Pagination::fromInput($msz->news->countCategories(), 15);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$categories = $msz->news->getCategories(pagination: $pagination); $categories = $msz->news->getCategories(pagination: $pagination);

View file

@ -7,12 +7,12 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('global')->check(Perm::G_NEWS_POSTS_MANAGE)) if(!$msz->authInfo->getPerms('global')->check(Perm::G_NEWS_POSTS_MANAGE))
Template::throwError(403); Template::throwError(403);
$pagination = new Pagination($msz->news->countPosts( $pagination = Pagination::fromInput($msz->news->countPosts(
includeScheduled: true, includeScheduled: true,
includeDeleted: true includeDeleted: true
), 15); ), 15);
if(!$pagination->hasValidOffset()) if(!$pagination->validOffset)
Template::throwError(404); Template::throwError(404);
$posts = $msz->news->getPosts( $posts = $msz->news->getPosts(

View file

@ -19,9 +19,8 @@ if(filter_has_var(INPUT_GET, 'u')) {
} }
} }
$pagination = new Pagination($msz->usersCtx->bans->countBans(userInfo: $filterUser), 10); $pagination = Pagination::fromInput($msz->usersCtx->bans->countBans(userInfo: $filterUser), 10);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$banList = []; $banList = [];

View file

@ -9,9 +9,8 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('user')->check(Perm::U_USERS_MANAGE)) if(!$msz->authInfo->getPerms('user')->check(Perm::U_USERS_MANAGE))
Template::throwError(403); Template::throwError(403);
$pagination = new Pagination($msz->usersCtx->users->countUsers(), 30); $pagination = Pagination::fromInput($msz->usersCtx->users->countUsers(), 30);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$userList = []; $userList = [];

View file

@ -19,9 +19,8 @@ if(filter_has_var(INPUT_GET, 'u')) {
} }
} }
$pagination = new Pagination($msz->usersCtx->modNotes->countNotes(userInfo: $filterUser), 10); $pagination = Pagination::fromInput($msz->usersCtx->modNotes->countNotes(userInfo: $filterUser), 10);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$notes = []; $notes = [];

View file

@ -8,9 +8,8 @@ if(!$msz->authInfo->getPerms('user')->check(Perm::U_ROLES_MANAGE))
Template::throwError(403); Template::throwError(403);
$roles = $msz->usersCtx->roles; $roles = $msz->usersCtx->roles;
$pagination = new Pagination($roles->countRoles(), 10); $pagination = Pagination::fromInput($roles->countRoles(), 10);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$rolesAll = []; $rolesAll = [];

View file

@ -19,9 +19,8 @@ if(filter_has_var(INPUT_GET, 'u')) {
} }
} }
$pagination = new Pagination($msz->usersCtx->warnings->countWarnings(userInfo: $filterUser), 10); $pagination = Pagination::fromInput($msz->usersCtx->warnings->countWarnings(userInfo: $filterUser), 10);
if(!$pagination->validOffset)
if(!$pagination->hasValidOffset())
Template::throwError(404); Template::throwError(404);
$warnList = []; $warnList = [];

View file

@ -76,7 +76,7 @@ $canManageUsers = $msz->authInfo->getPerms('user')->check(Perm::U_USERS_MANAGE);
$deleted = $canManageUsers ? null : false; $deleted = $canManageUsers ? null : false;
$rolesAll = $msz->usersCtx->roles->getRoles(hidden: false); $rolesAll = $msz->usersCtx->roles->getRoles(hidden: false);
$pagination = new Pagination($msz->usersCtx->users->countUsers(roleInfo: $roleInfo, deleted: $deleted), 15); $pagination = Pagination::fromInput($msz->usersCtx->users->countUsers(roleInfo: $roleInfo, deleted: $deleted), 15);
$userList = []; $userList = [];
$userInfos = $msz->usersCtx->users->getUsers( $userInfos = $msz->usersCtx->users->getUsers(

View file

@ -10,8 +10,8 @@ $currentUser = $msz->authInfo->userInfo;
if($currentUser === null) if($currentUser === null)
Template::throwError(401); Template::throwError(401);
$loginHistoryPagination = new Pagination($msz->authCtx->loginAttempts->countAttempts(userInfo: $currentUser), 5, 'hp'); $loginHistoryPagination = Pagination::fromInput($msz->authCtx->loginAttempts->countAttempts(userInfo: $currentUser), 5, 'hp');
$accountLogPagination = new Pagination($msz->auditLog->countLogs(userInfo: $currentUser), 10, 'ap'); $accountLogPagination = Pagination::fromInput($msz->auditLog->countLogs(userInfo: $currentUser), 10, 'ap');
$loginHistory = iterator_to_array($msz->authCtx->loginAttempts->getAttempts(userInfo: $currentUser, pagination: $loginHistoryPagination)); $loginHistory = iterator_to_array($msz->authCtx->loginAttempts->getAttempts(userInfo: $currentUser, pagination: $loginHistoryPagination));
$auditLogs = iterator_to_array($msz->auditLog->getLogs(userInfo: $currentUser, pagination: $accountLogPagination)); $auditLogs = iterator_to_array($msz->auditLog->getLogs(userInfo: $currentUser, pagination: $accountLogPagination));

View file

@ -42,7 +42,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
} else break; } else break;
} }
$pagination = new Pagination($msz->authCtx->sessions->countSessions(userInfo: $currentUser), 10); $pagination = Pagination::fromInput($msz->authCtx->sessions->countSessions(userInfo: $currentUser), 10);
$sessionList = []; $sessionList = [];
$sessionInfos = $msz->authCtx->sessions->getSessions(userInfo: $currentUser, pagination: $pagination); $sessionInfos = $msz->authCtx->sessions->getSessions(userInfo: $currentUser, pagination: $pagination);

View file

@ -87,8 +87,8 @@ class AuditLog {
if($hasRemoteAddr) if($hasRemoteAddr)
$stmt->addParameter(++$args, $remoteAddr); $stmt->addParameter(++$args, $remoteAddr);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -112,8 +112,8 @@ class LoginAttempts {
if($hasTimeRange) if($hasTimeRange)
$stmt->addParameter(++$args, $timeRange); $stmt->addParameter(++$args, $timeRange);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -78,8 +78,8 @@ class Sessions {
if($hasUserInfo) if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo); $stmt->addParameter(++$args, $userInfo);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -166,8 +166,8 @@ class Changelog {
foreach($tags as $tag) foreach($tags as $tag)
$stmt->addParameter(++$args, (string)$tag); $stmt->addParameter(++$args, (string)$tag);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -64,8 +64,8 @@ final class ChangelogRoutes implements RouteHandler, UrlSource {
} }
$count = $this->changelog->countChanges($filterUser, $filterDate, $filterTags); $count = $this->changelog->countChanges($filterUser, $filterDate, $filterTags);
$pagination = new Pagination($count, 30); $pagination = Pagination::fromRequest($request, $count, 30, 'p');
if(!$pagination->hasValidOffset()) if(!$pagination->validOffset)
return 404; return 404;
$changes = []; $changes = [];

View file

@ -65,8 +65,8 @@ class Comments {
if($hasOwner) if($hasOwner)
$stmt->addParameter(++$args, $owner); $stmt->addParameter(++$args, $owner);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -41,8 +41,8 @@ class Counters {
$args = 0; $args = 0;
$stmt = $this->cache->get($query); $stmt = $this->cache->get($query);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -154,8 +154,8 @@ class ForumCategories {
if($hasType) if($hasType)
$stmt->addParameter(++$args, $type); $stmt->addParameter(++$args, $type);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -186,8 +186,8 @@ class ForumPosts {
if($hasSearchQuery) if($hasSearchQuery)
$stmt->addParameter(++$args, $searchQuery); $stmt->addParameter(++$args, $searchQuery);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -42,12 +42,12 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
upToPostInfo: $post, upToPostInfo: $post,
deleted: $canDeleteAny ? null : false deleted: $canDeleteAny ? null : false
); );
$pageNumber = (int)ceil($postsCount / 10); // epic magic number $pageNumber = ((int)floor($postsCount / 10)) + 1; // epic magic number
return $response->redirect($this->urls->format('forum-topic', [ return $response->redirect($this->urls->format('forum-topic', [
'topic' => $post->topicId, 'topic' => $post->topicId,
'page' => $pageNumber, 'page' => $pageNumber,
'post' => sprintf('p%s', $post->id), 'topic_fragment' => sprintf('p%s', $post->id),
])); ]));
} }

View file

@ -56,8 +56,8 @@ class ForumTopicRedirects {
if($hasUserInfo) if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo); $stmt->addParameter(++$args, $userInfo);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -193,8 +193,8 @@ class ForumTopics {
if($hasSearchQuery) if($hasSearchQuery)
$stmt->addParameter(++$args, $searchQuery); $stmt->addParameter(++$args, $searchQuery);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -34,7 +34,7 @@ class LegacyRoutes implements RouteHandler, UrlSource {
$urls->register('forum-reply-new', '/forum/posting.php', ['t' => '<topic>']); $urls->register('forum-reply-new', '/forum/posting.php', ['t' => '<topic>']);
$urls->register('forum-category', '/forum/forum.php', ['f' => '<forum>', 'p' => '<page>']); $urls->register('forum-category', '/forum/forum.php', ['f' => '<forum>', 'p' => '<page>']);
$urls->register('forum-category-root', '/forum/index.php', fragment: '<forum>'); $urls->register('forum-category-root', '/forum/index.php', fragment: '<forum>');
$urls->register('forum-topic', '/forum/topic.php', ['t' => '<topic>', 'page' => '<page>'], '<post>'); $urls->register('forum-topic', '/forum/topic.php', ['t' => '<topic>', 'page' => '<page>'], '<topic_fragment>');
$urls->register('forum-topic-create', '/forum/posting.php', ['f' => '<forum>']); $urls->register('forum-topic-create', '/forum/posting.php', ['f' => '<forum>']);
$urls->register('forum-post', '/forum/topic.php', ['p' => '<post>'], 'p<post>'); $urls->register('forum-post', '/forum/topic.php', ['p' => '<post>'], 'p<post>');
$urls->register('forum-post-create', '/forum/posting.php', ['t' => '<topic>']); $urls->register('forum-post-create', '/forum/posting.php', ['t' => '<topic>']);

View file

@ -148,8 +148,8 @@ class MessagesDatabase {
if($hasReplyTo) if($hasReplyTo)
$stmt->addParameter(++$args, $replyTo instanceof MessageInfo ? $replyTo->replyToId : $replyTo); $stmt->addParameter(++$args, $replyTo instanceof MessageInfo ? $replyTo->replyToId : $replyTo);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -116,13 +116,13 @@ class MessagesRoutes implements RouteHandler, UrlSource {
$sent = $folderTrash ? null : !$folderDrafts; $sent = $folderTrash ? null : !$folderDrafts;
$deleted = $folderTrash; $deleted = $folderTrash;
$pagination = new Pagination($msgsDb->countMessages( $pagination = Pagination::fromRequest($request, $msgsDb->countMessages(
ownerInfo: $selfInfo, ownerInfo: $selfInfo,
authorInfo: $authorInfo, authorInfo: $authorInfo,
recipientInfo: $recipientInfo, recipientInfo: $recipientInfo,
sent: $sent, sent: $sent,
deleted: $deleted, deleted: $deleted,
), 50, 'page'); ), 50);
$messageInfos = $msgsDb->getMessages( $messageInfos = $msgsDb->getMessages(
ownerInfo: $selfInfo, ownerInfo: $selfInfo,

View file

@ -54,8 +54,8 @@ class News {
$args = 0; $args = 0;
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();
@ -259,8 +259,8 @@ class News {
if($hasSearchQuery) if($hasSearchQuery)
$stmt->addParameter(++$args, $searchQuery); $stmt->addParameter(++$args, $searchQuery);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -101,11 +101,11 @@ class NewsRoutes implements RouteHandler, UrlSource {
#[HttpGet('/news')] #[HttpGet('/news')]
#[UrlFormat('news-index', '/news', ['p' => '<page>'])] #[UrlFormat('news-index', '/news', ['p' => '<page>'])]
public function getIndex(): int|string { public function getIndex(HttpResponseBuilder $response, HttpRequest $request): int|string {
$categories = $this->news->getCategories(hidden: false); $categories = $this->news->getCategories(hidden: false);
$pagination = new Pagination($this->news->countPosts(onlyFeatured: true), 5); $pagination = Pagination::fromRequest($request, $this->news->countPosts(onlyFeatured: true), 5, 'p');
if(!$pagination->hasValidOffset()) if(!$pagination->validOffset)
return 404; return 404;
$posts = $this->getNewsPostsForView($pagination); $posts = $this->getNewsPostsForView($pagination);
@ -129,8 +129,8 @@ class NewsRoutes implements RouteHandler, UrlSource {
if($type !== '') if($type !== '')
return $this->getFeed($response, $request, $categoryInfo); return $this->getFeed($response, $request, $categoryInfo);
$pagination = new Pagination($this->news->countPosts(categoryInfo: $categoryInfo), 5); $pagination = Pagination::fromRequest($request, $this->news->countPosts(categoryInfo: $categoryInfo), 5, 'p');
if(!$pagination->hasValidOffset()) if(!$pagination->validOffset)
return 404; return 404;
$posts = $this->getNewsPostsForView($pagination, $categoryInfo); $posts = $this->getNewsPostsForView($pagination, $categoryInfo);

View file

@ -1,79 +1,74 @@
<?php <?php
namespace Misuzu; namespace Misuzu;
use Index\Http\HttpRequest;
final class Pagination { final class Pagination {
private const INVALID_OFFSET = -1; public private(set) bool $validOffset;
private const START_PAGE = 1;
public const DEFAULT_PARAM = 'p';
private int $count = 0; public function __construct(
private int $range = 0; public private(set) int $count = 0,
private int $offset = 0; public private(set) int $range = 0,
public private(set) int $offset = 0
public function __construct(int $count, int $range = -1, ?string $readParam = self::DEFAULT_PARAM) { ) {
$this->count = max(0, $count); $this->count = max(0, $count);
$this->range = $range < 0 ? $count : $range; if($range < 1)
$this->range = $count;
if(!empty($readParam)) $this->validOffset = $offset >= 0 && $offset < $count;
$this->readPage($readParam); $this->offset = max(0, $offset);
} }
public function getCount(): int { public int $pages {
return $this->count; get => (int)ceil($this->count / $this->range);
} }
public function getRange(): int { public int $page {
return $this->range; get => (int)floor($this->offset / $this->range) + 1;
} }
public function getPages(): int { public static function fromPage(
return (int)ceil($this->getCount() / $this->getRange()); int $count,
int $page,
int $range = 0,
int $firstPage = 1
): self {
if($range < 1)
$range = $count;
$offset = $range * ($page - $firstPage);
if($offset < 0 || $offset >= $count)
$offset = -1;
return new Pagination($count, $range, $offset);
} }
public function hasValidOffset(): bool { public static function fromInput(
return $this->offset !== self::INVALID_OFFSET; int $count,
int $range = 0,
string $pageParam = 'p',
int $firstPage = 1
): self {
return self::fromPage(
$count,
(int)(filter_input(INPUT_GET, $pageParam, FILTER_SANITIZE_NUMBER_INT) ?? $firstPage),
$range,
$firstPage
);
} }
public function getOffset(): int { public static function fromRequest(
return $this->hasValidOffset() ? $this->offset : 0; HttpRequest $request,
} int $count,
int $range = 0,
public function setOffset(int $offset): self { string $pageParam = 'page',
if($offset < 0) int $firstPage = 1
$offset = self::INVALID_OFFSET; ): Pagination {
return self::fromPage(
$this->offset = $offset; $count,
return $this; (int)($request->getParam($pageParam, FILTER_SANITIZE_NUMBER_INT) ?? $firstPage),
} $range,
$firstPage
public function getPage(): int { );
if($this->getOffset() < 1)
return self::START_PAGE;
return (int)floor($this->getOffset() / $this->getRange()) + self::START_PAGE;
}
public function setPage(int $page, bool $zeroBased = false): self {
if(!$zeroBased)
$page -= self::START_PAGE;
$this->setOffset($this->getRange() * $page);
return $this;
}
/** @param ?array<string, mixed> $source */
public function readPage(string $name = self::DEFAULT_PARAM, int $default = self::START_PAGE, ?array $source = null): self {
$this->setPage(self::param($name, $default, $source));
return $this;
}
/** @param ?array<string, mixed> $source */
public static function param(string $name = self::DEFAULT_PARAM, int $default = self::START_PAGE, ?array $source = null): int {
$source ??= $_GET;
if(isset($source[$name]) && is_string($source[$name]) && ctype_digit($source[$name]))
return (int)$source[$name];
return $default;
} }
} }

View file

@ -95,8 +95,8 @@ class Bans {
if($hasUserInfo) if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo); $stmt->addParameter(++$args, $userInfo);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -87,8 +87,8 @@ class ModNotes {
if($hasAuthorInfo) if($hasAuthorInfo)
$stmt->addParameter(++$args, $authorInfo); $stmt->addParameter(++$args, $authorInfo);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -86,8 +86,8 @@ class Roles {
if($hasUserInfo) if($hasUserInfo)
$stmt->nextParameter($userInfo); $stmt->nextParameter($userInfo);
if($hasPagination) { if($hasPagination) {
$stmt->nextParameter($pagination->getRange()); $stmt->nextParameter($pagination->range);
$stmt->nextParameter($pagination->getOffset()); $stmt->nextParameter($pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -207,8 +207,8 @@ class Users {
if($hasSearchQuery) if($hasSearchQuery)
$stmt->addParameter(++$args, $searchQuery); $stmt->addParameter(++$args, $searchQuery);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();

View file

@ -102,8 +102,8 @@ class Warnings {
if($hasBacklog) if($hasBacklog)
$stmt->addParameter(++$args, $backlog); $stmt->addParameter(++$args, $backlog);
if($hasPagination) { if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange()); $stmt->addParameter(++$args, $pagination->range);
$stmt->addParameter(++$args, $pagination->getOffset()); $stmt->addParameter(++$args, $pagination->offset);
} }
$stmt->execute(); $stmt->execute();