Browse Source

Cyclical threads ♺

pull/40/head
Fredrick Brennan 9 years ago
committed by czaks
parent
commit
505adffcdc
  1. 1
      inc/api.php
  2. 5
      inc/config.php
  3. 8
      inc/functions.php
  4. 22
      inc/mod/pages.php
  5. 7
      install.php
  6. 1
      mod.php
  7. 11
      post.php
  8. 8
      templates/post/post_controls.html
  9. 13
      templates/post_thread.html
  10. 1
      templates/posts.sql

1
inc/api.php

@ -32,6 +32,7 @@ class Api {
'images' => 'images', 'images' => 'images',
'sticky' => 'sticky', 'sticky' => 'sticky',
'locked' => 'locked', 'locked' => 'locked',
'cycle' => 'cyclical',
'bump' => 'last_modified', 'bump' => 'last_modified',
'embed' => 'embed', 'embed' => 'embed',
); );

5
inc/config.php

@ -1245,6 +1245,8 @@
$config['mod']['link_bumpunlock'] = '[-Sage]'; $config['mod']['link_bumpunlock'] = '[-Sage]';
$config['mod']['link_editpost'] = '[Edit]'; $config['mod']['link_editpost'] = '[Edit]';
$config['mod']['link_move'] = '[Move]'; $config['mod']['link_move'] = '[Move]';
$config['mod']['link_cycle'] = '[Cycle]';
$config['mod']['link_uncycle'] = '[-Cycle]';
// Moderator capcodes. // Moderator capcodes.
$config['capcode'] = ' <span class="capcode">## %s</span>'; $config['capcode'] = ' <span class="capcode">## %s</span>';
@ -1388,6 +1390,9 @@
$config['mod']['deletebyip_global'] = ADMIN; $config['mod']['deletebyip_global'] = ADMIN;
// Sticky a thread // Sticky a thread
$config['mod']['sticky'] = MOD; $config['mod']['sticky'] = MOD;
// Cycle a thread
$config['mod']['cycle'] = MOD;
$config['cycle_limit'] = &$config['reply_limit'];
// Lock a thread // Lock a thread
$config['mod']['lock'] = MOD; $config['mod']['lock'] = MOD;
// Post in a locked thread // Post in a locked thread

8
inc/functions.php

