Added ability to add redirects to deleted topic ids.
This commit is contained in:
parent
6f679fc78c
commit
8038f61470
11 changed files with 275 additions and 24 deletions
23
database/2023_04_30_001226_create_topic_redirs_table.php
Normal file
23
database/2023_04_30_001226_create_topic_redirs_table.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
use Index\Data\IDbConnection;
|
||||
use Index\Data\Migration\IDbMigration;
|
||||
|
||||
final class CreateTopicRedirsTable_20230430_001226 implements IDbMigration {
|
||||
public function migrate(IDbConnection $conn): void {
|
||||
$conn->execute('
|
||||
CREATE TABLE msz_forum_topics_redirects (
|
||||
topic_id INT(10) UNSIGNED NOT NULL,
|
||||
user_id INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
topic_redir_url VARCHAR(255) NOT NULL,
|
||||
topic_redir_created TIMESTAMP NOT NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (topic_id),
|
||||
KEY topics_redirs_user_foreign (user_id),
|
||||
CONSTRAINT topics_redirs_user_foreign
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES msz_users (user_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB COLLATE=utf8mb4_bin;
|
||||
');
|
||||
}
|
||||
}
|
|
@ -31,12 +31,21 @@ $perms = $topic
|
|||
if(isset($topicUser) && $topicUser->hasActiveWarning())
|
||||
$perms &= ~MSZ_FORUM_PERM_SET_WRITE;
|
||||
|
||||
$topicIsNuked = empty($topic['topic_id']);
|
||||
$topicIsDeleted = !empty($topic['topic_deleted']);
|
||||
$canDeleteAny = perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
|
||||
if(!$topic || ($topicIsDeleted && !$canDeleteAny)) {
|
||||
echo render_error(404);
|
||||
return;
|
||||
if($topicIsNuked || $topicIsDeleted) {
|
||||
$topicRedirectInfo = forum_topic_redir_info($topicId);
|
||||
Template::set('topic_redir_info', $topicRedirectInfo);
|
||||
|
||||
if($topicIsNuked || !$canDeleteAny) {
|
||||
if(empty($topicRedirectInfo))
|
||||
echo render_error(404);
|
||||
else
|
||||
header('Location: ' . $topicRedirectInfo->topic_redir_url);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM)) {
|
||||
|
|
51
public/manage/forum/redirs.php
Normal file
51
public/manage/forum/redirs.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
use Misuzu\Users\User;
|
||||
|
||||
require_once '../../../misuzu.php';
|
||||
|
||||
if(!User::hasCurrent() || !perms_check_user(MSZ_PERMS_GENERAL, User::getCurrent()->getId(), MSZ_PERM_FORUM_TOPIC_REDIRS)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
||||
if($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if(!CSRF::validateRequest())
|
||||
throw new \Exception("Request verification failed.");
|
||||
|
||||
$rTopicId = (int)filter_input(INPUT_POST, 'topic_redir_id');
|
||||
$rTopicURL = trim((string)filter_input(INPUT_POST, 'topic_redir_url'));
|
||||
|
||||
if($rTopicId < 1)
|
||||
throw new \Exception("Invalid topic id.");
|
||||
|
||||
AuditLog::create($_SERVER['REMOTE_ADDR'], AuditLog::FORUM_TOPIC_REDIR_CREATE, [$rTopicId]);
|
||||
forum_topic_redir_create($rTopicId, User::getCurrent()->getId(), $rTopicURL);
|
||||
url_redirect('manage-forum-topic-redirs');
|
||||
return;
|
||||
}
|
||||
|
||||
if(filter_input(INPUT_GET, 'm') === 'explode') {
|
||||
if(!CSRF::validateRequest())
|
||||
throw new \Exception("Request verification failed.");
|
||||
|
||||
$rTopicId = (int)filter_input(INPUT_GET, 't');
|
||||
AuditLog::create($_SERVER['REMOTE_ADDR'], AuditLog::FORUM_TOPIC_REDIR_REMOVE, [$rTopicId]);
|
||||
forum_topic_redir_remove($rTopicId);
|
||||
url_redirect('manage-forum-topic-redirs');
|
||||
return;
|
||||
}
|
||||
|
||||
$pagination = new Pagination(forum_topic_redir_count(), 20);
|
||||
if(!$pagination->hasValidOffset()) {
|
||||
echo render_error(404);
|
||||
return;
|
||||
}
|
||||
|
||||
$redirs = forum_topic_redir_all($pagination->getOffset(), $pagination->getRange());
|
||||
|
||||
Template::render('manage.forum.redirs', [
|
||||
'manage_redirs' => $redirs,
|
||||
'manage_redirs_pagination' => $pagination,
|
||||
]);
|
|
@ -40,6 +40,8 @@ class AuditLog {
|
|||
public const FORUM_TOPIC_BUMP = 'FORUM_TOPIC_BUMP';
|
||||
public const FORUM_TOPIC_LOCK = 'FORUM_TOPIC_LOCK';
|
||||
public const FORUM_TOPIC_UNLOCK = 'FORUM_TOPIC_UNLOCK';
|
||||
public const FORUM_TOPIC_REDIR_CREATE = 'FORUM_TOPIC_REDIR_CREATE';
|
||||
public const FORUM_TOPIC_REDIR_REMOVE = 'FORUM_TOPIC_REDIR_REMOVE';
|
||||
|
||||
public const FORUM_POST_EDIT = 'FORUM_POST_EDIT';
|
||||
public const FORUM_POST_DELETE = 'FORUM_POST_DELETE';
|
||||
|
@ -88,6 +90,8 @@ class AuditLog {
|
|||
self::FORUM_TOPIC_BUMP => 'Manually bumped forum topic #%d.',
|
||||
self::FORUM_TOPIC_LOCK => 'Locked forum topic #%d.',
|
||||
self::FORUM_TOPIC_UNLOCK => 'Unlocked forum topic #%d.',
|
||||
self::FORUM_TOPIC_REDIR_CREATE => 'Created redirect for topic #%d.',
|
||||
self::FORUM_TOPIC_REDIR_REMOVE => 'Removed redirect for topic #%d.',
|
||||
|
||||
self::CONFIG_CREATE => 'Created config value with name "%s".',
|
||||
self::CONFIG_UPDATE => 'Updated config value with name "%s".',
|
||||
|
|
|
@ -108,6 +108,56 @@ function forum_topic_get(int $topicId, bool $allowDeleted = false): array {
|
|||
return $getTopic->fetch();
|
||||
}
|
||||
|
||||
function forum_topic_redir_info(int $topicId): ?object {
|
||||
$getTopicRedir = \Misuzu\DB::prepare('
|
||||
SELECT topic_id, user_id, topic_redir_url,
|
||||
UNIX_TIMESTAMP(topic_redir_created) AS topic_redir_created
|
||||
FROM msz_forum_topics_redirects
|
||||
WHERE topic_id = :topic_id
|
||||
');
|
||||
$getTopicRedir->bind('topic_id', $topicId);
|
||||
return $getTopicRedir->fetchObject();
|
||||
}
|
||||
|
||||
function forum_topic_redir_count(): int {
|
||||
return \Misuzu\DB::query('SELECT COUNT(*) FROM msz_forum_topics_redirects')->fetchColumn() ?? 0;
|
||||
}
|
||||
|
||||
function forum_topic_redir_all(int $offset, int $take): array {
|
||||
$getTopicRedirs = \Misuzu\DB::prepare('
|
||||
SELECT topic_id, user_id, topic_redir_url,
|
||||
UNIX_TIMESTAMP(topic_redir_created) AS topic_redir_created
|
||||
FROM msz_forum_topics_redirects
|
||||
LIMIT :offset, :take
|
||||
');
|
||||
$getTopicRedirs->bind('offset', $offset);
|
||||
$getTopicRedirs->bind('take', $take);
|
||||
return $getTopicRedirs->fetchObjects();
|
||||
}
|
||||
|
||||
function forum_topic_redir_create(int $topicId, int $userId, string $url): void {
|
||||
if($topicId < 1 || empty($url)) return;
|
||||
if($userId < 1) $userId = null;
|
||||
|
||||
$createTopicRedir = \Misuzu\DB::prepare('
|
||||
INSERT INTO msz_forum_topics_redirects (topic_id, user_id, topic_redir_url)
|
||||
VALUES (:topic_id, :user_id, :redir_url)
|
||||
');
|
||||
$createTopicRedir->bind('topic_id', $topicId);
|
||||
$createTopicRedir->bind('user_id', $userId);
|
||||
$createTopicRedir->bind('redir_url', $url);
|
||||
$createTopicRedir->execute();
|
||||
}
|
||||
|
||||
function forum_topic_redir_remove(int $topicId): void {
|
||||
$removeTopicRedir = \Misuzu\DB::prepare('
|
||||
DELETE FROM msz_forum_topics_redirects
|
||||
WHERE topic_id = :topic_id
|
||||
');
|
||||
$removeTopicRedir->bind('topic_id', $topicId);
|
||||
$removeTopicRedir->execute();
|
||||
}
|
||||
|
||||
function forum_topic_bump(int $topicId): bool {
|
||||
$bumpTopic = \Misuzu\DB::prepare('
|
||||
UPDATE `msz_forum_topics`
|
||||
|
|
|
@ -30,6 +30,8 @@ function manage_get_menu(int $userId): array {
|
|||
|
||||
if(perms_check_user(MSZ_PERMS_FORUM, $userId, MSZ_PERM_FORUM_MANAGE_FORUMS))
|
||||
$menu['Forum']['Categories'] = url('manage-forum-categories');
|
||||
if(perms_check_user(MSZ_PERMS_FORUM, $userId, MSZ_PERM_FORUM_TOPIC_REDIRS))
|
||||
$menu['Forum']['Topic Redirects'] = url('manage-forum-topic-redirs');
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_CHANGELOG, $userId, MSZ_PERM_CHANGELOG_MANAGE_CHANGES))
|
||||
$menu['Changelog']['Changes'] = url('manage-changelog-changes');
|
||||
|
@ -226,6 +228,11 @@ function manage_perms_list(array $rawPerms): array {
|
|||
'title' => 'Can view the forum leaderboard live.',
|
||||
'perm' => MSZ_PERM_FORUM_VIEW_LEADERBOARD,
|
||||
],
|
||||
[
|
||||
'section' => 'topic-redirs',
|
||||
'title' => 'Can create redirects for deleted topics.',
|
||||
'perm' => MSZ_PERM_FORUM_TOPIC_REDIRS,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
|
|
|
@ -34,6 +34,7 @@ define('MSZ_PERM_NEWS_MANAGE_CATEGORIES', 0x00000002);
|
|||
define('MSZ_PERMS_FORUM', 'forum');
|
||||
define('MSZ_PERM_FORUM_MANAGE_FORUMS', 0x00000001);
|
||||
define('MSZ_PERM_FORUM_VIEW_LEADERBOARD', 0x00000002);
|
||||
define('MSZ_PERM_FORUM_TOPIC_REDIRS', 0x00000004);
|
||||
|
||||
define('MSZ_PERMS_COMMENTS', 'comments');
|
||||
define('MSZ_PERM_COMMENTS_CREATE', 0x00000001);
|
||||
|
|
|
@ -103,6 +103,9 @@ define('MSZ_URLS', [
|
|||
|
||||
'manage-forum-categories' => ['/manage/forum/index.php'],
|
||||
'manage-forum-category' => ['/manage/forum/category.php', ['f' => '<forum>']],
|
||||
'manage-forum-topic-redirs' => ['/manage/forum/redirs.php'],
|
||||
'manage-forum-topic-redirs-create' => ['/manage/forum/redirs.php'],
|
||||
'manage-forum-topic-redirs-nuke' => ['/manage/forum/redirs.php', ['m' => 'explode', 't' => '<topic>', 'csrf' => '{csrf}']],
|
||||
|
||||
'manage-changelog-changes' => ['/manage/changelog'],
|
||||
'manage-changelog-change' => ['/manage/changelog/change.php', ['c' => '<change>']],
|
||||
|
|
|
@ -209,24 +209,42 @@
|
|||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro forum_topic_locked(locked, archived) %}
|
||||
{% if locked is not null or archived %}
|
||||
<div class="container forum__status">
|
||||
<div class="forum__status__icon">
|
||||
<div class="forum__status__icon__background"></div>
|
||||
<i class="fas fa-{{ archived ? 'archive' : 'lock' }}"></i>
|
||||
</div>
|
||||
<div class="forum__status__text">
|
||||
{% if archived %}
|
||||
This topic has been <span class="forum__status__emphasis">archived</span>.
|
||||
{% else %}
|
||||
This topic was locked
|
||||
<time class="forum__status__emphasis"
|
||||
datetime="{{ locked|date('c') }}"
|
||||
title="{{ locked|date('r') }}">{{ locked|time_diff }}</time>.
|
||||
{% endif %}
|
||||
</div>
|
||||
{% macro forum_topic_notice(icon, body) %}
|
||||
<div class="container forum__status">
|
||||
<div class="forum__status__icon">
|
||||
<div class="forum__status__icon__background"></div>
|
||||
<i class="fas fa-{{ icon }}"></i>
|
||||
</div>
|
||||
<div class="forum__status__text">
|
||||
{{ body|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro forum_topic_redirect(redirect) %}
|
||||
{% from _self import forum_topic_notice %}
|
||||
{% if redirect is not empty %}
|
||||
{% set body %}
|
||||
This topic redirects to <span class="forum__status__emphasis"><a href="{{ redirect.topic_redir_url }}" class="link">{{ redirect.topic_redir_url }}</a></span>.
|
||||
{% endset %}
|
||||
{{ forum_topic_notice('share', body) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro forum_topic_locked(locked, archived) %}
|
||||
{% from _self import forum_topic_notice %}
|
||||
{% if locked is not null or archived %}
|
||||
{% set body %}
|
||||
{% if archived %}
|
||||
This topic has been <span class="forum__status__emphasis">archived</span>.
|
||||
{% else %}
|
||||
This topic was locked
|
||||
<time class="forum__status__emphasis"
|
||||
datetime="{{ locked|date('c') }}"
|
||||
title="{{ locked|date('r') }}">{{ locked|time_diff }}</time>.
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
{{ forum_topic_notice(archived ? 'archive' : 'lock', body) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
forum_topic_buttons,
|
||||
forum_topic_locked,
|
||||
forum_header,
|
||||
forum_topic_tools
|
||||
forum_topic_tools,
|
||||
forum_topic_redirect
|
||||
%}
|
||||
|
||||
{% set title = topic_info.topic_title %}
|
||||
|
@ -18,7 +19,7 @@
|
|||
|
||||
{% set forum_post_csrf = csrf_token() %}
|
||||
{% set topic_tools = forum_topic_tools(topic_info, topic_pagination, can_reply) %}
|
||||
{% set topic_notice = forum_topic_locked(topic_info.topic_locked, topic_info.topic_archived) %}
|
||||
{% set topic_notice = forum_topic_locked(topic_info.topic_locked, topic_info.topic_archived) ~ forum_topic_redirect(topic_redir_info|default(null)) %}
|
||||
{% set topic_actions = [
|
||||
{
|
||||
'html': '<i class="far fa-trash-alt fa-fw"></i> Delete',
|
||||
|
@ -54,10 +55,10 @@
|
|||
|
||||
{% block content %}
|
||||
{{ forum_header(topic_info.topic_title, topic_breadcrumbs, false, canonical_url, topic_actions) }}
|
||||
{{ topic_notice }}
|
||||
{{ topic_notice|raw }}
|
||||
{{ topic_tools }}
|
||||
{{ forum_post_listing(topic_posts, current_user.id|default(0), topic_perms) }}
|
||||
{{ topic_tools }}
|
||||
{{ topic_notice }}
|
||||
{{ topic_notice|raw }}
|
||||
{{ forum_header('', topic_breadcrumbs) }}
|
||||
{% endblock %}
|
||||
|
|
84
templates/manage/forum/redirs.twig
Normal file
84
templates/manage/forum/redirs.twig
Normal file
|
@ -0,0 +1,84 @@
|
|||
{% extends 'manage/users/master.twig' %}
|
||||
{% from 'macros.twig' import pagination, container_title %}
|
||||
{% from '_layout/input.twig' import input_csrf, input_text %}
|
||||
|
||||
{% set redirs_pagination = pagination(manage_redirs_pagination, url('manage-forum-topic-redirs')) %}
|
||||
|
||||
{% block manage_content %}
|
||||
<div class="container">
|
||||
{{ container_title('<i class="fas fa-share fa-fw"></i> Topic Redirects') }}
|
||||
|
||||
<div class="manage__description">
|
||||
Allows you to set redirects for deleted forum topics.
|
||||
</div>
|
||||
|
||||
<form method="post" action="{{ url('manage-forum-topic-redirs-create') }}" class="manage-setting">
|
||||
{{ input_csrf() }}
|
||||
|
||||
<label class="manage-setting-field">
|
||||
<div class="manage-setting-field-name">Topic #</div>
|
||||
{{ input_text('topic_redir_id', 'manage__emote__field__value', '', 'number') }}
|
||||
</label>
|
||||
|
||||
<label class="manage-setting-field">
|
||||
<div class="manage-setting-field-name">Target URL</div>
|
||||
{{ input_text('topic_redir_url', 'manage__emote__field__value', '', 'text') }}
|
||||
</label>
|
||||
|
||||
<div class="manage-setting-actions">
|
||||
<button class="input__button input__button--save">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if redirs_pagination|trim|length > 0 %}
|
||||
<div class="manage__users__pagination">
|
||||
{{ redirs_pagination }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="manage-settings-list-container">
|
||||
<table class="manage-settings-list">
|
||||
<thead>
|
||||
<tr class="manage-settings-list-header">
|
||||
<th class="manage-settings-list-header-name">Topic #</th>
|
||||
<th class="manage-settings-list-header-name">User #</th>
|
||||
<th class="manage-settings-list-header-value">Target URL</th>
|
||||
<th class="manage-settings-list-header-value">Created</th>
|
||||
<th class="manage-settings-list-header-options">Options</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for redir in manage_redirs %}
|
||||
<tr class="manage-list-setting">
|
||||
<td class="manage-list-setting-key">
|
||||
<div class="manage-list-setting-key-text">{{ redir.topic_id }}</div>
|
||||
</td>
|
||||
<td class="manage-list-setting-key">
|
||||
<div class="manage-list-setting-key-text">{{ redir.user_id }}</div>
|
||||
</td>
|
||||
<td class="manage-list-setting-value">
|
||||
<div class="manage-list-setting-value-text">{{ redir.topic_redir_url }}</div>
|
||||
</td>
|
||||
<td class="manage-list-setting-value">
|
||||
<div class="manage-list-setting-value-text">
|
||||
<time datetime="{{ redir.topic_redir_created|date('c') }}" title="{{ redir.topic_redir_created|date('r') }}">
|
||||
{{ redir.topic_redir_created|time_diff }}
|
||||
</time>
|
||||
</div>
|
||||
</td>
|
||||
<td class="manage-list-setting-options">
|
||||
<a class="input__button input__button--autosize input__button--destroy" href="{{ url('manage-forum-topic-redirs-nuke', {'topic': redir.topic_id}) }}" title="Delete"><i class="fas fa-times fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if redirs_pagination|trim|length > 0 %}
|
||||
<div class="manage__users__pagination">
|
||||
{{ redirs_pagination }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Reference in a new issue