diff --git a/js/catalog-link.js b/js/catalog-link.js
index 05ee9efb..a98078f7 100644
--- a/js/catalog-link.js
+++ b/js/catalog-link.js
@@ -12,47 +12,51 @@
* $config['additional_javascript'][] = 'js/catalog-link.js';
*/
-function catalog() {
-var board = $("input[name='board']");
+(function($) {
+var catalog = function() {
+ var board = $('input[name="board"]');
-var catalog_url = configRoot + board.first().val() + "/catalog.html";
+ if (!board.length) {
+ return;
+ }
-var pages = document.getElementsByClassName('pages')[0];
-var bottom = document.getElementsByClassName('boardlist bottom')[0]
-var subtitle = document.getElementsByClassName('subtitle')[0];
+ var catalog_url = configRoot + board.first().val() + '/catalog.html';
-var link = document.createElement('a');
-link.href = catalog_url;
+ var pages = $('.pages');
+ var bottom = $('.boardlist.bottom');
+ var subtitle = $('.subtitle');
-if (pages) {
- link.textContent = _('Catalog');
- link.style.color = '#F10000';
- link.style.padding = '4px';
- link.style.paddingLeft = '9px';
- link.style.borderLeft = '1px solid'
- link.style.borderLeftColor = '#A8A8A8';
- link.style.textDecoration = "underline";
+ var link = $('')
+ .attr('href', catalog_url);
- pages.appendChild(link)
-}
-else {
- link.textContent = '['+_('Catalog')+']';
- link.style.paddingLeft = '10px';
- link.style.textDecoration = "underline";
- document.body.insertBefore(link, bottom);
+ if (pages.length) {
+ link.text(_('Catalog'))
+ .css({
+ color: '#F10000',
+ padding: '4px',
+ textDecoration: 'underline',
+ display: 'table-cell'
+ });
+ link.insertAfter(pages);
+ } else if (bottom.length) {
+ link.text('['+_('Catalog')+']')
+ .css({
+ paddingLeft: '10px',
+ textDecoration: 'underline'
+ });
+ link.insertBefore(bottom);
+ }
+
+ if (subtitle.length) {
+ subtitle.append('
');
+ $('')
+ .text(_('Catalog'))
+ .attr('href', catalog_url)
+ .appendTo(subtitle);
+ }
}
-if (subtitle) {
- var link2 = document.createElement('a');
- link2.textContent = _('Catalog');
- link2.href = catalog_url;
-
- var br = document.createElement('br');
- subtitle.appendChild(br);
- subtitle.appendChild(link2);
-}
-}
-
-if (active_page == 'thread' || active_page == 'index') {
+if (active_page == 'thread' || active_page == 'index' || active_page == 'ukko') {
$(document).ready(catalog);
}
+})(jQuery);
diff --git a/templates/themes/catalog/catalog.html b/templates/themes/catalog/catalog.html
index 92969b00..5ee9fdec 100644
--- a/templates/themes/catalog/catalog.html
+++ b/templates/themes/catalog/catalog.html
@@ -9,7 +9,7 @@
{% include 'header.html' %}
{{ settings.title }}
-
+
{{ boardlist.top }}
@@ -49,6 +49,7 @@
data-reply="{{ post.reply_count }}"
data-bump="{{ post.bump }}"
data-time="{{ post.time }}"
+ data-board="{{ post.board }}"
>
diff --git a/templates/themes/catalog/info.php b/templates/themes/catalog/info.php
index c20a0ca3..e2b13307 100644
--- a/templates/themes/catalog/info.php
+++ b/templates/themes/catalog/info.php
@@ -1,27 +1,27 @@
'Title',
'name' => 'title',
'type' => 'text',
'default' => 'Catalog'
);
-
+
$__boards = listBoards();
$__default_boards = Array();
foreach ($__boards as $__board)
$__default_boards[] = $__board['uri'];
-
+
$theme['config'][] = Array(
'title' => 'Included boards',
'name' => 'boards',
@@ -29,7 +29,7 @@
'comment' => '(space seperated)',
'default' => implode(' ', $__default_boards)
);
-
+
$theme['config'][] = Array(
'title' => 'Update on new posts',
'name' => 'update_on_posts',
@@ -38,14 +38,22 @@
'comment' => 'Without this checked, the catalog only updates on new threads.'
);
- $theme['config'][] = Array(
- 'title' => 'Use tooltipster',
- 'name' => 'use_tooltipster',
- 'type' => 'checkbox',
- 'default' => true,
- 'comment' => 'Check this if you wish to show a nice tooltip with info about the thread on mouse over.'
- );
+ $theme['config'][] = Array(
+ 'title' => 'Enable Ukko catalog',
+ 'name' => 'enable_ukko',
+ 'type' => 'checkbox',
+ 'default' => false,
+ 'comment' => 'Enable catalog for the Ukko theme. This requires the Ukko theme to be enabled.'
+ );
+ $theme['config'][] = Array(
+ 'title' => 'Use tooltipster',
+ 'name' => 'use_tooltipster',
+ 'type' => 'checkbox',
+ 'default' => true,
+ 'comment' => 'Check this if you wish to show a nice tooltip with info about the thread on mouse over.'
+ );
// Unique function name for building everything
$theme['build_function'] = 'catalog_build';
+
diff --git a/templates/themes/catalog/theme.php b/templates/themes/catalog/theme.php
index 34b28e48..9ecdb9d1 100644
--- a/templates/themes/catalog/theme.php
+++ b/templates/themes/catalog/theme.php
@@ -1,68 +1,144 @@
build($settings, $board);
+ } else {
+ $b->build($board);
}
}
- } elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') || ($settings['update_on_posts'] && $action == 'post-delete') && in_array($board, $boards)) {
- $b = new Catalog();
-
+ } elseif (in_array($board, $boards) &&
+ $action == 'post-thread' ||
+ ($settings['update_on_posts'] && $action == 'post') ||
+ ($settings['update_on_posts'] && $action == 'post-delete'))
+ {
if ($config['smart_build']) {
file_unlink($config['dir']['home'] . $board . '/catalog.html');
- }
- else {
- $b->build($settings, $board);
+ } else {
+ $b->build($board);
}
}
+
+ // FIXME: Check that Ukko is actually enabled
+ if ($settings['enable_ukko'] && (
+ $action === 'all' || $action === 'post' ||
+ $action === 'post-thread' || $action === 'post-delete'))
+ {
+ $b->buildUkko();
+ }
}
-
+
// Wrap functions in a class so they don't interfere with normal Tinyboard operations
class Catalog {
- public function build($settings, $board_name) {
- global $config, $board;
+ private $settings;
+ // Cache for threads from boards that have already been processed
+ private $threadsCache = array();
- if ($board['uri'] != $board_name) {
- if (!openBoard($board_name)) {
- error(sprintf(_("Board %s doesn't exist"), $board_name));
+ public function __construct($settings) {
+ $this->settings = $settings;
+ }
+
+ /**
+ * Build and save the HTML of the catalog for the Ukko theme
+ */
+ public function buildUkko() {
+ global $config;
+
+ $ukkoSettings = themeSettings('ukko');
+ $queries = array();
+ $threads = array();
+
+ $exclusions = explode(' ', $ukkoSettings['exclude']);
+ $boards = array_diff(listBoards(true), $exclusions);
+
+ foreach ($boards as $b) {
+ if (array_key_exists($b, $this->threadsCache)) {
+ $threads = array_merge($threads, $this->threadsCache[$b]);
+ } else {
+ $queries[] = $this->buildThreadsQuery($b);
}
}
-
- $recent_images = array();
- $recent_posts = array();
- $stats = array();
-
- $query = query(sprintf("SELECT *, `id` AS `thread_id`,
- (SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `thread` = `thread_id`) AS `reply_count`,
- (SELECT SUM(`num_files`) FROM ``posts_%s`` WHERE `thread` = `thread_id` AND `num_files` IS NOT NULL) AS `image_count`,
- '%s' AS `board` FROM ``posts_%s`` WHERE `thread` IS NULL ORDER BY `bump` DESC",
- $board_name, $board_name, $board_name, $board_name, $board_name)) or error(db_error());
-
- while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
+
+ // Fetch threads from boards that haven't beenp processed yet
+ if (!empty($queries)) {
+ $sql = implode(' UNION ALL ', $queries);
+ $res = query($sql) or error(db_error());
+ $threads = array_merge($threads, $res->fetchAll(PDO::FETCH_ASSOC));
+ }
+
+ // Sort in bump order
+ usort($threads, function($a, $b) {
+ return strcmp($b['bump'], $a['bump']);
+ });
+ // Generate data for the template
+ $recent_posts = $this->generateRecentPosts($threads);
+
+ $this->saveForBoard($ukkoSettings['uri'], $recent_posts,
+ $config['root'] . $ukkoSettings['uri']);
+ }
+
+ /**
+ * Build and save the HTML of the catalog for the given board
+ */
+ public function build($board_name) {
+ if (!openBoard($board_name)) {
+ error(sprintf(_("Board %s doesn't exist"), $post['board']));
+ }
+
+ if (array_key_exists($board_name, $this->threadsCache)) {
+ $threads = $this->threadsCache[$board_name];
+ } else {
+ $sql = $this->buildThreadsQuery($board_name);
+ $query = query($sql . ' ORDER BY `bump` DESC') or error(db_error());
+ $threads = $query->fetchAll(PDO::FETCH_ASSOC);
+ // Save for posterity
+ $this->threadsCache[$board_name] = $threads;
+ }
+
+ // Generate data for the template
+ $recent_posts = $this->generateRecentPosts($threads);
+
+ $this->saveForBoard($board_name, $recent_posts);
+ }
+
+ private function buildThreadsQuery($board) {
+ $sql = "SELECT *, `id` AS `thread_id`, " .
+ "(SELECT COUNT(`id`) FROM ``posts_$board`` WHERE `thread` = `thread_id`) AS `reply_count`, " .
+ "(SELECT SUM(`num_files`) FROM ``posts_$board`` WHERE `thread` = `thread_id` AND `num_files` IS NOT NULL) AS `image_count`, " .
+ "'$board' AS `board` FROM ``posts_$board`` WHERE `thread` IS NULL";
+
+ return $sql;
+ }
+
+ private function generateRecentPosts($threads) {
+ global $config, $board;
+
+ $posts = array();
+ foreach ($threads as $post) {
+ if ($board['uri'] !== $post['board']) {
+ openBoard($post['board']);
+ }
+
$post['link'] = $config['root'] . $board['dir'] . $config['dir']['res'] . link_for($post);
$post['board_name'] = $board['name'];
if ($post['embed'] && preg_match('/^https?:\/\/(\w+\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9\-_]{10,11})(&.+)?$/i', $post['embed'], $matches)) {
$post['youtube'] = $matches[2];
- }
+ }
if (isset($post['files']) && $post['files']) {
$files = json_decode($post['files']);
@@ -71,45 +147,58 @@
if ($files[0]->file == 'deleted') {
if (count($files) > 1) {
foreach ($files as $file) {
- if (($file == $files[0]) || ($file->file == 'deleted')) continue;
+ if (($file == $files[0]) || ($file->file == 'deleted'))
+ continue;
$post['file'] = $config['uri_thumb'] . $file->thumb;
}
- if (empty($post['file'])) $post['file'] = $config['image_deleted'];
- }
- else {
+ if (empty($post['file']))
+ $post['file'] = $config['image_deleted'];
+ } else {
$post['file'] = $config['image_deleted'];
}
- }
- else if($files[0]->thumb == 'spoiler') {
+ } else if($files[0]->thumb == 'spoiler') {
$post['file'] = '/' . $config['spoiler_image'];
- }
- else {
+ } else {
$post['file'] = $config['uri_thumb'] . $files[0]->thumb;
}
}
}
- if (empty($post['image_count'])) $post['image_count'] = 0;
- $recent_posts[] = $post;
- }
-
- $required_scripts = array('js/jquery.min.js', 'js/jquery.mixitup.min.js', 'js/catalog.js');
+ if (empty($post['image_count']))
+ $post['image_count'] = 0;
+ $posts[] = $post;
+ }
+
+ return $posts;
+ }
+
+ private function saveForBoard($board_name, $recent_posts, $board_link = null) {
+ global $board, $config;
+
+ if ($board_link === null) {
+ $board_link = $config['root'] . $board['dir'];
+ }
+
+ $required_scripts = array('js/jquery.min.js', 'js/jquery.mixitup.min.js',
+ 'js/catalog.js');
+
+ // Include scripts that haven't been yet included
foreach($required_scripts as $i => $s) {
if (!in_array($s, $config['additional_javascript']))
$config['additional_javascript'][] = $s;
}
file_write($config['dir']['home'] . $board_name . '/catalog.html', Element('themes/catalog/catalog.html', Array(
- 'settings' => $settings,
+ 'settings' => $this->settings,
'config' => $config,
'boardlist' => createBoardlist(),
- 'recent_images' => $recent_images,
+ 'recent_images' => array(),
'recent_posts' => $recent_posts,
- 'stats' => $stats,
+ 'stats' => array(),
'board' => $board_name,
- 'link' => $config['root'] . $board['dir']
+ 'link' => $board_link
)));
}
- };
+ }
diff --git a/templates/themes/ukko/theme.php b/templates/themes/ukko/theme.php
index d6fc303c..05525299 100644
--- a/templates/themes/ukko/theme.php
+++ b/templates/themes/ukko/theme.php
@@ -29,6 +29,7 @@
$overflow = array();
$board = array(
'url' => $this->settings['uri'],
+ 'uri' => $this->settings['uri'],
'name' => $this->settings['title'],
'title' => sprintf($this->settings['subtitle'], $this->settings['thread_limit'])
);