functions yay
This commit is contained in:
parent
19bc8bdaa8
commit
cd9e72d3c0
18 changed files with 343 additions and 173 deletions
|
@ -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)
|
||||||
|
|
4
assets/less/mio/classes/forum/pagination.less
Normal file
4
assets/less/mio/classes/forum/pagination.less
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.forum__pagination {
|
||||||
|
box-shadow: 0 1px 2px #9475b2;
|
||||||
|
background-color: #fbeeff;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
|
32
assets/less/mio/classes/forum/topic.less
Normal file
32
assets/less/mio/classes/forum/topic.less
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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";
|
||||||
|
|
|
@ -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`),
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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`,
|
||||||
|
|
|
@ -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,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -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
51
src/Forum/forum.php
Normal 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
49
src/Forum/post.php
Normal 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
39
src/Forum/topic.php
Normal 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
35
src/Forum/validate.php
Normal 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 '';
|
||||||
|
}
|
|
@ -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 }}
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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/') }}
|
||||||
|
|
Loading…
Add table
Reference in a new issue