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
|
||||
- PHP 7.2
|
||||
- MySQL
|
||||
- MySQL 8.0
|
||||
- Redis
|
||||
- [Composer](https://getcomposer.org/)
|
||||
- [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;
|
||||
}
|
||||
|
||||
&__errors {
|
||||
font-weight: 700;
|
||||
color: #a00;
|
||||
padding: 0 2px 1px;
|
||||
margin-bottom: 2px;
|
||||
border-bottom: 1px solid #9475b2;
|
||||
}
|
||||
|
||||
&__title {
|
||||
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
|
||||
@import "classes/forum/actions";
|
||||
@import "classes/forum/listing";
|
||||
@import "classes/forum/pagination";
|
||||
@import "classes/forum/post";
|
||||
@import "classes/forum/posting";
|
||||
@import "classes/forum/topic";
|
||||
@import "classes/forum/topics";
|
||||
|
|
|
@ -28,13 +28,13 @@ function migrate_up(PDO $conn): void
|
|||
`topic_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`forum_id` INT(10) UNSIGNED NOT NULL,
|
||||
`user_id` INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
`topic_type` TINYINT(4) NOT NULL DEFAULT '0',
|
||||
`topic_title` VARCHAR(255) NOT NULL,
|
||||
`topic_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`topic_bumped` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`topic_deleted` TIMESTAMP NULL DEFAULT NULL,
|
||||
`topic_locked` TIMESTAMP NULL DEFAULT NULL,
|
||||
`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`),
|
||||
INDEX `topics_forum_id_foreign` (`forum_id`),
|
||||
INDEX `topics_user_id_foreign` (`user_id`),
|
||||
|
|
|
@ -4,6 +4,10 @@ namespace Misuzu;
|
|||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
require_once __DIR__ . '/src/colour.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/validation.php';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use Misuzu\Database;
|
|||
|
||||
require_once __DIR__ . '/../../misuzu.php';
|
||||
|
||||
$forumId = (int)($_GET['f'] ?? 0);
|
||||
$forumId = max((int)($_GET['f'] ?? 0), 0);
|
||||
$topicsOffset = max((int)($_GET['o'] ?? 0), 0);
|
||||
$topicsRange = max(min((int)($_GET['r'] ?? 20), 50), 10);
|
||||
|
||||
|
@ -15,39 +15,28 @@ if ($forumId === 0) {
|
|||
$db = Database::connection();
|
||||
$templating = $app->getTemplating();
|
||||
|
||||
if ($forumId > 0) {
|
||||
$getForum = $db->prepare('
|
||||
SELECT
|
||||
`forum_id`, `forum_name`, `forum_type`, `forum_link`, `forum_link_clicks`, `forum_parent`,
|
||||
(
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `forum_id` = f.`forum_id`
|
||||
) as `forum_topic_count`
|
||||
FROM `msz_forum_categories` as f
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
$getForum->bindValue('forum_id', $forumId);
|
||||
$forum = $getForum->execute() ? $getForum->fetch() : [];
|
||||
}
|
||||
$getForum = $db->prepare('
|
||||
SELECT
|
||||
`forum_id`, `forum_name`, `forum_type`, `forum_link`, `forum_link_clicks`, `forum_parent`,
|
||||
(
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `forum_id` = f.`forum_id`
|
||||
) as `forum_topic_count`
|
||||
FROM `msz_forum_categories` as f
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
$getForum->bindValue('forum_id', $forumId);
|
||||
$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);
|
||||
echo $templating->render('errors.404');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($forum['forum_type'] == 2) {
|
||||
if ($forum['forum_link_clicks'] !== null) {
|
||||
$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();
|
||||
}
|
||||
|
||||
if ($forum['forum_type'] == MSZ_FORUM_TYPE_LINK) {
|
||||
forum_increment_clicks($forum['forum_id']);
|
||||
header('Location: ' . $forum['forum_link']);
|
||||
return;
|
||||
}
|
||||
|
@ -56,10 +45,10 @@ if ($forum['forum_type'] == 2) {
|
|||
$topics = [];
|
||||
|
||||
// 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('
|
||||
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`,
|
||||
COALESCE(ar.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `author_colour`,
|
||||
lp.`post_id` as `response_id`,
|
||||
|
@ -102,7 +91,7 @@ if ($forum['forum_type'] == 0) {
|
|||
|
||||
$getSubforums = $db->prepare('
|
||||
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_title` as `recent_topic_title`,
|
||||
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', [
|
||||
'forum_breadcrumbs' => forum_get_breadcrumbs($forum['forum_id']),
|
||||
'forum_info' => $forum,
|
||||
'forum_breadcrumbs' => $breadcrumbs,
|
||||
'forum_topics' => $topics,
|
||||
'forum_offset' => $topicsOffset,
|
||||
'forum_range' => $topicsRange,
|
||||
|
|
|
@ -31,7 +31,8 @@ $categories = array_merge([
|
|||
|
||||
$getSubCategories = $db->prepare('
|
||||
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_title` as `recent_topic_title`,
|
||||
p.`post_created` as `recent_post_created`,
|
||||
|
|
|
@ -46,7 +46,7 @@ if (!empty($postId)) {
|
|||
|
||||
if (!empty($topicId)) {
|
||||
$getTopic = $db->prepare('
|
||||
SELECT `topic_id`, `forum_id`, `topic_title`
|
||||
SELECT `topic_id`, `forum_id`, `topic_title`, `topic_locked`
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `topic_id` = :topic_id
|
||||
');
|
||||
|
@ -60,7 +60,7 @@ if (!empty($topicId)) {
|
|||
|
||||
if (!empty($forumId)) {
|
||||
$getForum = $db->prepare('
|
||||
SELECT `forum_id`, `forum_name`, `forum_type`
|
||||
SELECT `forum_id`, `forum_name`, `forum_type`, `forum_archived`
|
||||
FROM `msz_forum_categories`
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
|
@ -74,82 +74,67 @@ if (empty($forum)) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($forum['forum_type'] != 0) {
|
||||
if ($forum['forum_type'] != MSZ_FORUM_TYPE_DISCUSSION) {
|
||||
http_response_code(400);
|
||||
echo $templating->render('errors.400');
|
||||
return;
|
||||
}
|
||||
|
||||
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 ($forum['forum_archived'] || !empty($topic['topic_locked'])) {
|
||||
http_response_code(403);
|
||||
echo $templating->render('errors.403');
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
if ($postRequest) {
|
||||
$topicTitle = $_POST['post']['title'] ?? '';
|
||||
$topicTitleValidate = forum_validate_title($topicTitle);
|
||||
$postText = $_POST['post']['text'] ?? '';
|
||||
$postTextValidate = forum_validate_post($postText);
|
||||
|
||||
switch ($postTextValidate) {
|
||||
case 'too-short':
|
||||
echo 'Post content was too short.';
|
||||
return;
|
||||
|
||||
case 'too-long':
|
||||
echo 'Post content was too long.';
|
||||
return;
|
||||
}
|
||||
|
||||
$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();
|
||||
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}");
|
||||
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)) {
|
||||
$templating->var('posting_topic', $topic);
|
||||
}
|
||||
|
||||
echo $templating->render('forum.posting', [
|
||||
'posting_breadcrumbs' => $breadcrumbs,
|
||||
'posting_breadcrumbs' => forum_get_breadcrumbs($forumId),
|
||||
'posting_forum' => $forum,
|
||||
]);
|
||||
|
|
|
@ -13,24 +13,7 @@ $postsRange = max(min((int)($_GET['r'] ?? 10), 25), 5);
|
|||
|
||||
// find topic id
|
||||
if ($topicId < 1 && $postId > 0) {
|
||||
$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`
|
||||
');
|
||||
$getPostInfo->bindValue('post_id', $postId);
|
||||
$postInfo = $getPostInfo->execute() ? $getPostInfo->fetch() : false;
|
||||
$postInfo = forum_post_find($postId);
|
||||
|
||||
if ($postInfo) {
|
||||
$topicId = (int)$postInfo['target_topic_id'];
|
||||
|
@ -40,7 +23,8 @@ if ($topicId < 1 && $postId > 0) {
|
|||
|
||||
$getTopic = $db->prepare('
|
||||
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`)
|
||||
FROM `msz_forum_posts`
|
||||
|
@ -52,6 +36,8 @@ $getTopic = $db->prepare('
|
|||
WHERE `topic_id` = t.`topic_id`
|
||||
) as `topic_post_count`
|
||||
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
|
||||
AND t.`topic_deleted` IS NULL
|
||||
');
|
||||
|
@ -93,31 +79,8 @@ if (!$posts) {
|
|||
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', [
|
||||
'topic_breadcrumbs' => $breadcrumbs,
|
||||
'topic_breadcrumbs' => forum_get_breadcrumbs($topic['forum_id']),
|
||||
'topic_info' => $topic,
|
||||
'topic_posts' => $posts,
|
||||
'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 %}
|
||||
{% 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 }}
|
||||
{{ fcpagination }}
|
||||
|
|
|
@ -118,10 +118,27 @@
|
|||
|
||||
{% macro forum_topic_buttons(topic) %}
|
||||
<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>
|
||||
{% 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) %}
|
||||
{% from _self import forum_topic_entry %}
|
||||
|
||||
|
@ -155,7 +172,7 @@
|
|||
{% elseif topic.topic_type == 1 %}
|
||||
{% set topic_type = 'pinned' %}
|
||||
{% 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' %}
|
||||
{% else %}
|
||||
{% set topic_type = 'default' %}
|
||||
|
@ -281,6 +298,10 @@
|
|||
<div class="container__content forum__posting__content">
|
||||
<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 %}
|
||||
<div class="forum__posting__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' %}
|
||||
{% 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 base_url = '/forum/topic.php?t=' ~ topic_info.topic_id %}
|
||||
{% set canonical_url = base_url %}
|
||||
|
||||
{% set ftbuttons = app.hasActiveSession ? forum_topic_buttons(topic_info) : '' %}
|
||||
{% set ftpagination = pagination(topic_info.topic_post_count, topic_range, topic_offset, base_url) %}
|
||||
{% set can_reply = app.hasActiveSession and topic_info.topic_locked is null and not topic_info.topic_archived %}
|
||||
{% 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 %}
|
||||
{{ navigation(topic_breadcrumbs, topic_breadcrumbs|last, true, null, 'left') }}
|
||||
|
@ -18,20 +26,22 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{ forum_topic_locked(topic_info.topic_locked, topic_info.topic_archived) }}
|
||||
|
||||
{{ ftbuttons }}
|
||||
{{ ftpagination }}
|
||||
{{ forum_post_listing(topic_posts, topic_info.topic_first_post_id) }}
|
||||
{{ ftpagination }}
|
||||
|
||||
{% if app.hasActiveSession %}
|
||||
{% if can_reply %}
|
||||
{{ forum_posting_form('Reply', topic_info.topic_id, true, 'reply', true) }}
|
||||
|
||||
<script>
|
||||
<!--script>
|
||||
window.addEventListener('load', () => {
|
||||
closeContainer('reply');
|
||||
document.getElementById('reply').children[0].addEventListener('mouseover', () => openContainer('reply'));
|
||||
});
|
||||
</script>
|
||||
</script-->
|
||||
{% endif %}
|
||||
|
||||
{{ navigation(mio_navigation, '/forum/') }}
|
||||
|
|
Loading…
Add table
Reference in a new issue