// more replacements

This commit is contained in:
flash 2020-10-03 16:54:51 +00:00
parent cc72b8211b
commit 419e9b3e0a
6 changed files with 68 additions and 299 deletions

View file

@ -3,6 +3,8 @@ namespace Misuzu;
use Misuzu\Forum\ForumCategory;
use Misuzu\Forum\ForumCategoryNotFoundException;
use Misuzu\Forum\ForumTopic;
use Misuzu\Forum\ForumTopicNotFoundException;
use Misuzu\Net\IPAddress;
use Misuzu\Parsers\Parser;
use Misuzu\Users\User;
@ -73,13 +75,11 @@ if(!empty($postId)) {
}
}
if(!empty($topicId)) {
$topic = forum_topic_get($topicId);
if(isset($topic['forum_id'])) {
$forumId = (int)$topic['forum_id'];
}
}
if(!empty($topicId))
try {
$topicInfo = ForumTopic::byId($topicId);
$forumId = $topicInfo->getCategoryId();
} catch(ForumTopicNotFoundException $ex) {}
try {
@ -92,9 +92,9 @@ try {
$perms = forum_perms_get_user($forumInfo->getId(), $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
if($forumInfo->isArchived()
|| (!empty($topic['topic_locked']) && !perms_check($perms, MSZ_FORUM_PERM_LOCK_TOPIC))
|| (!empty($topicInfo) && $topicInfo->isLocked() && !perms_check($perms, MSZ_FORUM_PERM_LOCK_TOPIC))
|| !perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM | MSZ_FORUM_PERM_CREATE_POST)
|| (empty($topic) && !perms_check($perms, MSZ_FORUM_PERM_CREATE_TOPIC))) {
|| (empty($topicInfo) && !perms_check($perms, MSZ_FORUM_PERM_CREATE_TOPIC))) {
echo render_error(403);
return;
}
@ -145,7 +145,7 @@ if(!empty($_POST)) {
if(!CSRF::validateRequest()) {
$notices[] = 'Could not verify request.';
} else {
$isEditingTopic = empty($topic) || ($mode === 'edit' && $post['is_opening_post']);
$isEditingTopic = empty($topicInfo) || ($mode === 'edit' && $post['is_opening_post']);
if($mode === 'create') {
$timeoutCheck = max(1, forum_timeout($forumInfo->getId(), $currentUserId));
@ -157,9 +157,9 @@ if(!empty($_POST)) {
}
if($isEditingTopic) {
$originalTopicTitle = $topic['topic_title'] ?? null;
$originalTopicTitle = empty($topicInfo) ? null : $topicInfo->getTitle();
$topicTitleChanged = $topicTitle !== $originalTopicTitle;
$originalTopicType = (int)($topic['topic_type'] ?? MSZ_TOPIC_TYPE_DISCUSSION);
$originalTopicType = empty($topicInfo) ? ForumTopic::TYPE_DISCUSSION : $topicInfo->getType();
$topicTypeChanged = $topicType !== null && $topicType !== $originalTopicType;
switch(forum_validate_title($topicTitle)) {
@ -196,8 +196,8 @@ if(!empty($_POST)) {
if(empty($notices)) {
switch($mode) {
case 'create':
if(!empty($topic)) {
forum_topic_bump($topic['topic_id']);
if(!empty($topicInfo)) {
$topicInfo->bumpTopic();
} else {
$topicId = forum_topic_create(
$forumInfo->getId(),
@ -217,7 +217,7 @@ if(!empty($_POST)) {
$postSignature
);
forum_topic_mark_read($currentUserId, $topicId, $forumInfo->getId());
$forumInfo->increaseTopicPostCount(empty($topic));
$forumInfo->increaseTopicPostCount(empty($topicInfo));
break;
case 'edit':
@ -234,7 +234,7 @@ if(!empty($_POST)) {
}
if(empty($notices)) {
$redirect = url(empty($topic) ? 'forum-topic' : 'forum-post', [
$redirect = url(empty($topicInfo) ? 'forum-topic' : 'forum-post', [
'topic' => $topicId ?? 0,
'post' => $postId ?? 0,
'post_fragment' => 'p' . ($postId ?? 0),
@ -246,8 +246,8 @@ if(!empty($_POST)) {
}
}
if(!empty($topic)) {
Template::set('posting_topic', $topic);
if(!empty($topicInfo)) {
Template::set('posting_topic', $topicInfo);
}
if($mode === 'edit') { // $post is pretty much sure to be populated at this point

View file

@ -293,7 +293,8 @@ if(in_array($moderationMode, $validModerationModes, true)) {
break;
case 'bump':
if($canBumpTopic && forum_topic_bump($topicInfo->getId())) {
if($canBumpTopic) {
$topicInfo->bumpTopic();
AuditLog::create(AuditLog::FORUM_TOPIC_BUMP, [$topicInfo->getId()]);
}
@ -303,7 +304,8 @@ if(in_array($moderationMode, $validModerationModes, true)) {
break;
case 'lock':
if($canLockTopic && !$topicInfo->isLocked() && forum_topic_lock($topicInfo->getId())) {
if($canLockTopic && !$topicInfo->isLocked()) {
$topicInfo->setLocked(true);
AuditLog::create(AuditLog::FORUM_TOPIC_LOCK, [$topicInfo->getId()]);
}
@ -313,7 +315,8 @@ if(in_array($moderationMode, $validModerationModes, true)) {
break;
case 'unlock':
if($canLockTopic && $topicInfo->isLocked() && forum_topic_unlock($topicInfo->getId())) {
if($canLockTopic && $topicInfo->isLocked()) {
$topicInfo->setLocked(false);
AuditLog::create(AuditLog::FORUM_TOPIC_UNLOCK, [$topicInfo->getId()]);
}

View file

@ -1,6 +1,7 @@
<?php
namespace Misuzu;
use Misuzu\Forum\ForumTopic;
use Misuzu\News\NewsPost;
use Misuzu\Users\User;
@ -9,7 +10,7 @@ require_once '../misuzu.php';
$searchQuery = !empty($_GET['q']) && is_string($_GET['q']) ? $_GET['q'] : '';
if(!empty($searchQuery)) {
$forumTopics = forum_topic_listing_search($searchQuery, User::hasCurrent() ? User::getCurrent()->getId() : 0);
$forumTopics = ForumTopic::bySearchQuery($searchQuery);
$forumPosts = forum_post_search($searchQuery);
$newsPosts = NewsPost::bySearchQuery($searchQuery);

View file

@ -15,14 +15,14 @@ class ForumTopic {
public const TYPE_ANNOUNCEMENT = 2;
public const TYPE_GLOBAL_ANNOUNCEMENT = 3;
private const TYPE_ORDER = [
public const TYPE_ORDER = [
self::TYPE_GLOBAL_ANNOUNCEMENT,
self::TYPE_ANNOUNCEMENT,
self::TYPE_STICKY,
self::TYPE_DISCUSSION,
];
private const TYPE_IMPORTANT = [
public const TYPE_IMPORTANT = [
self::TYPE_STICKY,
self::TYPE_ANNOUNCEMENT,
self::TYPE_GLOBAL_ANNOUNCEMENT,
@ -212,11 +212,14 @@ class ForumTopic {
return $this->topic_bumped === null ? -1 : $this->topic_bumped;
}
public function bumpTopic(): void {
if($this->isDeleted())
return;
$this->topic_bumped = time();
DB::prepare(
'UPDATE `' . DB::PREFIX . self::TABLE . '`'
. ' SET `topic_bumped` = NOW()'
. ' WHERE `topic_id` = :topic'
. ' AND `topic_deleted` IS NULL'
)->bind('topic', $this->getId())->execute();
}
@ -368,4 +371,26 @@ class ForumTopic {
$memoizer->insert($objects[] = $object);
return $objects;
}
public static function bySearchQuery(string $search, bool $includeDeleted = false, ?Pagination $pagination = null): array {
$query = self::byQueryBase()
. ' WHERE MATCH(`topic_title`) AGAINST (:search IN NATURAL LANGUAGE MODE)'
. ($includeDeleted ? '' : ' AND `topic_deleted` IS NULL')
. ' ORDER BY FIELD(`topic_type`, ' . implode(',', self::TYPE_ORDER) . '), `topic_bumped` DESC';
if($pagination !== null)
$query .= ' LIMIT :range OFFSET :offset';
$getObjects = DB::prepare($query)
->bind('search', $search);
if($pagination !== null)
$getObjects->bind('range', $pagination->getRange())
->bind('offset', $pagination->getOffset());
$objects = [];
$memoizer = self::memoizer();
while($object = $getObjects->fetchObject(self::class))
$memoizer->insert($objects[] = $object);
return $objects;
}
}

View file

@ -71,54 +71,6 @@ function forum_topic_update(int $topicId, ?string $title, ?int $type = null): bo
return $updateTopic->execute();
}
function forum_topic_get(int $topicId, bool $allowDeleted = false): array {
$getTopic = \Misuzu\DB::prepare(sprintf(
'
SELECT
t.`topic_id`, t.`forum_id`, t.`topic_title`, t.`topic_type`, t.`topic_locked`, t.`topic_created`,
f.`forum_archived` AS `topic_archived`, t.`topic_deleted`, t.`topic_bumped`, f.`forum_type`,
fp.`topic_id` AS `author_post_id`, fp.`user_id` AS `author_user_id`,
(
SELECT COUNT(`post_id`)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `post_deleted` IS NULL
) AS `topic_count_posts`,
(
SELECT COUNT(`post_id`)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `post_deleted` IS NOT NULL
) AS `topic_count_posts_deleted`
FROM `msz_forum_topics` AS t
LEFT JOIN `msz_forum_categories` AS f
ON f.`forum_id` = t.`forum_id`
LEFT JOIN `msz_forum_posts` AS fp
ON fp.`post_id` = (
SELECT MIN(`post_id`)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
)
WHERE t.`topic_id` = :topic_id
%s
',
$allowDeleted ? '' : 'AND t.`topic_deleted` IS NULL'
));
$getTopic->bind('topic_id', $topicId);
return $getTopic->fetch();
}
function forum_topic_bump(int $topicId): bool {
$bumpTopic = \Misuzu\DB::prepare('
UPDATE `msz_forum_topics`
SET `topic_bumped` = NOW()
WHERE `topic_id` = :topic_id
AND `topic_deleted` IS NULL
');
$bumpTopic->bind('topic_id', $topicId);
return $bumpTopic->execute();
}
function forum_topic_views_increment(int $topicId): void {
if($topicId < 1) {
return;
@ -174,110 +126,6 @@ function forum_topic_mark_read(int $userId, int $topicId, int $forumId): void {
}
}
function forum_topic_listing(
int $forumId, int $userId,
int $offset = 0, int $take = 0,
bool $showDeleted = false, bool $sortByPriority = false
): array {
$hasPagination = $offset >= 0 && $take > 0;
$getTopics = \Misuzu\DB::prepare(sprintf(
'
SELECT
:user_id AS `target_user_id`,
t.`topic_id`, t.`topic_title`, t.`topic_locked`, t.`topic_type`, t.`topic_created`,
t.`topic_bumped`, t.`topic_deleted`, t.`topic_count_views`, f.`forum_type`,
COALESCE(SUM(tp.`topic_priority`), 0) AS `topic_priority`,
au.`user_id` AS `author_id`, au.`username` AS `author_name`,
COALESCE(au.`user_colour`, ar.`role_colour`) AS `author_colour`,
lp.`post_id` AS `response_id`,
lp.`post_created` AS `response_created`,
lu.`user_id` AS `respondent_id`,
lu.`username` AS `respondent_name`,
COALESCE(lu.`user_colour`, lr.`role_colour`) AS `respondent_colour`,
(
SELECT COUNT(`post_id`)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
%5$s
) AS `topic_count_posts`,
(
SELECT CEIL(COUNT(`post_id`) / %6$d)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
%5$s
) AS `topic_pages`,
(
SELECT
`target_user_id` > 0
AND
t.`topic_bumped` > NOW() - INTERVAL 1 MONTH
AND (
SELECT COUNT(ti.`topic_id`) < 1
FROM `msz_forum_topics_track` AS tt
RIGHT JOIN `msz_forum_topics` AS ti
ON ti.`topic_id` = tt.`topic_id`
WHERE ti.`topic_id` = t.`topic_id`
AND tt.`user_id` = `target_user_id`
AND `track_last_read` >= `topic_bumped`
)
) AS `topic_unread`,
(
SELECT COUNT(`post_id`) > 0
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `user_id` = `target_user_id`
LIMIT 1
) AS `topic_participated`
FROM `msz_forum_topics` AS t
LEFT JOIN `msz_forum_topics_priority` AS tp
ON tp.`topic_id` = t.`topic_id`
LEFT JOIN `msz_forum_categories` AS f
ON f.`forum_id` = t.`forum_id`
LEFT JOIN `msz_users` AS au
ON t.`user_id` = au.`user_id`
LEFT JOIN `msz_roles` AS ar
ON ar.`role_id` = au.`display_role`
LEFT JOIN `msz_forum_posts` AS lp
ON lp.`post_id` = (
SELECT `post_id`
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
%5$s
ORDER BY `post_id` DESC
LIMIT 1
)
LEFT JOIN `msz_users` AS lu
ON lu.`user_id` = lp.`user_id`
LEFT JOIN `msz_roles` AS lr
ON lr.`role_id` = lu.`display_role`
WHERE (
t.`forum_id` = :forum_id
OR t.`topic_type` = %3$d
)
%1$s
GROUP BY t.`topic_id`
ORDER BY FIELD(t.`topic_type`, %4$s) DESC, %7$s t.`topic_bumped` DESC
%2$s
',
$showDeleted ? '' : 'AND t.`topic_deleted` IS NULL',
$hasPagination ? 'LIMIT :offset, :take' : '',
MSZ_TOPIC_TYPE_GLOBAL_ANNOUNCEMENT,
implode(',', array_reverse(MSZ_TOPIC_TYPE_ORDER)),
$showDeleted ? '' : 'AND `post_deleted` IS NULL',
MSZ_FORUM_POSTS_PER_PAGE,
$sortByPriority ? '`topic_priority` DESC,' : ''
));
$getTopics->bind('forum_id', $forumId);
$getTopics->bind('user_id', $userId);
if($hasPagination) {
$getTopics->bind('offset', $offset);
$getTopics->bind('take', $take);
}
return $getTopics->fetchAll();
}
function forum_topic_count_user(int $authorId, int $userId, bool $showDeleted = false): int {
$getTopics = \Misuzu\DB::prepare(sprintf(
'
@ -393,120 +241,6 @@ function forum_topic_listing_user(
return $getTopics->fetchAll();
}
function forum_topic_listing_search(string $query, int $userId): array {
$getTopics = \Misuzu\DB::prepare(sprintf(
'
SELECT
:user_id AS `target_user_id`,
t.`topic_id`, t.`topic_title`, t.`topic_locked`, t.`topic_type`, t.`topic_created`,
t.`topic_bumped`, t.`topic_deleted`, t.`topic_count_views`, f.`forum_type`,
au.`user_id` AS `author_id`, au.`username` AS `author_name`,
COALESCE(au.`user_colour`, ar.`role_colour`) AS `author_colour`,
lp.`post_id` AS `response_id`,
lp.`post_created` AS `response_created`,
lu.`user_id` AS `respondent_id`,
lu.`username` AS `respondent_name`,
COALESCE(lu.`user_colour`, lr.`role_colour`) AS `respondent_colour`,
(
SELECT COUNT(`post_id`)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `post_deleted` IS NULL
) AS `topic_count_posts`,
(
SELECT CEIL(COUNT(`post_id`) / %2$d)
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `post_deleted` IS NULL
) AS `topic_pages`,
(
SELECT
`target_user_id` > 0
AND
t.`topic_bumped` > NOW() - INTERVAL 1 MONTH
AND (
SELECT COUNT(ti.`topic_id`) < 1
FROM `msz_forum_topics_track` AS tt
RIGHT JOIN `msz_forum_topics` AS ti
ON ti.`topic_id` = tt.`topic_id`
WHERE ti.`topic_id` = t.`topic_id`
AND tt.`user_id` = `target_user_id`
AND `track_last_read` >= `topic_bumped`
)
) AS `topic_unread`,
(
SELECT COUNT(`post_id`) > 0
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `user_id` = `target_user_id`
LIMIT 1
) AS `topic_participated`
FROM `msz_forum_topics` AS t
LEFT JOIN `msz_forum_categories` AS f
ON f.`forum_id` = t.`forum_id`
LEFT JOIN `msz_users` AS au
ON t.`user_id` = au.`user_id`
LEFT JOIN `msz_roles` AS ar
ON ar.`role_id` = au.`display_role`
LEFT JOIN `msz_forum_posts` AS lp
ON lp.`post_id` = (
SELECT `post_id`
FROM `msz_forum_posts`
WHERE `topic_id` = t.`topic_id`
AND `post_deleted` IS NULL
ORDER BY `post_id` DESC
LIMIT 1
)
LEFT JOIN `msz_users` AS lu
ON lu.`user_id` = lp.`user_id`
LEFT JOIN `msz_roles` AS lr
ON lr.`role_id` = lu.`display_role`
WHERE MATCH(`topic_title`)
AGAINST (:query IN NATURAL LANGUAGE MODE)
AND t.`topic_deleted` IS NULL
ORDER BY FIELD(t.`topic_type`, %1$s) DESC, t.`topic_bumped` DESC
',
implode(',', array_reverse(MSZ_TOPIC_TYPE_ORDER)),
MSZ_FORUM_POSTS_PER_PAGE
));
$getTopics->bind('query', $query);
$getTopics->bind('user_id', $userId);
return $getTopics->fetchAll();
}
function forum_topic_lock(int $topicId): bool {
if($topicId < 1) {
return false;
}
$markLocked = \Misuzu\DB::prepare('
UPDATE `msz_forum_topics`
SET `topic_locked` = NOW()
WHERE `topic_id` = :topic
AND `topic_locked` IS NULL
');
$markLocked->bind('topic', $topicId);
return $markLocked->execute();
}
function forum_topic_unlock(int $topicId): bool {
if($topicId < 1) {
return false;
}
$markUnlocked = \Misuzu\DB::prepare('
UPDATE `msz_forum_topics`
SET `topic_locked` = NULL
WHERE `topic_id` = :topic
AND `topic_locked` IS NOT NULL
');
$markUnlocked->bind('topic', $topicId);
return $markUnlocked->execute();
}
define('MSZ_E_FORUM_TOPIC_DELETE_OK', 0); // deleting is fine
define('MSZ_E_FORUM_TOPIC_DELETE_USER', 1); // invalid user
define('MSZ_E_FORUM_TOPIC_DELETE_TOPIC', 2); // topic doesn't exist
@ -529,6 +263,16 @@ function forum_topic_can_delete($topicId, ?int $userId = null): int {
return MSZ_E_FORUM_TOPIC_DELETE_USER;
}
if(is_array($topicId)) {
$topic = $topicId;
} elseif(is_int($topicId)) {
try {
$topic = \Misuzu\Forum\ForumTopic::byId($topicId);
} catch(\Misuzu\Forum\ForumTopicNotFoundException $ex) {
return MSZ_E_FORUM_TOPIC_DELETE_TOPIC;
}
}
if($topicId instanceof \Misuzu\Forum\ForumTopic) {
$topic = [
'forum_id' => $topicId->getCategoryId(),
@ -538,10 +282,6 @@ function forum_topic_can_delete($topicId, ?int $userId = null): int {
'topic_count_posts' => $topicId->getActualPostCount(true),
'topic_count_posts_deleted' => 0,
];
} elseif(is_array($topicId)) {
$topic = $topicId;
} else {
$topic = forum_topic_get((int)$topicId, true);
}
if(empty($topic)) {

View file

@ -9,23 +9,23 @@
{% block content %}
<form method="post" action="{{ url('forum-' ~ (is_reply ? 'post' : 'topic') ~ '-create') }}">
{{ input_hidden('post[' ~ (is_reply ? 'topic' : 'forum') ~ ']', is_reply ? posting_topic.topic_id : posting_forum.id) }}
{{ input_hidden('post[' ~ (is_reply ? 'topic' : 'forum') ~ ']', is_reply ? posting_topic.id : posting_forum.id) }}
{{ input_hidden('post[mode]', posting_mode) }}
{{ input_csrf() }}
{{ forum_header(
is_reply and not is_opening
? posting_topic.topic_title
? posting_topic.title
: input_text(
'post[title]',
'forum__header__input',
posting_defaults.title|default(posting_topic.topic_title|default('')),
posting_defaults.title|default(posting_topic.title|default('')),
'text',
'Enter your title here...'
),
posting_breadcrumbs,
false,
is_reply and not is_opening
? url('forum-topic', {'topic': posting_topic.topic_id})
? url('forum-topic', {'topic': posting_topic.id})
: ''
) }}
@ -147,7 +147,7 @@
{{ input_select(
'post[type]',
posting_types,
posting_defaults.type|default(posting_topic.topic_type|default(posting_types|keys|first)),
posting_defaults.type|default(posting_topic.type|default(posting_types|keys|first)),
null, null, null, 'forum__post__dropdown'
) }}
{% endif %}