From 60e6accb2e78c0281db9066b624bcb1ed49c6bfd Mon Sep 17 00:00:00 2001 From: flashwave Date: Tue, 22 May 2018 01:05:25 +0200 Subject: [PATCH] SQL is black magic --- assets/less/mio/classes/container.less | 2 + assets/less/mio/classes/forum/post.less | 16 ++- assets/less/mio/classes/pagination.less | 2 +- public/forum/posting.php | 127 ++++++++++++++++++++++++ public/forum/topic.php | 67 ++++++++++--- views/mio/forum/macros.twig | 54 +++++----- views/mio/forum/topic.twig | 12 ++- views/mio/macros.twig | 9 +- 8 files changed, 243 insertions(+), 46 deletions(-) create mode 100644 public/forum/posting.php diff --git a/assets/less/mio/classes/container.less b/assets/less/mio/classes/container.less index 6a34cdba..60b20010 100644 --- a/assets/less/mio/classes/container.less +++ b/assets/less/mio/classes/container.less @@ -17,6 +17,8 @@ font-weight: 700; padding: 3px; font-family: @mio-font-heading; + word-wrap: break-word; + overflow: hidden; &--link:hover { text-decoration: underline; diff --git a/assets/less/mio/classes/forum/post.less b/assets/less/mio/classes/forum/post.less index 33bc39ea..b10be898 100644 --- a/assets/less/mio/classes/forum/post.less +++ b/assets/less/mio/classes/forum/post.less @@ -10,6 +10,8 @@ flex-direction: column; flex-grow: 1; flex-shrink: 1; + word-wrap: break-word; + overflow: hidden; &__text { margin: 2px; @@ -37,14 +39,26 @@ &__author { border-right: 1px solid #9475b2; - padding: 5px; text-align: center; flex-grow: 0; flex-shrink: 0; + min-width: 150px; + display: flex; + flex-direction: column; + align-items: center; + + &__joined { + flex-grow: 1; + flex-shrink: 1; + margin: 5px; + } &__link { + margin: 15px; color: inherit; text-decoration: none; + flex-grow: 0; + flex-shrink: 0; } &__avatar { diff --git a/assets/less/mio/classes/pagination.less b/assets/less/mio/classes/pagination.less index 1a7b356d..2ad47210 100644 --- a/assets/less/mio/classes/pagination.less +++ b/assets/less/mio/classes/pagination.less @@ -13,7 +13,7 @@ background: #9475b2; color: #306; height: 20px; - width: 20px; + min-width: 20px; &:not(:last-child) { margin-right: 1px; diff --git a/public/forum/posting.php b/public/forum/posting.php new file mode 100644 index 00000000..488ddbc0 --- /dev/null +++ b/public/forum/posting.php @@ -0,0 +1,127 @@ +hasActiveSession()) { + header('Location: /'); + return; +} + +$postRequest = $_SERVER['REQUEST_METHOD'] === 'POST'; + +$db = Database::connection(); + +// ORDER OF CHECKING +// - $postId non-zero: enter quote mode +// - $topicId non-zero: enter reply mode +// - $forumId non-zero: enter create mode +// - all zero: enter explode mode +if ($postRequest) { + $topicId = max(0, (int)($_POST['post']['topic'] ?? 0)); + $forumId = max(0, (int)($_POST['post']['forum'] ?? 0)); +} else { + $postId = max(0, (int)($_GET['p'] ?? 0)); + $topicId = max(0, (int)($_GET['t'] ?? 0)); + $forumId = max(0, (int)($_GET['f'] ?? 0)); +} + +if (!empty($postId)) { + $getPost = $db->prepare(' + SELECT `post_id`, `topic_id`, `user_id`, `post_text` + FROM `msz_forum_posts` + WHERE `post_id` = :post_id + '); + $getPost->bindValue('post_id', $postId); + $post = $getPost->execute() ? $getPost->fetch() : false; + + if (isset($post['topic_id'])) { // should automatic cross-quoting be a thing? if so, check if $topicId is < 1 first + $topicId = (int)$post['topic_id']; + } +} + +if (!empty($topicId)) { + $getTopic = $db->prepare(' + SELECT `topic_id`, `forum_id` + FROM `msz_forum_topics` + WHERE `topic_id` = :topic_id + '); + $getTopic->bindValue('topic_id', $topicId); + $topic = $getTopic->execute() ? $getTopic->fetch() : false; + + if (isset($topic['forum_id'])) { + $forumId = (int)$topic['forum_id']; + } +} + +if (!empty($forumId)) { + $getForum = $db->prepare(' + SELECT `forum_id` + FROM `msz_forum_categories` + WHERE `forum_id` = :forum_id + '); + $getForum->bindValue('forum_id', $forumId); + $forum = $getForum->execute() ? $getForum->fetch() : false; +} + +if ($postRequest) { + $createPost = $db->prepare(' + INSERT INTO `msz_forum_posts` + (`topic_id`, `forum_id`, `user_id`, `post_ip`, `post_text`) + VALUES + (:topic_id, :forum_id, :user_id, INET6_ATON(:post_ip), :post_text) + '); + + if (isset($topic)) { + $bumpTopic = $db->prepare(' + UPDATE `msz_forum_topics` + SET `topic_bumped` = NOW() + WHERE `topic_id` = :topic_id + '); + $bumpTopic->bindValue('topic_id', $topic['topic_id']); + $bumpTopic->execute(); + } else { + $createTopic = $db->prepare(' + INSERT INTO `msz_forum_topics` + (`forum_id`, `user_id`, `topic_title`) + VALUES + (:forum_id, :user_id, :topic_title) + '); + $createTopic->bindValue('forum_id', $forum['forum_id']); + $createTopic->bindValue('user_id', $app->getUserId()); + $createTopic->bindValue('topic_title', $_POST['post']['title']); + $createTopic->execute(); + $topicId = (int)$db->lastInsertId(); + } + + $createPost->bindValue('topic_id', $topicId); + $createPost->bindValue('forum_id', $forum['forum_id']); + $createPost->bindValue('user_id', $app->getUserId()); + $createPost->bindValue('post_ip', IPAddress::remote()->getString()); + $createPost->bindValue('post_text', $_POST['post']['text']); + $createPost->execute(); + $postId = $db->lastInsertId(); + + header("Location: /forum/topic.php?p={$postId}#p{$postId}"); + return; +} + +echo '
'; + +if (isset($topic)) { + echo ""; +} else { + echo ""; + echo '
'; +} + +echo '
+ +
'; diff --git a/public/forum/topic.php b/public/forum/topic.php index 368ae8d8..f5c65a54 100644 --- a/public/forum/topic.php +++ b/public/forum/topic.php @@ -13,23 +13,44 @@ $postsRange = max(min((int)($_GET['r'] ?? 10), 25), 5); // find topic id if ($topicId < 1 && $postId > 0) { - $getTopicId = $db->prepare(' - SELECT `topic_id` - FROM `msz_forum_posts` - WHERE `post_id` = :post_id + $getPostInfo = $db->prepare(' + SELECT + :post_id as `target_post_id`, + ( + SELECT `topic_id` + FROM `msz_forum_posts` + WHERE `post_id` = `target_post_id` + ) as `target_topic_id`, + ( + SELECT COUNT(`post_id`) + FROM `msz_forum_posts` + WHERE `topic_id` = `target_topic_id` + AND `post_id` < `target_post_id` + ORDER BY `post_id` + ) as `preceeding_post_count` '); - $getTopicId->bindValue('post_id', $postId); - $topicId = $getTopicId->execute() ? (int)$getTopicId->fetchColumn() : 0; + $getPostInfo->bindValue('post_id', $postId); + $postInfo = $getPostInfo->execute() ? $getPostInfo->fetch() : false; + + if ($postInfo) { + $topicId = (int)$postInfo['target_topic_id']; + $postsOffset = floor($postInfo['preceeding_post_count'] / $postsRange) * $postsRange; + } } $getTopic = $db->prepare(' SELECT t.`topic_id`, t.`forum_id`, t.`topic_title`, t.`topic_type`, t.`topic_status`, ( - SELECT MIN(p.`post_id`) - FROM `msz_forum_posts` as p - WHERE p.`topic_id` = t.`topic_id` - ) as `topic_first_post_id` + SELECT MIN(`post_id`) + FROM `msz_forum_posts` + WHERE `topic_id` = t.`topic_id` + ) as `topic_first_post_id`, + ( + SELECT COUNT(`post_id`) + FROM `msz_forum_posts` + WHERE `topic_id` = t.`topic_id` + ) as `topic_post_count` FROM `msz_forum_topics` as t WHERE t.`topic_id` = :topic_id AND t.`topic_deleted` IS NULL @@ -45,15 +66,33 @@ if (!$topic) { $getPosts = $db->prepare(' SELECT - `post_id`, `post_text`, `post_created`, - `topic_id` - FROM `msz_forum_posts` + p.`post_id`, p.`post_text`, p.`post_created`, + p.`topic_id`, + u.`user_id` as `poster_id`, + u.`username` as `poster_name`, + u.`created_at` as `poster_joined`, + COALESCE(r.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `poster_colour` + FROM `msz_forum_posts` as p + LEFT JOIN `msz_users` as u + ON u.`user_id` = p.`user_id` + LEFT JOIN `msz_roles` as r + ON r.`role_id` = u.`display_role` WHERE `topic_id` = :topic_id AND `post_deleted` IS NULL + ORDER BY `post_id` + LIMIT :offset, :take '); $getPosts->bindValue('topic_id', $topic['topic_id']); +$getPosts->bindValue('offset', $postsOffset); +$getPosts->bindValue('take', $postsRange); $posts = $getPosts->execute() ? $getPosts->fetchAll() : []; +if (!$posts) { + http_response_code(404); + echo $templating->render('errors.404'); + return; +} + $lastParent = $topic['forum_id']; $breadcrumbs = []; $getBreadcrumb = $db->prepare(' @@ -81,4 +120,6 @@ echo $templating->render('forum.topic', [ 'topic_breadcrumbs' => $breadcrumbs, 'topic_info' => $topic, 'topic_posts' => $posts, + 'topic_offset' => $postsOffset, + 'topic_range' => $postsRange, ]); diff --git a/views/mio/forum/macros.twig b/views/mio/forum/macros.twig index 1d4ab2b4..f79fbe71 100644 --- a/views/mio/forum/macros.twig +++ b/views/mio/forum/macros.twig @@ -19,7 +19,7 @@ {% macro forum_category_buttons(forum) %}
- New Topic + New Topic
{% endmacro %} @@ -104,6 +104,12 @@ {% endmacro %} +{% macro forum_topic_buttons(topic) %} +
+ Reply +
+{% endmacro %} + {% macro forum_topic_listing(topics) %} {% from _self import forum_topic_entry %} @@ -202,35 +208,35 @@ {% macro forum_post_listing(posts, opening_post_id) %} {% from _self import forum_post_entry %} - {% if posts|length > 0 %} - {% for post in posts %} - {{ forum_post_entry(post, post.post_id == opening_post_id) }} - {% endfor %} - {% else %} -
-
Information
-
- This topic has no associated posts. -
-
- {% endif %} + {% for post in posts %} + {{ forum_post_entry(post, post.post_id == opening_post_id) }} + {% endfor %} {% endmacro %} -{% macro forum_post_entry(post, is_opening_post) %} - {% set is_opening_post = is_opening_post|default(false) %} +{% macro forum_post_entry(post, is_original_post, is_original_poster) %} + {% set is_original_post = is_original_post|default(false) %} + {% set is_original_poster = is_original_poster|default(false) %}
+ {{ ftbuttons }} + {{ ftpagination }} {{ forum_post_listing(topic_posts, topic_info.topic_first_post_id) }} + {{ ftpagination }} + {{ ftbuttons }} {{ navigation(mio_navigation, '/forum/') }} {% endblock %} diff --git a/views/mio/macros.twig b/views/mio/macros.twig index 99191048..3ff043ad 100644 --- a/views/mio/macros.twig +++ b/views/mio/macros.twig @@ -26,6 +26,7 @@ {% from _self import pagination_class %} {% set classPrefix = classPrefix|default('') %} {% set separator = '%3F' in baseUrl|default('')|url_encode ? '&' : '?' %} + {% set originalUrl = baseUrl %} {% set baseUrl = baseUrl ~ separator %} {% set pageCount = (itemCount / itemRange)|round(0, 'ceil') %} {% set currentPage = currentOffset // itemRange %} @@ -46,15 +47,13 @@ {% else %} - {% set firstUrl = baseUrl|slice(0, (baseUrl|length) - (separator|length)) %} -
  • - + «
  • -
  • @@ -68,7 +67,7 @@ {% for i in paginationStart..paginationStop %} {% if i >= 0 and i < pageCount %}
  • - + {{ i + 1 }}