summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Łabanowski <marcin@6irc.net>2013-01-28 13:29:21 +0100
committerMarcin Łabanowski <marcin@6irc.net>2013-01-28 13:29:21 +0100
commitd1bd4e1f7bb67eb863f4fd4233720e6e9baea8d1 (patch)
tree880263a122e50baa20cb6b22a9b4343cd0b456af
parente6b9bad788a6d9ae5f203b999925b9368a77536c (diff)
parentfd33e9eba1e72fd4ee5f064944e9592be66c12c1 (diff)
Merge branch 'master' of https://github.com/savetheinternet/Tinyboard
-rw-r--r--inc/cache.php23
-rw-r--r--inc/config.php6
-rw-r--r--inc/functions.php47
-rw-r--r--inc/mod/pages.php10
-rw-r--r--js/toggle-locked-threads.js63
-rw-r--r--templates/mod/dashboard.html4
6 files changed, 129 insertions, 24 deletions
diff --git a/inc/cache.php b/inc/cache.php
index 89ca865c..849748d4 100644
--- a/inc/cache.php
+++ b/inc/cache.php
@@ -19,6 +19,14 @@ class Cache {
self::$cache = new Memcached();
self::$cache->addServers($config['cache']['memcached']);
break;
+ case 'redis':
+ self::$cache = new Redis();
+ self::$cache->connect($config['cache']['redis'][0], $config['cache']['redis'][1]);
+ if ($config['cache']['redis'][2]) {
+ self::$cache->auth($config['cache']['redis'][2]);
+ }
+ self::$cache->select($config['cache']['redis'][3]) or die('cache select failure');
+ break;
case 'php':
self::$cache = array();
break;
@@ -45,6 +53,11 @@ class Cache {
case 'php':
$data = isset(self::$cache[$key]) ? self::$cache[$key] : false;
break;
+ case 'redis':
+ if (!self::$cache)
+ self::init();
+ $data = json_decode(self::$cache->get($key), true);
+ break;
}
// debug
@@ -68,6 +81,11 @@ class Cache {
self::init();
self::$cache->set($key, $value, $expires);
break;
+ case 'redis':
+ if (!self::$cache)
+ self::init();
+ self::$cache->setex($key, $expires, json_encode($value));
+ break;
case 'apc':
apc_store($key, $value, $expires);
break;
@@ -86,6 +104,7 @@ class Cache {
switch ($config['cache']['enabled']) {
case 'memcached':
+ case 'redis':
if (!self::$cache)
self::init();
self::$cache->delete($key);
@@ -114,6 +133,10 @@ class Cache {
case 'php':
self::$cache[$key] = array();
break;
+ case 'redis':
+ if (!self::$cache)
+ self::init();
+ return self::$cache->flushDB();
}
return false;
diff --git a/inc/config.php b/inc/config.php
index d47ab59f..913a5686 100644
--- a/inc/config.php
+++ b/inc/config.php
@@ -91,6 +91,7 @@
$config['cache']['enabled'] = false;
// $config['cache']['enabled'] = 'memcached';
+ // $config['cache']['enabled'] = 'redis';
// $config['cache']['enabled'] = 'apc';
// $config['cache']['enabled'] = 'xcache';
@@ -104,6 +105,11 @@
$config['cache']['memcached'] = array(
array('localhost', 11211)
);
+
+ // Redis server to use. Location, port, password, database id.
+ // Note that Tinyboard may clear the database at times, so you may want to pick a
+ // database id just for Tinyboard to use.
+ $config['cache']['redis'] = array('localhost', 6379, '', 1);
/*
* ====================
diff --git a/inc/functions.php b/inc/functions.php
index 8490fac6..5cf539ce 100644
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -974,16 +974,33 @@ function index($page, $mod=false) {
$th['sticky'], $th['locked'], $th['sage'], $th['embed'], $mod ? '?/' : $config['root'], $mod
);
- if (!$config['cache']['enabled'] || !$replies = cache::get("thread_index_{$board['uri']}_{$th['id']}")) {
+ if ($config['cache']['enabled'] && $cached = cache::get("thread_index_{$board['uri']}_{$th['id']}")) {
+ $replies = $cached['replies'];
+ $omitted = $cached['omitted'];
+ } else {
$posts = prepare(sprintf("SELECT * FROM `posts_%s` WHERE `thread` = :id ORDER BY `id` DESC LIMIT :limit", $board['uri']));
$posts->bindValue(':id', $th['id']);
$posts->bindValue(':limit', ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']), PDO::PARAM_INT);
$posts->execute() or error(db_error($posts));
-
- $replies = $posts->fetchAll(PDO::FETCH_ASSOC);
+
+ $replies = array_reverse($posts->fetchAll(PDO::FETCH_ASSOC));
+
+ if (count($replies) == ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview'])) {
+ $count = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM `posts_%s` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM `posts_%s` WHERE `file` IS NOT NULL AND `thread` = :thread", $board['uri'], $board['uri']));
+ $count->bindValue(':thread', $th['id'], PDO::PARAM_INT);
+ $count->execute() or error(db_error($count));
+ $count = $count->fetchAll(PDO::FETCH_COLUMN);
+
+ $omitted = array('post_count' => $count[0], 'image_count' => $count[1]);
+ } else {
+ $omitted = false;
+ }
if ($config['cache']['enabled'])
- cache::set("thread_index_{$board['uri']}_{$th['id']}", $replies);
+ cache::set("thread_index_{$board['uri']}_{$th['id']}", array(
+ 'replies' => $replies,
+ 'omitted' => $omitted,
+ ));
}
$num_images = 0;
@@ -998,26 +1015,11 @@ function index($page, $mod=false) {
);
}
- $post_count = count($replies); // $posts->rowCount()
-
- if ($post_count == ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview'])) {
- // Yeah, using two cache objects for one thread seems a little inefficient. This code is messy and dumb; please clean it up if you can.
- if (!$config['cache']['enabled'] || !$count = cache::get("thread_index_{$board['uri']}_{$th['id']}_omitted")) {
- $count = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM `posts_%s` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM `posts_%s` WHERE `file` IS NOT NULL AND `thread` = :thread", $board['uri'], $board['uri']));
- $count->bindValue(':thread', $th['id'], PDO::PARAM_INT);
- $count->execute() or error(db_error($count));
- $count = $count->fetchAll(PDO::FETCH_COLUMN);
-
- if ($config['cache']['enabled'])
- cache::set("thread_index_{$board['uri']}_{$th['id']}_omitted", $count);
- }
-
- $thread->omitted = $count[0] - ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']);
- $thread->omitted_images = $count[1] - $num_images;
+ if ($omitted) {
+ $thread->omitted = $omitted['post_count'] - ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']);
+ $thread->omitted_images = $omitted['image_count'] - $num_images;
}
- $thread->posts = array_reverse($thread->posts);
-
$body .= $thread->build(true);
}
@@ -1505,7 +1507,6 @@ function buildThread($id, $return=false, $mod=false) {
if ($config['cache']['enabled'] && !$mod) {
// Clear cache
cache::delete("thread_index_{$board['uri']}_{$id}");
- cache::delete("thread_index_{$board['uri']}_{$id}_omitted");
cache::delete("thread_{$board['uri']}_{$id}");
}
diff --git a/inc/mod/pages.php b/inc/mod/pages.php
index f6ac3fc4..34945b08 100644
--- a/inc/mod/pages.php
+++ b/inc/mod/pages.php
@@ -209,6 +209,8 @@ function mod_edit_board($boardName) {
$query->bindValue(':title', $_POST['title']);
$query->bindValue(':subtitle', $_POST['subtitle']);
$query->execute() or error(db_error($query));
+
+ modLog('Edited board information for ' . sprintf($config['board_abbreviation'], $board['uri']), false);
}
if ($config['cache']['enabled']) {
@@ -864,6 +866,8 @@ function mod_move($originBoard, $postID) {
}
}
+ modLog("Moved thread #${postID} to " . sprintf($config['board_abbreviation'], $targetBoard) . " (#${newID})", $originBoard);
+
// build new hread
buildThread($newID);
buildIndex();
@@ -1019,8 +1023,12 @@ function mod_edit_post($board, $edit_raw_html, $postID) {
$query->bindValue(':body', $_POST['body']);
$query->execute() or error(db_error($query));
- if (!$edit_raw_html)
+ if ($edit_raw_html) {
+ modLog("Edited raw HTML of post #{$postID}");
+ } else {
+ modLog("Edited post #{$postID}");
rebuildPost($postID);
+ }
buildIndex();
diff --git a/js/toggle-locked-threads.js b/js/toggle-locked-threads.js
new file mode 100644
index 00000000..50c44eda
--- /dev/null
+++ b/js/toggle-locked-threads.js
@@ -0,0 +1,63 @@
+/*
+ * toggle-locked-threads.js
+ *
+ * Released under the MIT license
+ * Copyright (c) 2012 Michael Save <savetheinternet@tinyboard.org>
+ *
+ * Usage:
+ * $config['additional_javascript'][] = 'js/jquery.min.js';
+ * $config['additional_javascript'][] = 'js/toggle-locked-threads.js';
+ *
+ */
+
+$(document).ready(function(){
+ if($('div.banner').length != 0)
+ return; // not index
+
+ var hide_locked_threads = localStorage['hidelockedthreads'] ? true : false;
+
+ $('<style type="text/css"> img.hidden{ opacity: 0.1; background: grey; border: 1px solid #000; } </style>').appendTo($('head'));
+
+ var hideLockedThread = function($thread) {
+ $thread
+ .hide()
+ .addClass('hidden');
+ };
+
+ var restoreLockedThread = function($thread) {
+ $thread
+ .show()
+ .removeClass('hidden');
+ };
+
+ var getThreadFromIcon = function($icon) {
+ return $icon.parent().parent().parent()
+ };
+
+ $('hr:first').before('<div id="toggle-locked-threads" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
+ $('div#toggle-locked-threads a')
+ .text((hide_locked_threads ? 'Show' : 'Hide') + ' locked threads')
+ .click(function() {
+ hide_locked_threads = !hide_locked_threads;
+ if (hide_locked_threads) {
+ $('img.icon[title="Locked"]').each(function() {
+ hideLockedThread(getThreadFromIcon($(this)));
+ });
+ localStorage.hidelockedthreads = true;
+ } else {
+ $('img.icon[title="Locked"]').each(function() {
+ restoreLockedThread(getThreadFromIcon($(this)));
+ });
+ delete localStorage.hidelockedthreads;
+ }
+
+ $(this).text((hide_locked_threads ? 'Show' : 'Hide') + ' locked threads')
+ });
+
+ if (hide_locked_threads) {
+ $('img.icon[title="Locked"]').each(function() {
+ hideLockedThread(getThreadFromIcon($(this)));
+ });
+ }
+});
+
diff --git a/templates/mod/dashboard.html b/templates/mod/dashboard.html
index 04da9e70..2f0b03ad 100644
--- a/templates/mod/dashboard.html
+++ b/templates/mod/dashboard.html
@@ -121,6 +121,10 @@
<legend>{% trans 'Debug' %}</legend>
<ul>
<li><a href="?/debug/antispam">{% trans 'Anti-spam' %}</a></li>
+ <li><a href="?/debug/recent">{% trans 'Recent posts' %}</a></li>
+ {% if mod|hasPermission(config.mod.debug_sql) %}
+ <li><a href="?/debug/sql">{% trans 'SQL' %}</a></li>
+ {% endif %}
</ul>
</fieldset>
{% endif %}