@ -1021,7 +1021,7 @@ function insertFloodPost(array $post) {
function post(array $post) { function post(array $post) {
global $pdo, $board; global $pdo, $board;
$query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :files, :num_files, :filehash, :password, :ip, :sticky, :locked, 0, :embed, :slug)", $board['uri'])); $query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :files, :num_files, :filehash, :password, :ip, :sticky, :locked, :cycle, 0, :embed, :slug)", $board['uri']));
// Basic stuff // Basic stuff
if (!empty($post['subject'])) { if (!empty($post['subject'])) {
@ -1061,6 +1061,12 @@ function post(array $post) {
$query->bindValue(':locked', false, PDO::PARAM_INT); $query->bindValue(':locked', false, PDO::PARAM_INT);
} }
if ($post['op'] && $post['mod'] && isset($post['cycle']) && $post['cycle']) {
$query->bindValue(':cycle', true, PDO::PARAM_INT);
} else {
$query->bindValue(':cycle', false, PDO::PARAM_INT);
}
if ($post['mod'] && isset($post['capcode']) && $post['capcode']) { if ($post['mod'] && isset($post['capcode']) && $post['capcode']) {
$query->bindValue(':capcode', $post['capcode'], PDO::PARAM_INT); $query->bindValue(':capcode', $post['capcode'], PDO::PARAM_INT);
} else { } else {

22
inc/mod/pages.php

@ -1089,6 +1089,28 @@ function mod_sticky($board, $unsticky, $post) {
header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']);
} }
function mod_cycle($board, $uncycle, $post) {
global $config;
if (!openBoard($board))
error($config['error']['noboard']);
if (!hasPermission($config['mod']['cycle'], $board))
error($config['error']['noaccess']);
$query = prepare(sprintf('UPDATE ``posts_%s`` SET `cycle` = :cycle WHERE `id` = :id AND `thread` IS NULL', $board));
$query->bindValue(':id', $post);
$query->bindValue(':cycle', $uncycle ? 0 : 1);
$query->execute() or error(db_error($query));
if ($query->rowCount()) {
modLog(($uncycle ? 'Made not cyclical' : 'Made cyclical') . " thread #{$post}");
buildThread($post);
buildIndex();
}
header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']);
}
function mod_bumplock($board, $unbumplock, $post) { function mod_bumplock($board, $unbumplock, $post) {
global $config; global $config;

7
install.php

@ -1,7 +1,7 @@
<?php <?php
// Installation/upgrade file // Installation/upgrade file
define('VERSION', '5.1.1'); define('VERSION', '5.1.2');
require 'inc/functions.php'; require 'inc/functions.php';
@ -570,6 +570,11 @@ if (file_exists($config['has_installed'])) {
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `u_pages` (`name`,`board`) UNIQUE KEY `u_pages` (`name`,`board`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;') or error(db_error()); ) ENGINE=InnoDB DEFAULT CHARSET=utf8;') or error(db_error());
case '5.1.1':
foreach ($boards as &$board) {
query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error());
}
case false: case false:
// TODO: enhance Tinyboard -> vichan upgrade path. // TODO: enhance Tinyboard -> vichan upgrade path.
query("CREATE TABLE IF NOT EXISTS ``search_queries`` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error()); query("CREATE TABLE IF NOT EXISTS ``search_queries`` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error());

1
mod.php

@ -82,6 +82,7 @@ $pages = array(
'/(\%b)/deletebyip/(\d+)(/global)?' => 'secure deletebyip', // delete all posts by IP address '/(\%b)/deletebyip/(\d+)(/global)?' => 'secure deletebyip', // delete all posts by IP address
'/(\%b)/(un)?lock/(\d+)' => 'secure lock', // lock thread '/(\%b)/(un)?lock/(\d+)' => 'secure lock', // lock thread
'/(\%b)/(un)?sticky/(\d+)' => 'secure sticky', // sticky thread '/(\%b)/(un)?sticky/(\d+)' => 'secure sticky', // sticky thread
'/(\%b)/(un)?cycle/(\d+)' => 'secure cycle', // cycle thread
'/(\%b)/bump(un)?lock/(\d+)' => 'secure bumplock', // "bumplock" thread '/(\%b)/bump(un)?lock/(\d+)' => 'secure bumplock', // "bumplock" thread
'/themes' => 'themes_list', // manage themes '/themes' => 'themes_list', // manage themes

11
post.php

@ -265,7 +265,7 @@ if (isset($_POST['delete'])) {
//Check if thread exists //Check if thread exists
if (!$post['op']) { if (!$post['op']) {
$query = prepare(sprintf("SELECT `sticky`,`locked`,`sage`,`slug` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL LIMIT 1", $board['uri'])); $query = prepare(sprintf("SELECT `sticky`,`locked`,`cycle`,`sage`,`slug` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL LIMIT 1", $board['uri']));
$query->bindValue(':id', $post['thread'], PDO::PARAM_INT); $query->bindValue(':id', $post['thread'], PDO::PARAM_INT);
$query->execute() or error(db_error()); $query->execute() or error(db_error());
@ -867,6 +867,15 @@ if (isset($_POST['delete'])) {
$post['slug'] = slugify($post); $post['slug'] = slugify($post);
insertFloodPost($post); insertFloodPost($post);
// Handle cyclical threads
if (!$post['op'] && isset($thread['cycle']) && $thread['cycle']) {
// Query is a bit weird due to "This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'" (MariaDB Ver 15.1 Distrib 10.0.17-MariaDB, for Linux (x86_64))
$query = prepare(sprintf('DELETE FROM ``posts_%s`` WHERE `thread` = :thread AND `id` NOT IN (SELECT `id` FROM (SELECT `id` FROM ``posts_%s`` WHERE `thread` = :thread ORDER BY `id` DESC LIMIT :limit) i)', $board['uri'], $board['uri']));
$query->bindValue(':thread', $post['thread']);
$query->bindValue(':limit', $config['cycle_limit'], PDO::PARAM_INT);
$query->execute() or error(db_error($query));
}
if (isset($post['antispam_hash'])) { if (isset($post['antispam_hash'])) {
incrementSpamHash($post['antispam_hash']); incrementSpamHash($post['antispam_hash']);

8
templates/post/post_controls.html

@ -41,7 +41,6 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if mod|hasPermission(config.mod.move, board.uri) %} {% if mod|hasPermission(config.mod.move, board.uri) %}
{% if not post.thread %} {% if not post.thread %}
<a title="{% trans %}Move thread to another board{% endtrans %}" href="?/{{ board.dir }}move/{{ post.id }}">{{ config.mod.link_move }}</a>&nbsp; <a title="{% trans %}Move thread to another board{% endtrans %}" href="?/{{ board.dir }}move/{{ post.id }}">{{ config.mod.link_move }}</a>&nbsp;
@ -49,6 +48,13 @@
<a title="{% trans %}Move reply to another board{% endtrans %}" href="?/{{ board.dir }}move_reply/{{ post.id }}">{{ config.mod.link_move }}</a>&nbsp; <a title="{% trans %}Move reply to another board{% endtrans %}" href="?/{{ board.dir }}move_reply/{{ post.id }}">{{ config.mod.link_move }}</a>&nbsp;
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if mod|hasPermission(config.mod.cycle, board.uri) %}
{% if post.cycle %}
<a title="{% trans %}Make thread not cycle{% endtrans %}" href="?/{{ secure_link(board.dir ~ 'uncycle/' ~ post.id) }}">{{ config.mod.link_uncycle }}</a>&nbsp;
{% else %}
<a title="{% trans %}Make thread cycle{% endtrans %}" href="?/{{ secure_link(board.dir ~ 'cycle/' ~ post.id) }}">{{ config.mod.link_cycle }}</a>&nbsp;
{% endif %}
{% endif %}
{% if mod|hasPermission(config.mod.editpost, board.uri) %} {% if mod|hasPermission(config.mod.editpost, board.uri) %}
<a title="{% trans %}Edit post{% endtrans %}" href="?/{{ board.dir }}edit{% if config.mod.raw_html_default %}_raw{% endif %}/{{ post.id }}">{{ config.mod.link_editpost }}</a>&nbsp; <a title="{% trans %}Edit post{% endtrans %}" href="?/{{ board.dir }}edit{% if config.mod.raw_html_default %}_raw{% endif %}/{{ post.id }}">{{ config.mod.link_editpost }}</a>&nbsp;
{% endif %} {% endif %}

13
templates/post_thread.html

@ -19,25 +19,32 @@
<a class="post_no" onclick="citeReply({{ post.id }})" href="{% if isnoko50 %}{{ post.link('q', '50') }}{% else %}{{ post.link('q') }}{% endif %}">{{ post.id }}</a> <a class="post_no" onclick="citeReply({{ post.id }})" href="{% if isnoko50 %}{{ post.link('q', '50') }}{% else %}{{ post.link('q') }}{% endif %}">{{ post.id }}</a>
{% if post.sticky %} {% if post.sticky %}
{% if config.font_awesome %} {% if config.font_awesome %}
<i class="fa fa-thumb-tack"></i> <i class="fa fa-thumb-tack" title="Sticky"></i>
{% else %} {% else %}
<img class="icon" title="Sticky" src="{{ config.image_sticky }}" alt="Sticky" /> <img class="icon" title="Sticky" src="{{ config.image_sticky }}" alt="Sticky" />
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if post.locked %} {% if post.locked %}
{% if config.font_awesome %} {% if config.font_awesome %}
<i class="fa fa-lock"></i> <i class="fa fa-lock" title="Locked"></i>
{% else %} {% else %}
<img class="icon" title="Locked" src="{{ config.image_locked }}" alt="Locked" /> <img class="icon" title="Locked" src="{{ config.image_locked }}" alt="Locked" />
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if post.bumplocked and (config.mod.view_bumplock < 0 or (post.mod and post.mod|hasPermission(config.mod.view_bumplock, board.uri))) %} {% if post.bumplocked and (config.mod.view_bumplock < 0 or (post.mod and post.mod|hasPermission(config.mod.view_bumplock, board.uri))) %}
{% if config.font_awesome %} {% if config.font_awesome %}
<i class="fa fa-anchor"></i> <i class="fa fa-anchor" title="Bumplocked"></i>
{% else %} {% else %}
<img class="icon" title="Bumplocked" src="{{ config.image_bumplocked }}" alt="Bumplocked" /> <img class="icon" title="Bumplocked" src="{{ config.image_bumplocked }}" alt="Bumplocked" />
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if post.cycle %}
{% if config.font_awesome %}
<i class="fa fa-refresh" title="Cyclical"></i>
{% else %}
<img class="icon" title="Cyclical" src="{{ config.image_sticky }}" alt="Cyclical" />
{% endif %}
{% endif %}
{% if index %} {% if index %}
<a href="{{ post.root }}{{ board.dir }}{{ config.dir.res }}{{ link_for(post) }}">[{% trans %}Reply{% endtrans %}]</a> <a href="{{ post.root }}{{ board.dir }}{{ config.dir.res }}{{ link_for(post) }}">[{% trans %}Reply{% endtrans %}]</a>
{% endif %} {% endif %}

1
templates/posts.sql

@ -17,6 +17,7 @@ CREATE TABLE IF NOT EXISTS ``posts_{{ board }}`` (
`ip` varchar(39) CHARACTER SET ascii NOT NULL, `ip` varchar(39) CHARACTER SET ascii NOT NULL,
`sticky` int(1) NOT NULL, `sticky` int(1) NOT NULL,
`locked` int(1) NOT NULL, `locked` int(1) NOT NULL,
`cycle` int(1) NOT NULL,
`sage` int(1) NOT NULL, `sage` int(1) NOT NULL,
`embed` text, `embed` text,
`slug` varchar(256) DEFAULT NULL, `slug` varchar(256) DEFAULT NULL,

Loading…
Cancel
Save