From 48f68cfa2d2e2559547c9026fafacf31d51a1da4 Mon Sep 17 00:00:00 2001 From: flashwave Date: Wed, 16 May 2018 22:48:33 +0200 Subject: [PATCH] Fix frontend pagination. --- assets/less/mio/classes/news/pagination.less | 10 +- .../less/mio/classes/settings/pagination.less | 10 +- public/news.php | 62 +++++++----- public/settings.php | 47 ++++++--- src/Application.php | 1 - views/mio/macros.twig | 95 +++++++++++-------- views/mio/news/category.twig | 6 +- views/mio/news/index.twig | 4 +- views/mio/news/macros.twig | 4 +- views/mio/news/post.twig | 2 +- views/mio/settings/avatar.twig | 5 +- views/mio/settings/login-history.twig | 2 +- views/mio/settings/sessions.twig | 2 +- 13 files changed, 157 insertions(+), 93 deletions(-) diff --git a/assets/less/mio/classes/news/pagination.less b/assets/less/mio/classes/news/pagination.less index 321a4e1c..90711f49 100644 --- a/assets/less/mio/classes/news/pagination.less +++ b/assets/less/mio/classes/news/pagination.less @@ -11,6 +11,7 @@ &__option { background: #9475b2; + color: #306; height: 20px; width: 20px; @@ -18,6 +19,11 @@ margin-right: 1px; } + &--disabled { + color: #383838; + background: #777; + } + @media (max-width: @mio-news-mobile) { height: 30px; width: 30px; @@ -32,10 +38,12 @@ height: 100%; text-align: center; text-decoration: none; - color: #306; + color: inherit; &--prev, &--next, + &--first, + &--last, &--active, &:hover { font-weight: bold; diff --git a/assets/less/mio/classes/settings/pagination.less b/assets/less/mio/classes/settings/pagination.less index 1b4a3e1d..46fdcced 100644 --- a/assets/less/mio/classes/settings/pagination.less +++ b/assets/less/mio/classes/settings/pagination.less @@ -13,6 +13,7 @@ &__option { background: #9475b2; + color: #306; height: 20px; width: 20px; @@ -20,6 +21,11 @@ margin-right: 1px; } + &--disabled { + color: #383838; + background: #777; + } + @media (max-width: @mio-news-mobile) { height: 30px; width: 30px; @@ -34,10 +40,12 @@ height: 100%; text-align: center; text-decoration: none; - color: #306; + color: inherit; &--prev, &--next, + &--first, + &--last, &--active, &:hover { font-weight: bold; diff --git a/public/news.php b/public/news.php index c3386c30..0986038b 100644 --- a/public/news.php +++ b/public/news.php @@ -7,8 +7,11 @@ $db = Database::connection(); $templating = $app->getTemplating(); $category_id = isset($_GET['c']) ? (int)$_GET['c'] : null; -$post_id = isset($_GET['n']) ? (int)$_GET['n'] : null; -$page_id = (int)($_GET['p'] ?? 1); +$post_id = isset($_GET['p']) ? (int)$_GET['p'] : (isset($_GET['n']) ? (int)$_GET['n'] : null); +$posts_offset = (int)($_GET['o'] ?? 0); +$posts_take = 5; + +$templating->vars(compact('posts_offset', 'posts_take')); if ($post_id !== null) { $getPost = $db->prepare(' @@ -42,14 +45,18 @@ if ($post_id !== null) { if ($category_id !== null) { $getCategory = $db->prepare(' SELECT - `category_id`, `category_name`, `category_description` - FROM `msz_news_categories` - WHERE `category_id` = :category_id + c.`category_id`, c.`category_name`, c.`category_description`, + COUNT(p.`post_id`) AS `posts_count` + FROM `msz_news_categories` as c + LEFT JOIN `msz_news_posts` as p + ON c.`category_id` = p.`category_id` + WHERE c.`category_id` = :category_id + GROUP BY c.`category_id` '); $getCategory->bindValue(':category_id', $category_id, PDO::PARAM_INT); $category = $getCategory->execute() ? $getCategory->fetch() : false; - if ($category === false) { + if ($category === false || $posts_offset < 0 || $posts_offset >= $category['posts_count']) { http_response_code(404); echo $templating->render('errors.404'); return; @@ -70,20 +77,13 @@ if ($category_id !== null) { ON u.`display_role` = r.`role_id` WHERE p.`category_id` = :category_id ORDER BY `created_at` DESC - LIMIT 0, 5 + LIMIT :offset, :take '); + $getPosts->bindValue('offset', $posts_offset); + $getPosts->bindValue('take', $posts_take); $getPosts->bindValue('category_id', $category['category_id'], PDO::PARAM_INT); $posts = $getPosts->execute() ? $getPosts->fetchAll() : false; - //$posts = $category->posts()->orderBy('created_at', 'desc')->paginate(5, ['*'], 'p', $page_id); - - //if (!is_valid_page($posts, $page_id)) { - if ($posts === false) { - http_response_code(404); - echo $templating->render('errors.404'); - return; - } - $getFeatured = $db->prepare(' SELECT `post_id`, `post_title` FROM `msz_news_posts` @@ -95,7 +95,7 @@ if ($category_id !== null) { $getFeatured->bindValue('category_id', $category['category_id'], PDO::PARAM_INT); $featured = $getFeatured->execute() ? $getFeatured->fetchAll() : []; - echo $templating->render('news.category', compact('category', 'posts', 'featured', 'page_id')); + echo $templating->render('news.category', compact('category', 'posts', 'featured')); return; } @@ -112,6 +112,23 @@ $getCategories = $db->prepare(' '); $categories = $getCategories->execute() ? $getCategories->fetchAll() : []; +$postsCount = (int)$db->query(' + SELECT COUNT(p.`post_id`) as `posts_count` + FROM `msz_news_posts` as p + LEFT JOIN `msz_news_categories` as c + ON p.`category_id` = c.`category_id` + WHERE p.`is_featured` = true + AND c.`is_hidden` = false +')->fetchColumn(); + +$templating->var('posts_count', $postsCount); + +if ($posts_offset < 0 || $posts_offset >= $postsCount) { + http_response_code(404); + echo $templating->render('errors.404'); + return; +} + $getPosts = $db->prepare(' SELECT p.`post_id`, p.`post_title`, p.`post_text`, p.`created_at`, @@ -128,17 +145,16 @@ $getPosts = $db->prepare(' WHERE p.`is_featured` = true AND c.`is_hidden` = false ORDER BY p.`created_at` DESC - LIMIT 0, 5 + LIMIT :offset, :take '); +$getPosts->bindValue('offset', $posts_offset); +$getPosts->bindValue('take', $posts_take); $posts = $getPosts->execute() ? $getPosts->fetchAll() : []; -//$posts = NewsPost::where('is_featured', true)->orderBy('created_at', 'desc')->paginate(5, ['*'], 'p', $page_id); - -//if (!is_valid_page($posts, $page_id)) { -if ($posts === false) { +if (!$posts) { http_response_code(404); echo $templating->render('errors.404'); return; } -echo $templating->render('news.index', compact('categories', 'posts', 'page_id')); +echo $templating->render('news.index', compact('categories', 'posts')); diff --git a/public/settings.php b/public/settings.php index 211d6364..023a74d1 100644 --- a/public/settings.php +++ b/public/settings.php @@ -7,7 +7,8 @@ require_once __DIR__ . '/../misuzu.php'; $db = Database::connection(); $templating = $app->getTemplating(); -$page_id = (int)($_GET['p'] ?? 1); +$query_offset = (int)($_GET['o'] ?? 0); +$query_take = 15; if (!$app->hasActiveSession()) { http_response_code(403); @@ -397,9 +398,13 @@ switch ($settings_mode) { break; case 'sessions': - /*$sessions = $settings_user->sessions() - ->orderBy('session_id', 'desc') - ->paginate(15, ['*'], 'p', $page_id);*/ + $getSessionCount = $db->prepare(' + SELECT COUNT(`session_id`) + FROM `msz_sessions` + WHERE `user_id` = :user_id + '); + $getSessionCount->bindValue('user_id', $app->getUserId()); + $sessionCount = $getSessionCount->execute() ? $getSessionCount->fetchColumn() : 0; $getSessions = $db->prepare(' SELECT @@ -408,19 +413,30 @@ switch ($settings_mode) { FROM `msz_sessions` WHERE `user_id` = :user_id ORDER BY `session_id` DESC - LIMIT 0, 15 + LIMIT :offset, :take '); + $getSessions->bindValue('offset', $query_offset); + $getSessions->bindValue('take', $query_take); $getSessions->bindValue('user_id', $app->getUserId()); $sessions = $getSessions->execute() ? $getSessions->fetchAll() : []; - $templating->var('active_session_id', $app->getSessionId()); - $templating->var('user_sessions', $sessions); + $templating->vars([ + 'active_session_id' => $app->getSessionId(), + 'user_sessions' => $sessions, + 'sessions_offset' => $query_offset, + 'sessions_take' => $query_take, + 'sessions_count' => $sessionCount, + ]); break; case 'login-history': - /*$login_attempts = $settings_user->loginAttempts() - ->orderBy('attempt_id', 'desc') - ->paginate(15, ['*'], 'p', $page_id);*/ + $getLoginAttemptsCount = $db->prepare(' + SELECT COUNT(`attempt_id`) + FROM `msz_login_attempts` + WHERE `user_id` = :user_id + '); + $getLoginAttemptsCount->bindValue('user_id', $app->getUserId()); + $loginAttemptsCount = $getLoginAttemptsCount->execute() ? $getLoginAttemptsCount->fetchColumn() : 0; $getLoginAttempts = $db->prepare(' SELECT @@ -429,12 +445,19 @@ switch ($settings_mode) { FROM `msz_login_attempts` WHERE `user_id` = :user_id ORDER BY `attempt_id` DESC - LIMIT 0, 15 + LIMIT :offset, :take '); + $getLoginAttempts->bindValue('offset', $query_offset); + $getLoginAttempts->bindValue('take', $query_take); $getLoginAttempts->bindValue('user_id', $app->getUserId()); $loginAttempts = $getLoginAttempts->execute() ? $getLoginAttempts->fetchAll() : []; - $templating->var('user_login_attempts', $loginAttempts); + $templating->vars([ + 'user_login_attempts' => $loginAttempts, + 'login_attempts_offset' => $query_offset, + 'login_attempts_take' => $query_take, + 'login_attempts_count' => $loginAttemptsCount, + ]); break; } diff --git a/src/Application.php b/src/Application.php index b857e020..19da7cd1 100644 --- a/src/Application.php +++ b/src/Application.php @@ -240,7 +240,6 @@ class Application extends ApplicationBase $this->templatingInstance->addFilter('byte_symbol'); $this->templatingInstance->addFilter('country_name', 'get_country_name'); $this->templatingInstance->addFilter('flip', 'array_flip'); - $this->templatingInstance->addFilter('create_pagination'); $this->templatingInstance->addFilter('first_paragraph'); $this->templatingInstance->addFilter('colour_get_css'); $this->templatingInstance->addFilter('colour_get_inherit'); diff --git a/views/mio/macros.twig b/views/mio/macros.twig index b1000978..e2abccf8 100644 --- a/views/mio/macros.twig +++ b/views/mio/macros.twig @@ -16,70 +16,83 @@ {% endmacro %} -{% macro pagination_segment(url_window, base_url, currentPage, classPrefix) %} - {% for page, url in url_window %} -
  • - - {{ page }} - -
  • - {% endfor %} -{% endmacro %} - -{% macro paginate(paginator, base_url, classPrefix, alwaysRender) %} +{% macro paginate(itemCount, itemRange, currentOffset, baseUrl, classPrefix, alwaysRender, useRanges, offsetParam) %} {% set alwaysRender = alwaysRender|default(false) %} - {% if alwaysRender or paginator.lastPage > 1 %} - {% set classPrefix = classPrefix|default('') %} - {% set separator = '%3F' in base_url|default('')|url_encode ? '&' : '?' %} - {% set base_url = base_url ~ separator %} + {% if alwaysRender or itemCount > itemRange %} + {% set classPrefix = classPrefix|default('') %} + {% set separator = '%3F' in baseUrl|default('')|url_encode ? '&' : '?' %} + {% set baseUrl = baseUrl ~ separator %} + {% set pageCount = (itemCount / itemRange)|round(0, 'ceil') %} + {% set currentPage = currentOffset // itemRange %} + {% set useRanges = useRanges|default(true) %} + {% set offsetParam = offsetParam|default(useRanges ? 'o' : 'p') %} diff --git a/views/mio/news/category.twig b/views/mio/news/category.twig index aa008650..d5ff50ec 100644 --- a/views/mio/news/category.twig +++ b/views/mio/news/category.twig @@ -3,7 +3,7 @@ {% from '@mio/news/macros.twig' import news_preview %} {% set title = category.category_name ~ ' :: News' %} -{% set canonical_url = '/news.php?c=' ~ category.category_id ~ (page_id > 1 ? '&p=' ~ page_id : '') %} +{% set canonical_url = '/news.php?c=' ~ category.category_id ~ (posts_offset > 0 ? '&o=' ~ posts_offset : '') %} {% block news_content %}
    @@ -34,12 +34,12 @@
    {% for featured_post in featured %} - {{ featured_post.post_title }} + {{ featured_post.post_title }} {% endfor %}
    {% endif %} - {# paginate(posts, '?c=' ~ category.category_id, 'news__') #} + {{ paginate(category.posts_count, posts_take, posts_offset, '/news.php?c=' ~ category.category_id, 'news__') }} diff --git a/views/mio/news/index.twig b/views/mio/news/index.twig index 1afd3df2..0c5dbf20 100644 --- a/views/mio/news/index.twig +++ b/views/mio/news/index.twig @@ -3,7 +3,7 @@ {% from '@mio/news/macros.twig' import news_preview %} {% set title = 'News' %} -{% set canonical_url = '/news.php' ~ (page_id > 1 ? '?p=' ~ page_id : '') %} +{% set canonical_url = '/news.php' ~ (posts_offset > 0 ? '?o=' ~ posts_offset : '') %} {% block news_content %}
    @@ -34,7 +34,7 @@ {% endfor %}
    - {# paginate(posts, '', 'news__') #} + {{ paginate(posts_count, posts_take, posts_offset, '/news.php', 'news__') }} diff --git a/views/mio/news/macros.twig b/views/mio/news/macros.twig index b98b783e..9b2ee251 100644 --- a/views/mio/news/macros.twig +++ b/views/mio/news/macros.twig @@ -1,12 +1,12 @@ {% macro news_preview(post) %}
    - + {{ post.post_title }}
    {{ post.post_text|first_paragraph|raw }} -

    View full post

    +

    View full post

    diff --git a/views/mio/news/post.twig b/views/mio/news/post.twig index a57967ef..d7cf9ced 100644 --- a/views/mio/news/post.twig +++ b/views/mio/news/post.twig @@ -1,7 +1,7 @@ {% extends '@mio/news/master.twig' %} {% set title = post.post_title ~ ' :: News' %} -{% set canonical_url = '/news.php?n=' ~ post.post_id %} +{% set canonical_url = '/news.php?p=' ~ post.post_id %} {% block news_content %}
    diff --git a/views/mio/settings/avatar.twig b/views/mio/settings/avatar.twig index 40e23fc2..c1cf69cc 100644 --- a/views/mio/settings/avatar.twig +++ b/views/mio/settings/avatar.twig @@ -15,10 +15,7 @@
    - +
    diff --git a/views/mio/settings/login-history.twig b/views/mio/settings/login-history.twig index 77492e61..1c85fb8a 100644 --- a/views/mio/settings/login-history.twig +++ b/views/mio/settings/login-history.twig @@ -49,6 +49,6 @@
    {% endfor %} - {# paginate(user_login_attempts, '?m=login-history', 'settings__') #} + {{ paginate(login_attempts_count, login_attempts_take, login_attempts_offset, '?m=login-history', 'settings__') }}
    {% endblock %} diff --git a/views/mio/settings/sessions.twig b/views/mio/settings/sessions.twig index 08135316..d637f0a0 100644 --- a/views/mio/settings/sessions.twig +++ b/views/mio/settings/sessions.twig @@ -60,6 +60,6 @@
    {% endfor %} - {# paginate(user_sessions, '?m=sessions', 'settings__') #} + {{ paginate(sessions_count, sessions_take, sessions_offset, '?m=sessions', 'settings__') }}
    {% endblock %}