functions yay

This commit is contained in:
flash 2018-05-23 03:41:57 +02:00
parent 19bc8bdaa8
commit cd9e72d3c0
18 changed files with 343 additions and 173 deletions

View file

@ -6,7 +6,7 @@
## Requirements ## Requirements
- PHP 7.2 - PHP 7.2
- MySQL - MySQL 8.0
- Redis - Redis
- [Composer](https://getcomposer.org/) - [Composer](https://getcomposer.org/)
- [node.js](https://nodejs.org/) (for the typescript and less compilers) - [node.js](https://nodejs.org/) (for the typescript and less compilers)

View file

@ -0,0 +1,4 @@
.forum__pagination {
box-shadow: 0 1px 2px #9475b2;
background-color: #fbeeff;
}

View file

@ -6,6 +6,14 @@
flex-direction: column; flex-direction: column;
} }
&__errors {
font-weight: 700;
color: #a00;
padding: 0 2px 1px;
margin-bottom: 2px;
border-bottom: 1px solid #9475b2;
}
&__title { &__title {
margin-bottom: 2px; margin-bottom: 2px;

View file

@ -0,0 +1,32 @@
.forum__topic {
&__locked {
border: 1px solid #9475b2;
display: flex;
align-items: center;
min-height: 40px;
margin-bottom: 2px;
box-shadow: 0 1px 2px #9475b2;
&__icon {
height: 40px;
width: 40px;
background-size: 35px;
background-image: url('https://static.flash.moe/images/topic-icons/topic-locked-read.png');
background-position: center;
background-repeat: no-repeat;
background-color: #9475b2;
flex-grow: 0;
flex-shrink: 0;
}
&__text {
margin: 0 10px;
flex-grow: 1;
flex-shrink: 1;
}
&__time {
font-weight: 700;
}
}
}

View file

@ -73,6 +73,8 @@ body {
// Forums // Forums
@import "classes/forum/actions"; @import "classes/forum/actions";
@import "classes/forum/listing"; @import "classes/forum/listing";
@import "classes/forum/pagination";
@import "classes/forum/post"; @import "classes/forum/post";
@import "classes/forum/posting"; @import "classes/forum/posting";
@import "classes/forum/topic";
@import "classes/forum/topics"; @import "classes/forum/topics";

View file

@ -28,13 +28,13 @@ function migrate_up(PDO $conn): void
`topic_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `topic_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`forum_id` INT(10) UNSIGNED NOT NULL, `forum_id` INT(10) UNSIGNED NOT NULL,
`user_id` INT(10) UNSIGNED NULL DEFAULT NULL, `user_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`topic_type` TINYINT(4) NOT NULL DEFAULT '0',
`topic_title` VARCHAR(255) NOT NULL, `topic_title` VARCHAR(255) NOT NULL,
`topic_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `topic_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`topic_bumped` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `topic_bumped` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`topic_deleted` TIMESTAMP NULL DEFAULT NULL, `topic_deleted` TIMESTAMP NULL DEFAULT NULL,
`topic_locked` TIMESTAMP NULL DEFAULT NULL,
`topic_view_count` INT(10) NOT NULL DEFAULT '0', `topic_view_count` INT(10) NOT NULL DEFAULT '0',
`topic_type` TINYINT(4) NOT NULL DEFAULT '0',
`topic_status` TINYINT(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`topic_id`), PRIMARY KEY (`topic_id`),
INDEX `topics_forum_id_foreign` (`forum_id`), INDEX `topics_forum_id_foreign` (`forum_id`),
INDEX `topics_user_id_foreign` (`user_id`), INDEX `topics_user_id_foreign` (`user_id`),

View file

@ -4,6 +4,10 @@ namespace Misuzu;
require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/src/colour.php'; require_once __DIR__ . '/src/colour.php';
require_once __DIR__ . '/src/zalgo.php'; require_once __DIR__ . '/src/zalgo.php';
require_once __DIR__ . '/src/Forum/forum.php';
require_once __DIR__ . '/src/Forum/post.php';
require_once __DIR__ . '/src/Forum/topic.php';
require_once __DIR__ . '/src/Forum/validate.php';
require_once __DIR__ . '/src/Users/login_attempt.php'; require_once __DIR__ . '/src/Users/login_attempt.php';
require_once __DIR__ . '/src/Users/validation.php'; require_once __DIR__ . '/src/Users/validation.php';

View file

@ -3,7 +3,7 @@ use Misuzu\Database;
require_once __DIR__ . '/../../misuzu.php'; require_once __DIR__ . '/../../misuzu.php';
$forumId = (int)($_GET['f'] ?? 0); $forumId = max((int)($_GET['f'] ?? 0), 0);
$topicsOffset = max((int)($_GET['o'] ?? 0), 0); $topicsOffset = max((int)($_GET['o'] ?? 0), 0);
$topicsRange = max(min((int)($_GET['r'] ?? 20), 50), 10); $topicsRange = max(min((int)($_GET['r'] ?? 20), 50), 10);
@ -15,7 +15,6 @@ if ($forumId === 0) {
$db = Database::connection(); $db = Database::connection();
$templating = $app->getTemplating(); $templating = $app->getTemplating();
if ($forumId > 0) {
$getForum = $db->prepare(' $getForum = $db->prepare('
SELECT SELECT
`forum_id`, `forum_name`, `forum_type`, `forum_link`, `forum_link_clicks`, `forum_parent`, `forum_id`, `forum_name`, `forum_type`, `forum_link`, `forum_link_clicks`, `forum_parent`,
@ -29,25 +28,15 @@ if ($forumId > 0) {
'); ');
$getForum->bindValue('forum_id', $forumId); $getForum->bindValue('forum_id', $forumId);
$forum = $getForum->execute() ? $getForum->fetch() : []; $forum = $getForum->execute() ? $getForum->fetch() : [];
}
if (empty($forum) || ($forum['forum_type'] == 2 && empty($forum['forum_link']))) { if (empty($forum) || ($forum['forum_type'] == MSZ_FORUM_TYPE_LINK && empty($forum['forum_link']))) {
http_response_code(404); http_response_code(404);
echo $templating->render('errors.404'); echo $templating->render('errors.404');
return; return;
} }
if ($forum['forum_type'] == 2) { if ($forum['forum_type'] == MSZ_FORUM_TYPE_LINK) {
if ($forum['forum_link_clicks'] !== null) { forum_increment_clicks($forum['forum_id']);
$incrementLinkClicks = $db->prepare('
UPDATE `msz_forum_categories`
SET `forum_link_clicks` = `forum_link_clicks` + 1
WHERE `forum_id` = :forum_id
');
$incrementLinkClicks->bindValue('forum_id', $forum['forum_id']);
$incrementLinkClicks->execute();
}
header('Location: ' . $forum['forum_link']); header('Location: ' . $forum['forum_link']);
return; return;
} }
@ -56,10 +45,10 @@ if ($forum['forum_type'] == 2) {
$topics = []; $topics = [];
// no need to fetch topics for categories (or links but we're already done with those at this point) // no need to fetch topics for categories (or links but we're already done with those at this point)
if ($forum['forum_type'] == 0) { if ($forum['forum_type'] == MSZ_FORUM_TYPE_DISCUSSION) {
$getTopics = $db->prepare(' $getTopics = $db->prepare('
SELECT SELECT
t.`topic_id`, t.`topic_title`, t.`topic_view_count`, t.`topic_status`, t.`topic_type`, t.`topic_created`, t.`topic_id`, t.`topic_title`, t.`topic_view_count`, t.`topic_locked`, t.`topic_type`, t.`topic_created`,
au.`user_id` as `author_id`, au.`username` as `author_name`, au.`user_id` as `author_id`, au.`username` as `author_name`,
COALESCE(ar.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `author_colour`, COALESCE(ar.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `author_colour`,
lp.`post_id` as `response_id`, lp.`post_id` as `response_id`,
@ -102,7 +91,7 @@ if ($forum['forum_type'] == 0) {
$getSubforums = $db->prepare(' $getSubforums = $db->prepare('
SELECT SELECT
f.`forum_id`, f.`forum_name`, f.`forum_description`, f.`forum_type`, f.`forum_link`, f.`forum_id`, f.`forum_name`, f.`forum_description`, f.`forum_type`, f.`forum_link`, f.`forum_archived`,
t.`topic_id` as `recent_topic_id`, p.`post_id` as `recent_post_id`, t.`topic_id` as `recent_topic_id`, p.`post_id` as `recent_post_id`,
t.`topic_title` as `recent_topic_title`, t.`topic_title` as `recent_topic_title`,
p.`post_created` as `recent_post_created`, p.`post_created` as `recent_post_created`,
@ -162,32 +151,9 @@ if (count($forum['forum_subforums']) > 0) {
} }
} }
$lastParent = $forum['forum_parent'];
$breadcrumbs = [$forum['forum_name'] => '/forum/forum.php?f=' . $forum['forum_id']];
$getBreadcrumb = $db->prepare('
SELECT `forum_id`, `forum_name`, `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_id` = :forum_id
');
while ($lastParent > 0) {
$getBreadcrumb->bindValue('forum_id', $lastParent);
$breadcrumb = $getBreadcrumb->execute() ? $getBreadcrumb->fetch() : [];
if (!$breadcrumb) {
break;
}
$breadcrumbs[$breadcrumb['forum_name']] = '/forum/forum.php?f=' . $breadcrumb['forum_id'];
$lastParent = $breadcrumb['forum_parent'];
}
$breadcrumbs['Forums'] = '/forum/';
$breadcrumbs = array_reverse($breadcrumbs);
echo $app->getTemplating()->render('forum.forum', [ echo $app->getTemplating()->render('forum.forum', [
'forum_breadcrumbs' => forum_get_breadcrumbs($forum['forum_id']),
'forum_info' => $forum, 'forum_info' => $forum,
'forum_breadcrumbs' => $breadcrumbs,
'forum_topics' => $topics, 'forum_topics' => $topics,
'forum_offset' => $topicsOffset, 'forum_offset' => $topicsOffset,
'forum_range' => $topicsRange, 'forum_range' => $topicsRange,

View file

@ -31,7 +31,8 @@ $categories = array_merge([
$getSubCategories = $db->prepare(' $getSubCategories = $db->prepare('
SELECT SELECT
f.`forum_id`, f.`forum_name`, f.`forum_description`, f.`forum_type`, f.`forum_link`, f.`forum_link_clicks`, f.`forum_id`, f.`forum_name`, f.`forum_description`, f.`forum_type`,
f.`forum_link`, f.`forum_link_clicks`, f.`forum_archived`,
t.`topic_id` as `recent_topic_id`, p.`post_id` as `recent_post_id`, t.`topic_id` as `recent_topic_id`, p.`post_id` as `recent_post_id`,
t.`topic_title` as `recent_topic_title`, t.`topic_title` as `recent_topic_title`,
p.`post_created` as `recent_post_created`, p.`post_created` as `recent_post_created`,

View file

@ -46,7 +46,7 @@ if (!empty($postId)) {
if (!empty($topicId)) { if (!empty($topicId)) {
$getTopic = $db->prepare(' $getTopic = $db->prepare('
SELECT `topic_id`, `forum_id`, `topic_title` SELECT `topic_id`, `forum_id`, `topic_title`, `topic_locked`
FROM `msz_forum_topics` FROM `msz_forum_topics`
WHERE `topic_id` = :topic_id WHERE `topic_id` = :topic_id
'); ');
@ -60,7 +60,7 @@ if (!empty($topicId)) {
if (!empty($forumId)) { if (!empty($forumId)) {
$getForum = $db->prepare(' $getForum = $db->prepare('
SELECT `forum_id`, `forum_name`, `forum_type` SELECT `forum_id`, `forum_name`, `forum_type`, `forum_archived`
FROM `msz_forum_categories` FROM `msz_forum_categories`
WHERE `forum_id` = :forum_id WHERE `forum_id` = :forum_id
'); ');
@ -74,82 +74,67 @@ if (empty($forum)) {
return; return;
} }
if ($forum['forum_type'] != 0) { if ($forum['forum_type'] != MSZ_FORUM_TYPE_DISCUSSION) {
http_response_code(400); http_response_code(400);
echo $templating->render('errors.400'); echo $templating->render('errors.400');
return; return;
} }
if ($postRequest) { if ($forum['forum_archived'] || !empty($topic['topic_locked'])) {
$createPost = $db->prepare(' http_response_code(403);
INSERT INTO `msz_forum_posts` echo $templating->render('errors.403');
(`topic_id`, `forum_id`, `user_id`, `post_ip`, `post_text`) return;
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); if ($postRequest) {
$createPost->bindValue('forum_id', $forum['forum_id']); $topicTitle = $_POST['post']['title'] ?? '';
$createPost->bindValue('user_id', $app->getUserId()); $topicTitleValidate = forum_validate_title($topicTitle);
$createPost->bindValue('post_ip', IPAddress::remote()->getString()); $postText = $_POST['post']['text'] ?? '';
$createPost->bindValue('post_text', $_POST['post']['text']); $postTextValidate = forum_validate_post($postText);
$createPost->execute();
$postId = $db->lastInsertId(); switch ($postTextValidate) {
case 'too-short':
echo 'Post content was too short.';
return;
case 'too-long':
echo 'Post content was too long.';
return;
}
if (isset($topic)) {
forum_topic_bump($topic['topic_id']);
} else {
switch ($topicTitleValidate) {
case 'too-short':
echo 'Topic title was too short.';
return;
case 'too-long':
echo 'Topic title was too long.';
return;
}
$topicId = forum_topic_create($forum['forum_id'], $app->getUserId(), $topicTitle);
}
$postId = forum_post_create(
$topicId,
$forum['forum_id'],
$app->getUserId(),
IPAddress::remote()->getString(),
$postText
);
header("Location: /forum/topic.php?p={$postId}#p{$postId}"); header("Location: /forum/topic.php?p={$postId}#p{$postId}");
return; return;
} }
$lastParent = $forumId;
$breadcrumbs = [];
$getBreadcrumb = $db->prepare('
SELECT `forum_id`, `forum_name`, `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_id` = :forum_id
');
while ($lastParent > 0) {
$getBreadcrumb->bindValue('forum_id', $lastParent);
$breadcrumb = $getBreadcrumb->execute() ? $getBreadcrumb->fetch() : [];
if (!$breadcrumb) {
break;
}
$breadcrumbs[$breadcrumb['forum_name']] = '/forum/forum.php?f=' . $breadcrumb['forum_id'];
$lastParent = $breadcrumb['forum_parent'];
}
$breadcrumbs['Forums'] = '/forum/';
$breadcrumbs = array_reverse($breadcrumbs);
if (!empty($topic)) { if (!empty($topic)) {
$templating->var('posting_topic', $topic); $templating->var('posting_topic', $topic);
} }
echo $templating->render('forum.posting', [ echo $templating->render('forum.posting', [
'posting_breadcrumbs' => $breadcrumbs, 'posting_breadcrumbs' => forum_get_breadcrumbs($forumId),
'posting_forum' => $forum, 'posting_forum' => $forum,
]); ]);

View file

@ -13,24 +13,7 @@ $postsRange = max(min((int)($_GET['r'] ?? 10), 25), 5);
// find topic id // find topic id
if ($topicId < 1 && $postId > 0) { if ($topicId < 1 && $postId > 0) {
$getPostInfo = $db->prepare(' $postInfo = forum_post_find($postId);
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`
');
$getPostInfo->bindValue('post_id', $postId);
$postInfo = $getPostInfo->execute() ? $getPostInfo->fetch() : false;
if ($postInfo) { if ($postInfo) {
$topicId = (int)$postInfo['target_topic_id']; $topicId = (int)$postInfo['target_topic_id'];
@ -40,7 +23,8 @@ if ($topicId < 1 && $postId > 0) {
$getTopic = $db->prepare(' $getTopic = $db->prepare('
SELECT SELECT
t.`topic_id`, t.`forum_id`, t.`topic_title`, t.`topic_type`, t.`topic_status`, t.`topic_id`, t.`forum_id`, t.`topic_title`, t.`topic_type`, t.`topic_locked`,
f.`forum_archived` as `topic_archived`,
( (
SELECT MIN(`post_id`) SELECT MIN(`post_id`)
FROM `msz_forum_posts` FROM `msz_forum_posts`
@ -52,6 +36,8 @@ $getTopic = $db->prepare('
WHERE `topic_id` = t.`topic_id` WHERE `topic_id` = t.`topic_id`
) as `topic_post_count` ) as `topic_post_count`
FROM `msz_forum_topics` as t FROM `msz_forum_topics` as t
LEFT JOIN `msz_forum_categories` as f
ON f.`forum_id` = t.`forum_id`
WHERE t.`topic_id` = :topic_id WHERE t.`topic_id` = :topic_id
AND t.`topic_deleted` IS NULL AND t.`topic_deleted` IS NULL
'); ');
@ -93,31 +79,8 @@ if (!$posts) {
return; return;
} }
$lastParent = $topic['forum_id'];
$breadcrumbs = [];
$getBreadcrumb = $db->prepare('
SELECT `forum_id`, `forum_name`, `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_id` = :forum_id
');
while ($lastParent > 0) {
$getBreadcrumb->bindValue('forum_id', $lastParent);
$breadcrumb = $getBreadcrumb->execute() ? $getBreadcrumb->fetch() : [];
if (!$breadcrumb) {
break;
}
$breadcrumbs[$breadcrumb['forum_name']] = '/forum/forum.php?f=' . $breadcrumb['forum_id'];
$lastParent = $breadcrumb['forum_parent'];
}
$breadcrumbs['Forums'] = '/forum/';
$breadcrumbs = array_reverse($breadcrumbs);
echo $templating->render('forum.topic', [ echo $templating->render('forum.topic', [
'topic_breadcrumbs' => $breadcrumbs, 'topic_breadcrumbs' => forum_get_breadcrumbs($topic['forum_id']),
'topic_info' => $topic, 'topic_info' => $topic,
'topic_posts' => $posts, 'topic_posts' => $posts,
'topic_offset' => $postsOffset, 'topic_offset' => $postsOffset,

51
src/Forum/forum.php Normal file
View file

@ -0,0 +1,51 @@
<?php
use Misuzu\Database;
define('MSZ_FORUM_TYPE_DISCUSSION', 0);
define('MSZ_FORUM_TYPE_CATEGORY', 1);
define('MSZ_FORUM_TYPE_LINK', 2);
define('MSZ_FORUM_TYPES', [
MSZ_FORUM_TYPE_DISCUSSION,
MSZ_FORUM_TYPE_CATEGORY,
MSZ_FORUM_TYPE_LINK,
]);
function forum_get_breadcrumbs(
int $forumId,
string $linkFormat = '/forum/forum.php?f=%d',
array $indexLink = ['Forums' => '/forum/']
): array {
$breadcrumbs = [];
$getBreadcrumb = Database::connection()->prepare('
SELECT `forum_id`, `forum_name`, `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_id` = :forum_id
');
while ($forumId > 0) {
$getBreadcrumb->bindValue('forum_id', $forumId);
$breadcrumb = $getBreadcrumb->execute() ? $getBreadcrumb->fetch() : [];
if (!$breadcrumb) {
break;
}
$breadcrumbs[$breadcrumb['forum_name']] = sprintf($linkFormat, $breadcrumb['forum_id']);
$forumId = $breadcrumb['forum_parent'];
}
return array_reverse($breadcrumbs + $indexLink);
}
function forum_increment_clicks(int $forumId): void
{
$incrementLinkClicks = Database::connection()->prepare('
UPDATE `msz_forum_categories`
SET `forum_link_clicks` = `forum_link_clicks` + 1
WHERE `forum_id` = :forum_id
AND `forum_type` = 2
AND `forum_link_clicks` IS NOT NULL
');
$incrementLinkClicks->bindValue('forum_id', $forumId);
$incrementLinkClicks->execute();
}

49
src/Forum/post.php Normal file
View file

@ -0,0 +1,49 @@
<?php
use Misuzu\Database;
function forum_post_create(
int $topicId,
int $forumId,
int $userId,
string $ipAddress,
string $text
): int {
$dbc = Database::connection();
$createPost = $dbc->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)
');
$createPost->bindValue('topic_id', $topicId);
$createPost->bindValue('forum_id', $forumId);
$createPost->bindValue('user_id', $userId);
$createPost->bindValue('post_ip', $ipAddress);
$createPost->bindValue('post_text', $text);
return $createPost->execute() ? $dbc->lastInsertId() : 0;
}
function forum_post_find(int $postId): array
{
$getPostInfo = Database::connection()->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`
');
$getPostInfo->bindValue('post_id', $postId);
return $getPostInfo->execute() ? $getPostInfo->fetch() : false;
}

39
src/Forum/topic.php Normal file
View file

@ -0,0 +1,39 @@
<?php
use Misuzu\Database;
define('MSZ_TOPIC_TYPE_DISCUSSION', 0);
define('MSZ_TOPIC_TYPE_STICKY', 1);
define('MSZ_TOPIC_TYPE_ANNOUNCEMENT', 2);
define('MSZ_TOPIC_TYPES', [
MSZ_TOPIC_TYPE_DISCUSSION,
MSZ_TOPIC_TYPE_STICKY,
MSZ_TOPIC_TYPE_ANNOUNCEMENT,
]);
function forum_topic_create(int $forumId, int $userId, string $title): int
{
$dbc = Database::connection();
$createTopic = $dbc->prepare('
INSERT INTO `msz_forum_topics`
(`forum_id`, `user_id`, `topic_title`)
VALUES
(:forum_id, :user_id, :topic_title)
');
$createTopic->bindValue('forum_id', $forumId);
$createTopic->bindValue('user_id', $userId);
$createTopic->bindValue('topic_title', $title);
return $createTopic->execute() ? (int)$dbc->lastInsertId() : 0;
}
function forum_topic_bump(int $topicId): bool
{
$bumpTopic = Database::connection()->prepare('
UPDATE `msz_forum_topics`
SET `topic_bumped` = NOW()
WHERE `topic_id` = :topic_id
');
$bumpTopic->bindValue('topic_id', $topicId);
return $bumpTopic->execute();
}

35
src/Forum/validate.php Normal file
View file

@ -0,0 +1,35 @@
<?php
define('MSZ_TOPIC_TITLE_LENGTH_MIN', 5);
define('MSZ_TOPIC_TITLE_LENGTH_MAX', 100);
define('MSZ_POST_TEXT_LENGTH_MIN', 5);
define('MSZ_POST_TEXT_LENGTH_MAX', 60000);
function forum_validate_title(string $title): string
{
$length = strlen($title);
if ($length < MSZ_TOPIC_TITLE_LENGTH_MIN) {
return 'too-short';
}
if ($length > MSZ_TOPIC_TITLE_LENGTH_MAX) {
return 'too-long';
}
return '';
}
function forum_validate_post(string $text): string
{
$length = strlen($text);
if ($length < MSZ_POST_TEXT_LENGTH_MIN) {
return 'too-short';
}
if ($length > MSZ_POST_TEXT_LENGTH_MAX) {
return 'too-long';
}
return '';
}

View file

@ -14,7 +14,7 @@
{% if forum_info.forum_type == 0 %} {% if forum_info.forum_type == 0 %}
{% set fcbuttons = app.hasActiveSession ? forum_category_buttons(forum_info) : '' %} {% set fcbuttons = app.hasActiveSession ? forum_category_buttons(forum_info) : '' %}
{% set fcpagination = pagination(forum_info.forum_topic_count, forum_range, forum_offset, canonical_url) %} {% set fcpagination = pagination(forum_info.forum_topic_count, forum_range, forum_offset, canonical_url, 'forum__') %}
{{ fcbuttons }} {{ fcbuttons }}
{{ fcpagination }} {{ fcpagination }}

View file

@ -118,10 +118,27 @@
{% macro forum_topic_buttons(topic) %} {% macro forum_topic_buttons(topic) %}
<div class="forum__actions forum__actions__content"> <div class="forum__actions forum__actions__content">
<a href="#reply" class="input__button forum__actions__button" onclick="openContainer('reply')">Reply</a> <a href="#reply"
class="input__button forum__actions__button"
onclick="openContainer('reply')">Reply</a>
</div> </div>
{% endmacro %} {% endmacro %}
{% macro forum_topic_locked(locked, archived) %}
{% if locked is not null or archived %}
<div class="forum__topic__locked">
<div class="forum__topic__locked__icon"></div>
<div class="forum__topic__locked__text">
{% if archived %}
This topic has been <span class="forum__topic__locked__time">archived</span>.
{% else %}
This topic was locked on <time class="forum__topic__locked__time">{{ locked }}</time>.
{% endif %}
</div>
</div>
{% endif %}
{% endmacro %}
{% macro forum_topic_listing(topics) %} {% macro forum_topic_listing(topics) %}
{% from _self import forum_topic_entry %} {% from _self import forum_topic_entry %}
@ -155,7 +172,7 @@
{% elseif topic.topic_type == 1 %} {% elseif topic.topic_type == 1 %}
{% set topic_type = 'pinned' %} {% set topic_type = 'pinned' %}
{% endif %} {% endif %}
{% elseif topic.topic_status is defined and topic.topic_status == 1 %} {% elseif topic.topic_locked is defined and topic.topic_locked is not null %}
{% set topic_type = 'locked' %} {% set topic_type = 'locked' %}
{% else %} {% else %}
{% set topic_type = 'default' %} {% set topic_type = 'default' %}
@ -281,6 +298,10 @@
<div class="container__content forum__posting__content"> <div class="container__content forum__posting__content">
<input type="hidden" name="post[{{ is_reply ? 'topic' : 'forum' }}]" value="{{ target_id }}"> <input type="hidden" name="post[{{ is_reply ? 'topic' : 'forum' }}]" value="{{ target_id }}">
{#<div class="forum__posting__errors">
<p class="forum__posting__error">Error: Your post contained too much text, shorten it a bit or split it out in two posts.</p>
</div>#}
{% if not is_reply %} {% if not is_reply %}
<div class="forum__posting__title"> <div class="forum__posting__title">
<input class="input__text forum__posting__title__input" type="text" name="post[title]" placeholder="Topic title"> <input class="input__text forum__posting__title__input" type="text" name="post[title]" placeholder="Topic title">

View file

@ -1,13 +1,21 @@
{% extends '@mio/forum/master.twig' %} {% extends '@mio/forum/master.twig' %}
{% from '@mio/macros.twig' import navigation, pagination %} {% from '@mio/macros.twig' import navigation, pagination %}
{% from '@mio/forum/macros.twig' import forum_post_listing, forum_topic_buttons, forum_posting_form %} {%
from '@mio/forum/macros.twig'
import
forum_post_listing,
forum_topic_buttons,
forum_topic_locked,
forum_posting_form
%}
{% set title = topic_info.topic_title %} {% set title = topic_info.topic_title %}
{% set base_url = '/forum/topic.php?t=' ~ topic_info.topic_id %} {% set base_url = '/forum/topic.php?t=' ~ topic_info.topic_id %}
{% set canonical_url = base_url %} {% set canonical_url = base_url %}
{% set ftbuttons = app.hasActiveSession ? forum_topic_buttons(topic_info) : '' %} {% set can_reply = app.hasActiveSession and topic_info.topic_locked is null and not topic_info.topic_archived %}
{% set ftpagination = pagination(topic_info.topic_post_count, topic_range, topic_offset, base_url) %} {% set ftbuttons = can_reply ? forum_topic_buttons(topic_info) : '' %}
{% set ftpagination = pagination(topic_info.topic_post_count, topic_range, topic_offset, base_url, 'forum__') %}
{% block content %} {% block content %}
{{ navigation(topic_breadcrumbs, topic_breadcrumbs|last, true, null, 'left') }} {{ navigation(topic_breadcrumbs, topic_breadcrumbs|last, true, null, 'left') }}
@ -18,20 +26,22 @@
</div> </div>
</div> </div>
{{ forum_topic_locked(topic_info.topic_locked, topic_info.topic_archived) }}
{{ ftbuttons }} {{ ftbuttons }}
{{ ftpagination }} {{ ftpagination }}
{{ forum_post_listing(topic_posts, topic_info.topic_first_post_id) }} {{ forum_post_listing(topic_posts, topic_info.topic_first_post_id) }}
{{ ftpagination }} {{ ftpagination }}
{% if app.hasActiveSession %} {% if can_reply %}
{{ forum_posting_form('Reply', topic_info.topic_id, true, 'reply', true) }} {{ forum_posting_form('Reply', topic_info.topic_id, true, 'reply', true) }}
<script> <!--script>
window.addEventListener('load', () => { window.addEventListener('load', () => {
closeContainer('reply'); closeContainer('reply');
document.getElementById('reply').children[0].addEventListener('mouseover', () => openContainer('reply')); document.getElementById('reply').children[0].addEventListener('mouseover', () => openContainer('reply'));
}); });
</script> </script-->
{% endif %} {% endif %}
{{ navigation(mio_navigation, '/forum/') }} {{ navigation(mio_navigation, '/forum/') }}