From 817e6973a5073230e9e2dd5a1f665a4798b09924 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sat, 16 Aug 2025 12:01:22 +0200
Subject: [PATCH 01/30] Added canonical link to separate page
---
imcger/recenttopicsng/controller/page_controller.php | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/imcger/recenttopicsng/controller/page_controller.php b/imcger/recenttopicsng/controller/page_controller.php
index fca8abe..b8ff751 100644
--- a/imcger/recenttopicsng/controller/page_controller.php
+++ b/imcger/recenttopicsng/controller/page_controller.php
@@ -102,8 +102,11 @@ public function display(string $page): object
'U_BREADCRUMB' => $this->helper->route('imcger_recenttopicsng_page_controller', ['page' => 'separate']),
]);
- $this->rtng_functions->display_recent_topics();
+ $this->template->assign_vars([
+ 'U_CANONICAL' => $this->helper->route('imcger_recenttopicsng_page_controller', ['page' => 'separate'], true, false, \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL),
+ ]);
+ $this->rtng_functions->display_recent_topics();
break;
// Displays the start page of phpBB
From 7b703ea11ab80456206e82e4e491dcd163fdf9b3 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sat, 16 Aug 2025 12:09:40 +0200
Subject: [PATCH 02/30] Changed db query for topic list
Only reads the topics that are necessary to load the page.
---
imcger/recenttopicsng/core/rtng_functions.php | 33 +++++++++----------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 49a19ed..6343682 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -335,7 +335,7 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
if ($total_topics_limit > 0)
{
- $result = $this->db->sql_query_limit($sql, $total_topics_limit);
+ $result = $this->db->sql_query_limit($sql, $this->topics_per_page, $rtng_start);
}
else
{
@@ -355,30 +355,27 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
while ($row = $this->db->sql_fetchrow($result))
{
- $topics_count++;
-
- if (($topics_count > $rtng_start) && ($topics_count <= ($rtng_start + $this->topics_per_page)))
- {
- $topic_list[] = $row['topic_id'];
+ $topic_list[] = $row['topic_id'];
- $rowset[$row['topic_id']] = $row;
+ $rowset[$row['topic_id']] = $row;
- if (!isset($forums[$row['forum_id']]) && $this->user->data['is_registered'] && $this->config['load_db_lastread'])
- {
- $forums[$row['forum_id']]['mark_time'] = $row['f_mark_time'];
- }
- $forums[$row['forum_id']]['topic_list'][] = $row['topic_id'];
- $forums[$row['forum_id']]['rowset'][$row['topic_id']] = & $rowset[$row['topic_id']];
+ if (!isset($forums[$row['forum_id']]) && $this->user->data['is_registered'] && $this->config['load_db_lastread'])
+ {
+ $forums[$row['forum_id']]['mark_time'] = $row['f_mark_time'];
+ }
+ $forums[$row['forum_id']]['topic_list'][] = $row['topic_id'];
+ $forums[$row['forum_id']]['rowset'][$row['topic_id']] = & $rowset[$row['topic_id']];
- if ($row['icon_id'])
- {
- $obtain_icons = true;
- }
+ if ($row['icon_id'])
+ {
+ $obtain_icons = true;
}
}
+
$this->db->sql_freeresult($result);
}
- return $topics_count;
+
+ return min($num_rows, $total_topics_limit);
}
/**
From e008426b664890428896a1b991011b6cb4c04dda Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sat, 16 Aug 2025 12:42:16 +0200
Subject: [PATCH 03/30] Query conditions adjusted
- Added required tag in number macro in
`rtng_macros.html`
- Changed var name $num_rows to $topics_count
- Improved vars for `sql_query_limit()`
---
imcger/recenttopicsng/core/rtng_functions.php | 42 ++++++++-----------
.../styles/all/template/rtng_macros.html | 2 +-
2 files changed, 18 insertions(+), 26 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 6343682..78531ec 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -179,6 +179,12 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
$forums = [];
$topic_list = [];
+ // When 0 there are no topics to display
+ if ($total_topics_limit < 1)
+ {
+ return;
+ }
+
$topics_count = $this->gettopiclist($obtain_icons, $forums, $rtng_start, $total_topics_limit, $excluded_topics, $forum_id_list, $topic_list);
// Return if there are no topics available to display.
@@ -287,15 +293,8 @@ private function getforumlist(): array
*/
private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_start, int $total_topics_limit, array $excluded_topics, array $forum_id_list, array &$topic_list): int
{
- $rtng_start = max(0, $rtng_start);
-
- if ($total_topics_limit > 0)
- {
- $rtng_start = min((int) $rtng_start, $total_topics_limit);
- }
-
- $topics_count = 0;
-
+ $rtng_start = max(0, $rtng_start);
+ $topics_count = 0;
$min_topic_level = $this->config['rtng_min_topic_level'];
// Either use the phpBB core function to get unread topics, or the custom function for default behavior
@@ -327,28 +326,20 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
$sql = $this->db->sql_build_query('SELECT', $count_sql_array);
$result = $this->db->sql_query($sql);
- $num_rows = (int) $this->db->sql_fetchfield('topic_count');
+ $topics_count = (int) $this->db->sql_fetchfield('topic_count');
$this->db->sql_freeresult($result);
//load topics list
$sql = $this->db->sql_build_query('SELECT', $sql_array);
- if ($total_topics_limit > 0)
- {
- $result = $this->db->sql_query_limit($sql, $this->topics_per_page, $rtng_start);
- }
- else
- {
- $result = $this->db->sql_query($sql);
- }
+ $rtng_start = min($total_topics_limit - 1, $rtng_start);
+ $total_select = ($rtng_start + $this->topics_per_page) > $total_topics_limit ? ($this->topics_per_page - ($rtng_start % $this->topics_per_page)) : $this->topics_per_page;
+ $result = $this->db->sql_query_limit($sql, $total_select, $rtng_start);
- if ($result != null)
- {
- $rtng_start = min($num_rows - 1 , $rtng_start);
- }
- else
+ // Return 0 topics to display
+ if ($result == false)
{
- $rtng_start = 0;
+ return 0;
}
$rowset = [];
@@ -375,7 +366,8 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
$this->db->sql_freeresult($result);
}
- return min($num_rows, $total_topics_limit);
+ // Return number of total topics counts to display
+ return min($topics_count, $total_topics_limit);
}
/**
diff --git a/imcger/recenttopicsng/styles/all/template/rtng_macros.html b/imcger/recenttopicsng/styles/all/template/rtng_macros.html
index 9b9cae0..ba6677b 100644
--- a/imcger/recenttopicsng/styles/all/template/rtng_macros.html
+++ b/imcger/recenttopicsng/styles/all/template/rtng_macros.html
@@ -39,7 +39,7 @@
(max !== null ? ' max="' ~ max ~ '"') ~
(step !== null ? ' step="' ~ step ~ '"') ~
(placeholder !== null ? ' placeholder="' ~ placeholder ~ '"')
- }}>
+ }} required>
{%- endmacro %}
{% macro text(name, value, size = null, placeholder = null, pattern = null) -%}
From 71c5e61fac794f0d84efe808ea4fde33c6efcf78 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Tue, 19 Aug 2025 19:46:56 +0200
Subject: [PATCH 04/30] Optimization of loops that adjust arrays in
rtng_functions
---
imcger/recenttopicsng/core/rtng_functions.php | 28 +++++--------------
1 file changed, 7 insertions(+), 21 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 78531ec..6165c50 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -275,16 +275,12 @@ private function getforumlist(): array
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query($sql);
- $forum_ids = [];
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- $forum_ids[] = $row['forum_id'];
- }
+ $rows = $this->db->sql_fetchrowset($result);
+ $forum_ids_disp = array_column($rows, 'forum_id');
$this->db->sql_freeresult($result);
- return array_unique($forum_ids);
+ return array_unique($forum_ids_disp);
}
}
@@ -304,17 +300,11 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
$sql_extra = ' AND ' . $this->db->sql_in_set('t.topic_id', $excluded_topics, true);
$sql_extra .= ' AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $forum_id_list, $table_alias = 't.');
$unread_topics = get_unread_topics(false, $sql_extra, '', $total_topics_limit);
- $rtng_start = min(count($unread_topics) - 1 , (int) $rtng_start);
- foreach ($unread_topics as $topic_id => $mark_time)
- {
- $topics_count++;
+ $topics_count = count($unread_topics);
+ $rtng_start = min($topics_count - 1 , $rtng_start);
- if (($topics_count > $rtng_start) && ($topics_count <= ($rtng_start + $this->topics_per_page)))
- {
- $topic_list[] = $topic_id;
- }
- }
+ $topic_list = array_slice(array_keys($unread_topics), $rtng_start, $this->topics_per_page);
}
else
{
@@ -478,12 +468,8 @@ private function get_topics_sql(array $topic_list): array
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, $this->topics_per_page);
- $rowset = [];
- while ($row = $this->db->sql_fetchrow($result))
- {
- $rowset[] = $row;
- }
+ $rowset = $this->db->sql_fetchrowset($result);
$this->db->sql_freeresult($result);
return $rowset;
From b9200d1c703ffe545fdb7d592e09d09c13b71563 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Thu, 28 Aug 2025 21:08:52 +0200
Subject: [PATCH 05/30] Template Events
- Added events to `rtng_body_site`
- Added events to `rtng_body_topbottom`
- Changed, better support for phpBB Collapsed Categories
---
imcger/recenttopicsng/config/services.yml | 2 +-
imcger/recenttopicsng/core/rtng_functions.php | 15 +------------
imcger/recenttopicsng/event/main_listener.php | 19 ++++++++++++++++-
.../styles/all/template/rtng_body_side.html | 10 ++++++---
.../all/template/rtng_body_topbottom.html | 21 +++++++++++++++----
5 files changed, 44 insertions(+), 23 deletions(-)
diff --git a/imcger/recenttopicsng/config/services.yml b/imcger/recenttopicsng/config/services.yml
index a6a3483..f228585 100644
--- a/imcger/recenttopicsng/config/services.yml
+++ b/imcger/recenttopicsng/config/services.yml
@@ -48,7 +48,6 @@ services:
- '%core.root_path%'
- '%core.php_ext%'
- '@imcger.recenttopicsng.controller_common'
- - '@?phpbb.collapsiblecategories.operator'
imcger.recenttopicsng.main_listener:
class: imcger\recenttopicsng\event\main_listener
@@ -59,6 +58,7 @@ services:
- '@language'
- '@auth'
- '@imcger.recenttopicsng.controller_common'
+ - '@?phpbb.collapsiblecategories.operator'
tags:
- { name: event.listener }
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 6165c50..9dded8c 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -29,7 +29,6 @@ class rtng_functions
protected string $root_path;
protected string $phpEx;
protected object $ctrl_common;
- private ?object $collapsable_categories; // var support extension "Collapsible Forum Categories"
private array $user_setting;
private int $topics_per_page;
private int $topics_page_number;
@@ -49,8 +48,7 @@ public function __construct
\phpbb\user $user,
$root_path,
$phpEx,
- \imcger\recenttopicsng\controller\controller_common $controller_common,
- ?\phpbb\collapsiblecategories\operator\operator $collapsable_categories = null
+ \imcger\recenttopicsng\controller\controller_common $controller_common
)
{
$this->auth = $auth;
@@ -67,7 +65,6 @@ public function __construct
$this->root_path = $root_path;
$this->phpEx = $phpEx;
$this->ctrl_common = $controller_common;
- $this->collapsable_categories = $collapsable_categories;
$this->topics_per_page = 0;
$this->topics_page_number = 0;
@@ -119,16 +116,6 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
include($this->root_path . 'includes/functions_display.' . $this->phpEx);
}
- // support for phpbb collapsable categories extension
- if (isset($this->collapsable_categories))
- {
- $fid = 'fid_rtng'; // can be any unique string to identify the collapsible element of your extension.
- $this->template->assign_vars([
- 'S_EXT_COLCAT_HIDDEN' => $this->collapsable_categories->is_collapsed($fid),
- 'U_EXT_COLCAT_COLLAPSE_URL' => $this->collapsable_categories->get_collapsible_link($fid),
- ]);
- }
-
$rtng_start = $this->request->variable($tpl_loopname . '_start', 0);
$excluded_topics = explode(',', $this->config['rtng_anti_topics']);
diff --git a/imcger/recenttopicsng/event/main_listener.php b/imcger/recenttopicsng/event/main_listener.php
index 6884711..f9d4ed6 100644
--- a/imcger/recenttopicsng/event/main_listener.php
+++ b/imcger/recenttopicsng/event/main_listener.php
@@ -23,6 +23,7 @@ class main_listener implements EventSubscriberInterface
protected object $language;
protected object $auth;
protected object $ctrl_common;
+ private ?object $collapsable_categories; // var support extension "Collapsible Forum Categories"
private array $user_setting;
public function __construct
@@ -32,7 +33,8 @@ public function __construct
\phpbb\controller\helper $helper,
\phpbb\language\language $language,
\phpbb\auth\auth $auth,
- \imcger\recenttopicsng\controller\controller_common $controller_common
+ \imcger\recenttopicsng\controller\controller_common $controller_common,
+ ?\phpbb\collapsiblecategories\operator\operator $collapsable_categories = null
)
{
$this->rtng_functions = $rtng_functions;
@@ -41,6 +43,7 @@ public function __construct
$this->language = $language;
$this->auth = $auth;
$this->ctrl_common = $controller_common;
+ $this->collapsable_categories = $collapsable_categories;
$this->user_setting = $this->ctrl_common->get_user_setting();
}
@@ -53,6 +56,7 @@ public static function getSubscribedEvents(): array
'core.index_modify_page_title' => 'display_rt',
'core.permissions' => 'add_permission',
'core.viewonline_overwrite_location' => 'viewonline_overwrite_location',
+ 'core.display_forums_before' => 'display_forums_before',
];
}
@@ -61,6 +65,19 @@ public function user_setup_after(): void
$this->language->add_lang('rtng_common', 'imcger/recenttopicsng');
}
+ public function display_forums_before(): void
+ {
+ // support for phpbb collapsable categories extension
+ if (isset($this->collapsable_categories))
+ {
+ $fid = 'fid_rtng'; // can be any unique string to identify the collapsible element of your extension.
+ $this->template->assign_block_vars('rtng_cc', [
+ 'S_FORUM_HIDDEN' => $this->collapsable_categories->is_collapsed($fid),
+ 'U_COLLAPSE_URL' => $this->collapsable_categories->get_collapsible_link($fid),
+ ]);
+ }
+ }
+
public function set_template_vars(): void
{
$this->template->assign_vars([
diff --git a/imcger/recenttopicsng/styles/all/template/rtng_body_side.html b/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
index ee2a960..c844614 100644
--- a/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
+++ b/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
@@ -16,15 +16,19 @@
-
+
{% endif %}
+ {% EVENT viewforum_body_topicrow_row_before %}
-
+ {% EVENT viewforum_body_topic_row_prepend %}
-
@@ -81,9 +88,11 @@
{% if rtng.S_TOPIC_DELETED %} {% endif %}
{% if rtng.S_TOPIC_REPORTED %}{% endif %}
+ {% EVENT topiclist_row_topic_title_after %}
{% if !S_IS_BOT %}
{{ lang('LAST_POST') }} {{ lang('POST_BY_AUTHOR') }} {% EVENT viewforum_body_last_post_author_username_prepend %} {{ rtng.LAST_POST_AUTHOR_FULL }} {% EVENT viewforum_body_last_post_author_username_append %} «
{{ rtng.LAST_POST_TIME }}
+ {% EVENT topiclist_row_topic_by_author_after %}
{% if rtng.S_POST_GLOBAL && FORUM_ID != rtng.FORUM_ID %}
{{ lang('POSTED') }} {{ lang('IN') }}
{{ rtng.FORUM_NAME }}{% endif %}
{% if rtng.REPLIES %}{{ lang('REPLIES') }}{{ lang('COLON') }} {{ rtng.REPLIES }}{% endif %}
@@ -107,8 +116,10 @@
{% endif %}
+ {% EVENT topiclist_row_prepend %}
{% if rtng.S_HAS_POLL %}{% endif %}
+ {% EVENT topiclist_row_topic_by_author_before %}
{{ lang('POST_BY_AUTHOR') }} {% EVENT viewforum_body_topic_author_username_prepend %}
{% if rtng.S_DISP_FIRST_UNREAD_POST %}
{{ rtng.FIRST_UNREAD_POST_AUTHOR_FULL }}
@@ -141,7 +152,9 @@
+ {% EVENT viewforum_body_topic_row_append %}
+ {% EVENT viewforum_body_topic_row_after %}
{% if rtng.S_LAST_ROW %}
From 450937da530b79f42cfd281de05822beba2bdc58 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Fri, 26 Sep 2025 19:46:20 +0200
Subject: [PATCH 06/30] Comments corrected during validation
- Remove null coalescing operator with no effect.
- Fixed TypeError when `getforumlist()` returns no forum
---
imcger/recenttopicsng/core/rtng_functions.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 9dded8c..d339d08 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -125,7 +125,7 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
$forum_id_list = $this->getforumlist();
// No forums to display
- if (count($forum_id_list) == 0)
+ if (empty($forum_id_list))
{
return;
}
@@ -234,7 +234,7 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
/**
* Get the forums we take our topics from
*/
- private function getforumlist(): array
+ private function getforumlist(): ?array
{
// Get the allowed forums
$forum_ary = [];
@@ -508,7 +508,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
if ($this->user_setting['user_rtng_unread_only'])
{
topic_status($row, $replies, true, $folder_img, $folder_alt, $topic_type);
- $unread_topic = ($this->user->data['user_id'] != ANONYMOUS) ?? false;
+ $unread_topic = $this->user->data['user_id'] != ANONYMOUS;
}
else
{
From ba3325ba31e0247ab0d99542e655ebfead4c4c2d Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Mon, 29 Sep 2025 21:46:43 +0200
Subject: [PATCH 07/30] Revert "Comments corrected during validation"
This reverts commit 450937da530b79f42cfd281de05822beba2bdc58.
---
imcger/recenttopicsng/core/rtng_functions.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index d339d08..9dded8c 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -125,7 +125,7 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
$forum_id_list = $this->getforumlist();
// No forums to display
- if (empty($forum_id_list))
+ if (count($forum_id_list) == 0)
{
return;
}
@@ -234,7 +234,7 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
/**
* Get the forums we take our topics from
*/
- private function getforumlist(): ?array
+ private function getforumlist(): array
{
// Get the allowed forums
$forum_ary = [];
@@ -508,7 +508,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
if ($this->user_setting['user_rtng_unread_only'])
{
topic_status($row, $replies, true, $folder_img, $folder_alt, $topic_type);
- $unread_topic = $this->user->data['user_id'] != ANONYMOUS;
+ $unread_topic = ($this->user->data['user_id'] != ANONYMOUS) ?? false;
}
else
{
From b2a98f2337c7b6e87ca6afcd64aaa3b6287585af Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Fri, 17 Oct 2025 20:48:04 +0200
Subject: [PATCH 08/30] Added vars in event
- Added vars in event `modify_tpl_ary`. `$disp_topic_title` and properties of the first unread post to `$row`.
- Update CHANGELOG.md
- Update Events.md
---
imcger/recenttopicsng/core/rtng_functions.php | 29 ++++++-
imcger/recenttopicsng/docs/CHANGELOG.md | 14 +++-
imcger/recenttopicsng/docs/Events.md | 76 ++++++++++++++++++-
3 files changed, 112 insertions(+), 7 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 4280515..9bd4798 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -570,6 +570,26 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$u_first_unread_post_author = get_username_string('profile', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
}
+ if (!empty($first_unread['post_id']) && $this->user_setting['user_rtng_disp_first_unrd_post'])
+ {
+ $disp_topic_title = 'first_unread_post';
+ }
+ else if ($this->user_setting['user_rtng_disp_last_post'])
+ {
+ $disp_topic_title = 'last_post';
+ }
+ else
+ {
+ $disp_topic_title = 'first_post';
+ }
+
+ $row['topic_first_unread_post_id'] = $first_unread['post_id'] ?? '';
+ $row['topic_first_unread_poster_id'] = $first_unread['poster_id'] ?? '';
+ $row['topic_first_unread_poster_name'] = $first_unread['username'] ?? '';
+ $row['topic_first_unread_poster_colour'] = $first_unread['user_colour'] ?? '';
+ $row['topic_first_unread_post_subject'] = $first_unread['post_subject'] ?? '';
+ $row['topic_first_unread_post_time'] = $first_unread['post_time'] ?? '';
+
$view_topic_url = append_sid("{$this->root_path}viewtopic.$this->phpEx", 't=' . $topic_id);
$view_last_post_url = append_sid("{$this->root_path}viewtopic.$this->phpEx", 'p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id']);
$view_first_unread_post_url = !empty($first_unread['post_id']) ? append_sid("{$this->root_path}viewtopic.$this->phpEx", 'p=' . $first_unread['post_id'] . '#p' . $first_unread['post_id']) : '';
@@ -631,6 +651,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
'S_UNREAD_TOPIC' => $unread_topic,
'S_DISP_FIRST_UNREAD_POST' => $this->user_setting['user_rtng_disp_first_unrd_post'] && $unread_topic,
'S_DISP_LAST_POST' => $this->user_setting['user_rtng_disp_last_post'],
+ 'S_DISP_TOPIC_TITLE' => $disp_topic_title,
'S_TOPIC_REPORTED' => $row['topic_reported'] && $this->auth->acl_get('m_report', $forum_id),
'S_TOPIC_UNAPPROVED' => $topic_unapproved,
'S_POSTS_UNAPPROVED' => $posts_unapproved,
@@ -653,11 +674,13 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
* Modify the topic data before it is assigned to the template
*
* @event imcger.recenttopicsng.modify_tpl_ary
- * @var array row Array with topic data
- * @var array tpl_ary Template block array with topic data
+ * @var string disp_topic_title Post in Topic title. first, last or first unread post
+ * @var array row Array with topic data
+ * @var array tpl_ary Template block array with topic data
* @since 1.0.0
+ * @changed 1.1.0 Variables added. $disp_topic_title and properties of the first unread post in $row
*/
- $vars = ['row', 'tpl_ary'];
+ $vars = ['disp_topic_title', 'row', 'tpl_ary'];
extract($this->dispatcher->trigger_event('imcger.recenttopicsng.modify_tpl_ary', compact($vars)));
$this->template->assign_block_vars($tpl_loopname, $tpl_ary);
diff --git a/imcger/recenttopicsng/docs/CHANGELOG.md b/imcger/recenttopicsng/docs/CHANGELOG.md
index 68854ec..6cff1f3 100644
--- a/imcger/recenttopicsng/docs/CHANGELOG.md
+++ b/imcger/recenttopicsng/docs/CHANGELOG.md
@@ -1,6 +1,18 @@
-## Changelog Recent Topics NG V1.0.1
+## Changelog Recent Topics NG V1.1.0
This is a non-exhaustive (but still near complete) changelog for Recent Topics NG 1.x including release candidate versions.
+#### Changes since V1.0.1 (xx/xx/2025)
+ - [Changed] Optimization of loops that adjust arrays in `rtng_functions`.
+ - [Changed] Only reads the topics that are necessary to load the page.
+ - [Changed] Required tag in number macro in `rtng_macros.html` added.
+ - [Changed] Var name $num_rows to $topics_count.
+ - [Changed] Improved vars for `sql_query_limit()`.
+ - [Changed] Better support for phpBB Collapsed Categories.
+ - [Feature] Added events to `rtng_body_site`
+ - [Feature] Added events to `rtng_body_topbottom`
+ - [Feature] Added canonical link to separate page.
+ - [Feature] Added vars in event `modify_tpl_ary`. `$disp_topic_title` and properties of the first unread post to `$row`.
+
#### Changes since V1.0.0 (27/09/2025)
- [Change] Removed unnecessary NCO.
- [Fixed] Ensured that the correct variable type is always returned.
diff --git a/imcger/recenttopicsng/docs/Events.md b/imcger/recenttopicsng/docs/Events.md
index da4b163..b0096d5 100644
--- a/imcger/recenttopicsng/docs/Events.md
+++ b/imcger/recenttopicsng/docs/Events.md
@@ -14,11 +14,13 @@
### `imcger.recenttopicsng.modify_tpl_ary`
* Description: Modify the topic data before it is assigned to the template
* Placement: imcger\recenttopicsng\core\rtng_functions\display_recent_topics
-* Since: 1.0.0
+* Since: 1.0.0
+* Changed: 1.1.0 Variables added. $disp_topic_title and properties of the first unread post in $row
* known listeners: /
* Arguments:
- - @var array row Array with topic data
- - @var array tpl_ary Template block array with topic data
+ - @var string disp_topic_title Post in Topic title. first, last or first unread post
+ - @var array row Array with topic data
+ - @var array tpl_ary Template block array with topic data
### `imcger.recenttopicsng.sql_pull_topics_list`
* Description: Event to modify the SQL query before the allowed topics list data is retrieved
@@ -79,3 +81,71 @@
+ \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
* Purpose: Append information to last post author username of member
* Since: 1.0.0
+
+### `forumlist_body_category_header_before`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content before the header of the category on the forum list.
+* Since: 1.1.0
+
+### `forumlist_body_category_header_row_prepend`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_side.html
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content before the header row of the category on the forum list.
+* Since: 1.1.0
+
+### `forumlist_body_category_header_row_append`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_side.html
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content after the header row of the category on the forum list.
+* Since: 1.1.0
+
+### `viewforum_body_topicrow_row_before`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content before list of topics.
+* Since: 1.1.0
+
+### `viewforum_body_topic_row_prepend`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content at the end of the topic list item.
+* Since: 1.1.0
+
+### `topiclist_row_topic_title_after`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content into topic rows (after the elements containing the topic titles)
+* Since: 1.1.0
+
+### `topiclist_row_topic_by_author_after`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content into topic rows (after the "by topic author" row)
+* Since: 1.1.0
+
+### `topiclist_row_prepend`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content into topic rows (inside the elements containing topic titles)
+* Since: 1.1.0
+
+### `topiclist_row_topic_by_author_before`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content into topic rows (before the "by topic author" row)
+* Since: 1.1.0
+
+### `viewforum_body_topic_row_append`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content at the start of the topic list item.
+* Since: 1.1.0
+
+### `viewforum_body_topic_row_after`
+* Location:
+ + \ext\imcger\recenttopicsng\styles\all\template\rtng_body_topbottom.html
+* Purpose: Add content after the topic list item.
+* Since: 1.1.0
From f5af9041758420f11d34f3378589081d944d1fee Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sat, 18 Oct 2025 22:56:59 +0200
Subject: [PATCH 09/30] Template Var S_DISP_TOPIC_TITLE replaced with
S_DISP_FIRST_POST
---
imcger/recenttopicsng/core/rtng_functions.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 9bd4798..0a23f46 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -590,6 +590,8 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$row['topic_first_unread_post_subject'] = $first_unread['post_subject'] ?? '';
$row['topic_first_unread_post_time'] = $first_unread['post_time'] ?? '';
+ $disp_unread_topic_post = $this->user_setting['user_rtng_disp_first_unrd_post'] && $unread_topic;
+
$view_topic_url = append_sid("{$this->root_path}viewtopic.$this->phpEx", 't=' . $topic_id);
$view_last_post_url = append_sid("{$this->root_path}viewtopic.$this->phpEx", 'p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id']);
$view_first_unread_post_url = !empty($first_unread['post_id']) ? append_sid("{$this->root_path}viewtopic.$this->phpEx", 'p=' . $first_unread['post_id'] . '#p' . $first_unread['post_id']) : '';
@@ -649,9 +651,9 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
'S_HAS_POLL' => $row['poll_start'] ? true : false,
'S_TOPIC_TYPE' => $row['topic_type'],
'S_UNREAD_TOPIC' => $unread_topic,
- 'S_DISP_FIRST_UNREAD_POST' => $this->user_setting['user_rtng_disp_first_unrd_post'] && $unread_topic,
- 'S_DISP_LAST_POST' => $this->user_setting['user_rtng_disp_last_post'],
- 'S_DISP_TOPIC_TITLE' => $disp_topic_title,
+ 'S_DISP_FIRST_UNREAD_POST' => $disp_unread_topic_post,
+ 'S_DISP_LAST_POST' => $this->user_setting['user_rtng_disp_last_post'] && !$disp_unread_topic_post,
+ 'S_DISP_FIRST_POST' => !$this->user_setting['user_rtng_disp_last_post'] && !$disp_unread_topic_post,
'S_TOPIC_REPORTED' => $row['topic_reported'] && $this->auth->acl_get('m_report', $forum_id),
'S_TOPIC_UNAPPROVED' => $topic_unapproved,
'S_POSTS_UNAPPROVED' => $posts_unapproved,
From e3dbd1b9c1cc1c90291c8933db86e50fbe55d2a3 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sun, 19 Oct 2025 12:30:51 +0200
Subject: [PATCH 10/30] Code optimized in `fill_template()`
---
imcger/recenttopicsng/core/rtng_functions.php | 63 ++++---------------
1 file changed, 12 insertions(+), 51 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 0a23f46..4bd9ec1 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -491,49 +491,22 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
foreach ($rowset as $row)
{
- $topic_id = $row['topic_id'];
- $forum_id = $row['forum_id'];
+ $topic_id = $row['topic_id'];
+ $forum_id = $row['forum_id'];
+ $unread_topic = false;
+ $replies = $this->content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
$s_type_switch_test = ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) ? 1 : 0;
- $replies = $this->content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
if ($row['topic_status'] == ITEM_MOVED)
{
$topic_id = $row['topic_moved_id'];
- $unread_topic = false;
}
else
{
- $unread_topic = (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]) ? true : false;
+ $unread_topic = isset($topic_tracking_info[$forum_id][$row['topic_id']]) && ($row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]);
}
- // Get folder img, topic status/type related information
- $folder_img = $folder_alt = $topic_type = '';
-
- if ($this->user_setting['user_rtng_unread_only'])
- {
- topic_status($row, $replies, true, $folder_img, $folder_alt, $topic_type);
- $unread_topic = $this->user->data['user_id'] != ANONYMOUS;
- }
- else
- {
- if (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']])
- {
- topic_status($row, $replies, true, $folder_img, $folder_alt, $topic_type);
- }
- else
- {
- topic_status($row, $replies, false, $folder_img, $folder_alt, $topic_type);
- }
-
- if (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']])
- {
- $unread_topic = true;
- }
- else
- {
- $unread_topic = false;
- }
- }
+ $disp_topic_title = $this->user_setting['user_rtng_disp_last_post'] ? 'last_post' : 'first_post';
$first_unread = [];
@@ -563,6 +536,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$first_unread = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
+ $disp_topic_title = 'first_unread_post';
$first_unread_post_author = get_username_string('username', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
$first_unread_post_author_color = get_username_string('colour', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
$first_unread_post_author_full = get_username_string('full', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
@@ -570,19 +544,6 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$u_first_unread_post_author = get_username_string('profile', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
}
- if (!empty($first_unread['post_id']) && $this->user_setting['user_rtng_disp_first_unrd_post'])
- {
- $disp_topic_title = 'first_unread_post';
- }
- else if ($this->user_setting['user_rtng_disp_last_post'])
- {
- $disp_topic_title = 'last_post';
- }
- else
- {
- $disp_topic_title = 'first_post';
- }
-
$row['topic_first_unread_post_id'] = $first_unread['post_id'] ?? '';
$row['topic_first_unread_poster_id'] = $first_unread['poster_id'] ?? '';
$row['topic_first_unread_poster_name'] = $first_unread['username'] ?? '';
@@ -590,8 +551,6 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$row['topic_first_unread_post_subject'] = $first_unread['post_subject'] ?? '';
$row['topic_first_unread_post_time'] = $first_unread['post_time'] ?? '';
- $disp_unread_topic_post = $this->user_setting['user_rtng_disp_first_unrd_post'] && $unread_topic;
-
$view_topic_url = append_sid("{$this->root_path}viewtopic.$this->phpEx", 't=' . $topic_id);
$view_last_post_url = append_sid("{$this->root_path}viewtopic.$this->phpEx", 'p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id']);
$view_first_unread_post_url = !empty($first_unread['post_id']) ? append_sid("{$this->root_path}viewtopic.$this->phpEx", 'p=' . $first_unread['post_id'] . '#p' . $first_unread['post_id']) : '';
@@ -607,6 +566,8 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$topic_icons[] = $topic_id;
}
+ // Get folder img, topic status/type related information
+ $folder_img = $folder_alt = $topic_type = '';
topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
list($topic_author, $topic_author_color, $topic_author_full, $u_topic_author, $last_post_author, $last_post_author_colour, $last_post_author_full, $u_last_post_author) = $this->getusernamestrings($row);
@@ -651,9 +612,9 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
'S_HAS_POLL' => $row['poll_start'] ? true : false,
'S_TOPIC_TYPE' => $row['topic_type'],
'S_UNREAD_TOPIC' => $unread_topic,
- 'S_DISP_FIRST_UNREAD_POST' => $disp_unread_topic_post,
- 'S_DISP_LAST_POST' => $this->user_setting['user_rtng_disp_last_post'] && !$disp_unread_topic_post,
- 'S_DISP_FIRST_POST' => !$this->user_setting['user_rtng_disp_last_post'] && !$disp_unread_topic_post,
+ 'S_DISP_FIRST_UNREAD_POST' => $disp_topic_title == 'first_unread_post',
+ 'S_DISP_LAST_POST' => $disp_topic_title == 'last_post',
+ 'S_DISP_FIRST_POST' => $disp_topic_title == 'first_post',
'S_TOPIC_REPORTED' => $row['topic_reported'] && $this->auth->acl_get('m_report', $forum_id),
'S_TOPIC_UNAPPROVED' => $topic_unapproved,
'S_POSTS_UNAPPROVED' => $posts_unapproved,
From dc1536ee3a5f71dffc1dba12517984e280653c93 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sun, 19 Oct 2025 20:33:12 +0200
Subject: [PATCH 11/30] Fixed: Don't show unread topics as unread when set show
only unread topics
---
imcger/recenttopicsng/core/rtng_functions.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 4bd9ec1..1ccfecc 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -501,6 +501,10 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
{
$topic_id = $row['topic_moved_id'];
}
+ else if ($this->user_setting['user_rtng_unread_only'])
+ {
+ $unread_topic = $this->user->data['user_id'] != ANONYMOUS;
+ }
else
{
$unread_topic = isset($topic_tracking_info[$forum_id][$row['topic_id']]) && ($row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]);
From d92e41ea86319d52b556363cbd41c1e9329b64ba Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:46:36 +0200
Subject: [PATCH 12/30] Fill event var always with first unread post data
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Changed ternäre operators to coalescing operator
- Changed ternäre operators to type-casting
---
imcger/recenttopicsng/core/rtng_functions.php | 24 +++++++++++--------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 1ccfecc..c013a61 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -514,7 +514,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$first_unread = [];
- if ($unread_topic && $this->user_setting['user_rtng_disp_first_unrd_post'])
+ if ($unread_topic)
{
// Get author, posttime, id and title of first unread post in topic
$sql_array = [
@@ -540,7 +540,11 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$first_unread = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
- $disp_topic_title = 'first_unread_post';
+ if ($this->user_setting['user_rtng_disp_first_unrd_post'])
+ {
+ $disp_topic_title = 'first_unread_post';
+ }
+
$first_unread_post_author = get_username_string('username', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
$first_unread_post_author_color = get_username_string('colour', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
$first_unread_post_author_full = get_username_string('full', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
@@ -586,12 +590,12 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
'TOPIC_AUTHOR_FULL' => $topic_author_full,
'U_TOPIC_AUTHOR' => $u_topic_author,
'FIRST_POST_TIME' => $this->user->format_date($row['topic_time']),
- 'FIRST_UNREAD_POST_AUTHOR' => !empty($first_unread_post_author) ? $first_unread_post_author : '',
- 'FIRST_UNREAD_POST_AUTHOR_COLOUR' => !empty($first_unread_post_author_color) ? $first_unread_post_author_color : '',
- 'FIRST_UNREAD_POST_AUTHOR_FULL' => !empty($first_unread_post_author_full) ? $first_unread_post_author_full : '',
- 'U_FIRST_UNREAD_POST_AUTHOR' => !empty($u_first_unread_post_author) ? $u_first_unread_post_author : '',
- 'FIRST_UNREAD_POST_SUBJECT' => censor_text(!empty($first_unread['post_subject']) ? $first_unread['post_subject'] : ''),
- 'FIRST_UNREAD_POST_TIME' => !empty($first_unread_post_time) ? $first_unread_post_time : '',
+ 'FIRST_UNREAD_POST_AUTHOR' => $first_unread_post_author ?? '',
+ 'FIRST_UNREAD_POST_AUTHOR_COLOUR' => $first_unread_post_author_color ?? '',
+ 'FIRST_UNREAD_POST_AUTHOR_FULL' => $first_unread_post_author_full ?? '',
+ 'U_FIRST_UNREAD_POST_AUTHOR' => $u_first_unread_post_author ?? '',
+ 'FIRST_UNREAD_POST_SUBJECT' => censor_text($row['topic_first_unread_post_subject']),
+ 'FIRST_UNREAD_POST_TIME' => $first_unread_post_time ?? '',
'LAST_POST_SUBJECT' => censor_text($row['topic_last_post_subject']),
'LAST_POST_TIME' => $this->user->format_date($row['topic_last_post_time']),
'LAST_VIEW_TIME' => $this->user->format_date($row['topic_last_view_time']),
@@ -613,7 +617,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
'ATTACH_ICON_IMG' => ($this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $this->user->img('icon_topic_attach', $this->language->lang('TOTAL_ATTACHMENTS')) : '',
'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $this->user->img('icon_topic_unapproved', $topic_unapproved ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '',
'REPORTED_IMG' => ($row['topic_reported'] && $this->auth->acl_get('m_report', $forum_id)) ? $this->user->img('icon_topic_reported', 'TOPIC_REPORTED') : '',
- 'S_HAS_POLL' => $row['poll_start'] ? true : false,
+ 'S_HAS_POLL' => (bool) $row['poll_start'],
'S_TOPIC_TYPE' => $row['topic_type'],
'S_UNREAD_TOPIC' => $unread_topic,
'S_DISP_FIRST_UNREAD_POST' => $disp_topic_title == 'first_unread_post',
@@ -700,7 +704,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$tpl_loopname . '_start', $topics_count, $this->topics_per_page, max(0, min((int) $rtng_start, $total_topics_limit)));
$this->template->assign_vars([
- 'S_RTNG_TOPIC_ICONS' => count($topic_icons) ? true : false,
+ 'S_RTNG_TOPIC_ICONS' => (bool) $topic_icons,
]);
} // topics found
}
From 711d5588f8b8e1f75270905ad423efc47433a7ac Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sat, 1 Nov 2025 20:53:09 +0100
Subject: [PATCH 13/30] Optimise the SQL query for the first unread post.
- A switch has been added to the load settings to deactivate the request for the first unread post.
- The SQL query has been expanded and optimized.
- The evaluation conditions for information on read and unread posts from the database or cookie have been improved.
---
imcger/recenttopicsng/composer.json | 24 +++---
imcger/recenttopicsng/config/services.yml | 1 +
.../controller/controller_common.php | 13 +--
imcger/recenttopicsng/core/rtng_functions.php | 82 +++++++++----------
imcger/recenttopicsng/docs/CHANGELOG.md | 6 +-
imcger/recenttopicsng/event/acp_listener.php | 19 +++++
.../language/de/info_acp_rtng.php | 7 +-
.../language/de_x_sie/info_acp_rtng.php | 7 +-
.../language/en/info_acp_rtng.php | 7 +-
imcger/recenttopicsng/migrations/v_1_1_0.php | 35 ++++++++
10 files changed, 136 insertions(+), 65 deletions(-)
create mode 100644 imcger/recenttopicsng/migrations/v_1_1_0.php
diff --git a/imcger/recenttopicsng/composer.json b/imcger/recenttopicsng/composer.json
index 82654f4..de75de9 100644
--- a/imcger/recenttopicsng/composer.json
+++ b/imcger/recenttopicsng/composer.json
@@ -3,20 +3,20 @@
"type": "phpbb-extension",
"description": "Adds a list with a number of recent topics to the board index.",
"homepage": "https://github.com/IMC-GER/RecentTopicsNG",
- "version": "1.0.1",
- "time": "2025-09-27",
+ "version": "1.1.0-dev",
+ "time": "2025-11-01",
"license": "GPL-2.0-only",
"authors": [
- {
- "name": "Thorsten Ahlers",
- "homepage": "https://github.com/IMC-GER",
- "role": "Developer"
- },
- {
- "name": "LukeWCS",
- "homepage": "https://github.com/LukeWCS",
- "role": "Developer"
- },
+ {
+ "name": "Thorsten Ahlers",
+ "homepage": "https://github.com/IMC-GER",
+ "role": "Developer"
+ },
+ {
+ "name": "LukeWCS",
+ "homepage": "https://github.com/LukeWCS",
+ "role": "Developer"
+ },
{
"name": "Andreas Vandenberghe",
"homepage": "https://www.avathar.be",
diff --git a/imcger/recenttopicsng/config/services.yml b/imcger/recenttopicsng/config/services.yml
index f228585..3735d41 100644
--- a/imcger/recenttopicsng/config/services.yml
+++ b/imcger/recenttopicsng/config/services.yml
@@ -30,6 +30,7 @@ services:
- '@user'
- '@auth'
- '@dbal.conn'
+ - '@config'
imcger.recenttopicsng.functions:
class: imcger\recenttopicsng\core\rtng_functions
diff --git a/imcger/recenttopicsng/controller/controller_common.php b/imcger/recenttopicsng/controller/controller_common.php
index cc2d062..78847b2 100644
--- a/imcger/recenttopicsng/controller/controller_common.php
+++ b/imcger/recenttopicsng/controller/controller_common.php
@@ -18,17 +18,20 @@ class controller_common
protected object $user;
protected object $auth;
protected object $db;
+ protected object $config;
public function __construct
(
\phpbb\user $user,
\phpbb\auth\auth $auth,
- \phpbb\db\driver\driver_interface $db
+ \phpbb\db\driver\driver_interface $db,
+ \phpbb\config\config $config
)
{
- $this->user = $user;
- $this->auth = $auth;
- $this->db = $db;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->db = $db;
+ $this->config = $config;
}
/*
@@ -113,7 +116,7 @@ public function get_user_set_template_vars(int $user_id, array $template_setting
]);
}
- if ($user_auth->acl_get('u_rtng_disp_first_unrd_post') || $uaec)
+ if (($user_auth->acl_get('u_rtng_disp_first_unrd_post') || $uaec) && ($this->config['rtng_load_first_unrd_post'] && $this->config['load_db_lastread']))
{
$template_vars['RTNG_DISP_FIRST_UNRD_POST'] = $template_setting['user_rtng_disp_first_unrd_post'];
}
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index c013a61..91a616c 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -187,32 +187,17 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
$icons = $this->cache->obtain_icons();
}
- // Borrowed from search.php
+ // Get the topic tracking data
$topic_tracking_info = [];
foreach ($forums as $forum_id => $forum)
{
- if ($this->user->data['is_registered'] && $this->config['load_db_lastread'])
+ if ($this->config['load_db_lastread'] && $this->user->data['is_registered'] && !$this->config['rtng_load_first_unrd_post'])
{
- $topic_tracking_info[$forum_id] = get_topic_tracking($forum_id, $forum['topic_list'], $forum['rowset'], [$forum_id => $forum['mark_time']], $forum_id ? false : $forum['topic_list']);
+ $topic_tracking_info[$forum_id] = get_topic_tracking($forum_id, $forum['topic_list'], $forum['rowset'], [$forum_id => $forum['mark_time']]);
}
- else if ($this->config['load_anon_lastread'] || $this->user->data['is_registered'])
+ else if ($this->config['load_anon_lastread'] || ($this->user->data['is_registered'] && !$this->config['load_db_lastread']))
{
- $tracking_topics = $this->request->variable($this->config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
- $tracking_topics = $tracking_topics ? tracking_unserialize($tracking_topics) : [];
-
- $topic_tracking_info[$forum_id] = get_complete_topic_tracking($forum_id, $forum['topic_list'], $forum_id ? false : $forum['topic_list']);
-
- if (!$this->user->data['is_registered'])
- {
- if (isset($tracking_topics['l']))
- {
- $this->user->data['user_lastmark'] = ( (int) base_convert($tracking_topics['l'], 36, 10) + (int) $this->config['board_startdate']);
- }
- else
- {
- $this->user->data['user_lastmark'] = 0;
- }
- }
+ $topic_tracking_info[$forum_id] = get_complete_topic_tracking($forum_id, $forum['topic_list']);
}
}
@@ -491,40 +476,38 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
foreach ($rowset as $row)
{
+ $first_unread = [];
$topic_id = $row['topic_id'];
$forum_id = $row['forum_id'];
$unread_topic = false;
$replies = $this->content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
$s_type_switch_test = ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) ? 1 : 0;
+ $disp_topic_title = $this->user_setting['user_rtng_disp_last_post'] ? 'last_post' : 'first_post';
if ($row['topic_status'] == ITEM_MOVED)
{
$topic_id = $row['topic_moved_id'];
}
- else if ($this->user_setting['user_rtng_unread_only'])
- {
- $unread_topic = $this->user->data['user_id'] != ANONYMOUS;
- }
- else
- {
- $unread_topic = isset($topic_tracking_info[$forum_id][$row['topic_id']]) && ($row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]);
- }
-
- $disp_topic_title = $this->user_setting['user_rtng_disp_last_post'] ? 'last_post' : 'first_post';
-
- $first_unread = [];
-
- if ($unread_topic)
+ else if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && $this->config['rtng_load_first_unrd_post'])
{
// Get author, posttime, id and title of first unread post in topic
$sql_array = [
'SELECT' => 'p.poster_id, u.username, u.user_colour, p.post_id, p.post_subject, p.post_time',
'FROM' => [POSTS_TABLE => 'p', ],
'LEFT_JOIN' => [
+ [
+ 'FROM' => [TOPICS_TABLE => 't', ],
+ 'ON' => "t.topic_id = p.topic_id",
+ ],
[
'FROM' => [TOPICS_TRACK_TABLE => 'tt', ],
'ON' => "tt.user_id = {$this->user->data['user_id']}
- AND tt.topic_id = $topic_id",
+ AND tt.topic_id = p.topic_id",
+ ],
+ [
+ 'FROM' => [FORUMS_TRACK_TABLE => 'ft', ],
+ 'ON' => "ft.user_id = {$this->user->data['user_id']}
+ AND ft.forum_id = t.forum_id",
],
[
'FROM' => [USERS_TABLE => 'u', ],
@@ -532,24 +515,32 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
],
],
'WHERE' => "p.topic_id = $topic_id
- AND p.post_time > COALESCE(tt.mark_time, 0)",
+ AND p.post_time > COALESCE(tt.mark_time, ft.mark_time, {$this->user->data['user_lastmark']}, 0)
+ AND p.forum_id = $forum_id",
'ORDER_BY' => 'p.post_time ASC, p.post_id ASC',
];
+
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, 1);
$first_unread = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
- if ($this->user_setting['user_rtng_disp_first_unrd_post'])
+ $unread_topic = !empty($first_unread['post_id']);
+
+ if ($this->user_setting['user_rtng_disp_first_unrd_post'] && $unread_topic)
{
$disp_topic_title = 'first_unread_post';
- }
- $first_unread_post_author = get_username_string('username', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
- $first_unread_post_author_color = get_username_string('colour', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
- $first_unread_post_author_full = get_username_string('full', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
- $first_unread_post_time = $this->user->format_date($first_unread['post_time']);
- $u_first_unread_post_author = get_username_string('profile', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
+ $first_unread_post_author = get_username_string('username', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
+ $first_unread_post_author_color = get_username_string('colour', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
+ $first_unread_post_author_full = get_username_string('full', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
+ $first_unread_post_time = $this->user->format_date($first_unread['post_time']);
+ $u_first_unread_post_author = get_username_string('profile', $first_unread['poster_id'], $first_unread['username'], $first_unread['user_colour']);
+ }
+ }
+ else
+ {
+ $unread_topic = isset($topic_tracking_info[$forum_id][$row['topic_id']]) && ($row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]);
}
$row['topic_first_unread_post_id'] = $first_unread['post_id'] ?? '';
@@ -574,6 +565,11 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$topic_icons[] = $topic_id;
}
+ if ($this->user_setting['user_rtng_unread_only'] && $this->user->data['is_registered'])
+ {
+ $unread_topic = true;
+ }
+
// Get folder img, topic status/type related information
$folder_img = $folder_alt = $topic_type = '';
topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
diff --git a/imcger/recenttopicsng/docs/CHANGELOG.md b/imcger/recenttopicsng/docs/CHANGELOG.md
index 6cff1f3..90f037c 100644
--- a/imcger/recenttopicsng/docs/CHANGELOG.md
+++ b/imcger/recenttopicsng/docs/CHANGELOG.md
@@ -8,8 +8,10 @@ This is a non-exhaustive (but still near complete) changelog for Recent Topics N
- [Changed] Var name $num_rows to $topics_count.
- [Changed] Improved vars for `sql_query_limit()`.
- [Changed] Better support for phpBB Collapsed Categories.
- - [Feature] Added events to `rtng_body_site`
- - [Feature] Added events to `rtng_body_topbottom`
+ - [Changed] Improved sql query for first unread post.
+ - [Feature] Added switch in load settings to disable sql request for first unread post in RTNG.
+ - [Feature] Added events to `rtng_body_site`.
+ - [Feature] Added events to `rtng_body_topbottom`.
- [Feature] Added canonical link to separate page.
- [Feature] Added vars in event `modify_tpl_ary`. `$disp_topic_title` and properties of the first unread post to `$row`.
diff --git a/imcger/recenttopicsng/event/acp_listener.php b/imcger/recenttopicsng/event/acp_listener.php
index a82c68d..7bc7211 100644
--- a/imcger/recenttopicsng/event/acp_listener.php
+++ b/imcger/recenttopicsng/event/acp_listener.php
@@ -42,6 +42,7 @@ public static function getSubscribedEvents(): array
'core.acp_users_prefs_modify_data' => 'acp_users_prefs_modify_data',
'core.acp_users_prefs_modify_sql' => 'acp_users_prefs_modify_sql',
'core.acp_users_prefs_modify_template_data' => 'acp_users_prefs_modify_template_data',
+ 'core.acp_board_config_edit_add' => 'acp_board_config_edit_add',
];
}
@@ -136,4 +137,22 @@ public function acp_users_prefs_modify_template_data(object $event): void
$event['user_prefs_data'] = array_merge($event['user_prefs_data'], $template_vars);
}
}
+
+ /**
+ * Event to add and/or modify acp_board configurations
+ */
+ public function acp_board_config_edit_add(object $event): void
+ {
+ $display_vars = $event['display_vars'];
+ if (isset($display_vars['title']) && $display_vars['title'] == 'ACP_LOAD_SETTINGS')
+ {
+ $rtng_vars = [
+ 'rtng_options_legend' => 'RTNG_LOAD_OPTIONS',
+ 'rtng_load_first_unrd_post' => ['lang' => 'RTNG_LOAD_FIRST_UNRD_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true],
+ ];
+
+ $display_vars['vars'] = phpbb_insert_config_array($display_vars['vars'], $rtng_vars, ['before' => 'legend3']);
+ $event['display_vars'] = $display_vars;
+ }
+ }
}
diff --git a/imcger/recenttopicsng/language/de/info_acp_rtng.php b/imcger/recenttopicsng/language/de/info_acp_rtng.php
index 8827a42..7f6e050 100644
--- a/imcger/recenttopicsng/language/de/info_acp_rtng.php
+++ b/imcger/recenttopicsng/language/de/info_acp_rtng.php
@@ -41,7 +41,7 @@
$lang = array_merge($lang, [
// Language pack author
'RTNG_LANG_DESC' => 'Deutsch (Du)',
- 'RTNG_LANG_EXT_VER' => '1.0.0',
+ 'RTNG_LANG_EXT_VER' => '1.1.0',
'RTNG_LANG_AUTHOR' => 'IMC-GER / LukeWCS',
//forum acp
@@ -54,6 +54,11 @@
'RTNG_EXPLAIN' => 'Auf dieser Seite kannst du die Einstellungen der Erweiterung „Recent Topics NG“ anpassen.
Spezifische Foren können eingeschlossen oder ausgeschlossen werden.
Überprüfe auch die Benutzerberechtigungen, welche Benutzern erlauben, einige der Parameter für sich selbst zu verändern. Diese haben dann Vorrang vor den Einstellungen des Admin-Panels.',
'RTNG_CONFIG' => 'Einstellungen',
+ // acp load
+ 'RTNG_LOAD_OPTIONS' => '„Recent Topics NG“ Optionen',
+ 'RTNG_LOAD_FIRST_UNRD_POST' => 'Ermöglicht den Zugriff auf den ersten ungelesenen Beitrag',
+ 'RTNG_LOAD_FIRST_UNRD_POST_EXPLAIN' => 'Wenn diese Option aktiviert ist, werden die Daten des ersten ungelesenen Beitrags ausgelesen und zur weiteren Verarbeitung bereitgestellt.',
+
//allgemeine Einstellungen
'RTNG_GLOBAL_SETTINGS' => 'Globale Einstellungen',
'RTNG_INDEX_DISPLAY_EXP' => 'Anzeigen auf der Index-Seite.',
diff --git a/imcger/recenttopicsng/language/de_x_sie/info_acp_rtng.php b/imcger/recenttopicsng/language/de_x_sie/info_acp_rtng.php
index 514e23c..3a85471 100644
--- a/imcger/recenttopicsng/language/de_x_sie/info_acp_rtng.php
+++ b/imcger/recenttopicsng/language/de_x_sie/info_acp_rtng.php
@@ -41,7 +41,7 @@
$lang = array_merge($lang, [
// Language pack author
'RTNG_LANG_DESC' => 'Deutsch (Sie)',
- 'RTNG_LANG_EXT_VER' => '1.0.0',
+ 'RTNG_LANG_EXT_VER' => '1.1.0',
'RTNG_LANG_AUTHOR' => 'IMC-GER / LukeWCS',
//forum acp
@@ -54,6 +54,11 @@
'RTNG_EXPLAIN' => 'Auf dieser Seite können Sie die Einstellungen der Erweiterung „Recent Topics NG“ anpassen.
Spezifische Foren können eingeschlossen oder ausgeschlossen werden.
Überprüfe auch die Benutzerberechtigungen, welche Benutzern erlauben, einige der Parameter für sich selbst zu verändern. Diese haben dann Vorrang vor den Einstellungen des Admin-Panels.',
'RTNG_CONFIG' => 'Einstellungen',
+ // acp load
+ 'RTNG_LOAD_OPTIONS' => '„Recent Topics NG“ Optionen',
+ 'RTNG_LOAD_FIRST_UNRD_POST' => 'Ermöglicht den Zugriff auf den ersten ungelesenen Beitrag',
+ 'RTNG_LOAD_FIRST_UNRD_POST_EXPLAIN' => 'Wenn diese Option aktiviert ist, werden die Daten des ersten ungelesenen Beitrags ausgelesen und zur weiteren Verarbeitung bereitgestellt.',
+
//allgemeine Einstellungen
'RTNG_GLOBAL_SETTINGS' => 'Globale Einstellungen',
'RTNG_INDEX_DISPLAY_EXP' => 'Anzeigen auf der Index-Seite.',
diff --git a/imcger/recenttopicsng/language/en/info_acp_rtng.php b/imcger/recenttopicsng/language/en/info_acp_rtng.php
index 7aeeab9..898e43c 100644
--- a/imcger/recenttopicsng/language/en/info_acp_rtng.php
+++ b/imcger/recenttopicsng/language/en/info_acp_rtng.php
@@ -41,7 +41,7 @@
$lang = array_merge($lang, [
// Language pack author
'RTNG_LANG_DESC' => 'English',
- 'RTNG_LANG_EXT_VER' => '1.0.0',
+ 'RTNG_LANG_EXT_VER' => '1.1.0',
'RTNG_LANG_AUTHOR' => 'IMC-GER / LukeWCS',
//forum acp
@@ -54,6 +54,11 @@
'RTNG_EXPLAIN' => 'On this page you can change the settings specific for the Recent Topics extension.
Specific forums can be included or excluded by editing the respective forums in your ACP.
Also be sure to check your user permissions, which allow users to change some of the settings found below for themselves.',
'RTNG_CONFIG' => 'Configuration',
+ // acp load
+ 'RTNG_LOAD_OPTIONS' => '“Recent Topics NG” options',
+ 'RTNG_LOAD_FIRST_UNRD_POST' => 'Allows access to the first unread post',
+ 'RTNG_LOAD_FIRST_UNRD_POST_EXPLAIN' => 'If this option is enabled, the data of the first unread post is read and made available for further processing.',
+
//global settings
'RTNG_GLOBAL_SETTINGS' => 'Global Settings',
'RTNG_INDEX_DISPLAY_EXP' => 'Display on Index page',
diff --git a/imcger/recenttopicsng/migrations/v_1_1_0.php b/imcger/recenttopicsng/migrations/v_1_1_0.php
new file mode 100644
index 0000000..cee0587
--- /dev/null
+++ b/imcger/recenttopicsng/migrations/v_1_1_0.php
@@ -0,0 +1,35 @@
+config['rtng_load_first_unrd_post']);
+ }
+
+ public static function depends_on(): array
+ {
+ return ['\imcger\recenttopicsng\migrations\v_1_0_0'];
+ }
+
+ public function update_data(): array
+ {
+ return [
+ // Add new config vars
+ ['config.add', ['rtng_load_first_unrd_post', 0]],
+ ];
+ }
+}
From addfa860b585045a9e196559f75b2b79910a06e3 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sun, 23 Nov 2025 11:03:06 +0100
Subject: [PATCH 14/30] Code improvements in migration and core
- Migration: Set the load setting to true when link to unread post used
- Removed old template code from "Collapse Forum Cat"
- Improved ITEM_MOVED handling for unread posts
---
imcger/recenttopicsng/core/rtng_functions.php | 9 +++------
.../recenttopicsng/language/en/rtng_common.php | 2 +-
imcger/recenttopicsng/migrations/v_1_1_0.php | 17 +++++++++++++++++
.../styles/all/template/rtng_body_side.html | 1 -
.../all/template/rtng_body_topbottom.html | 3 +--
5 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 91a616c..2bc293d 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -270,11 +270,12 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
$min_topic_level = $this->config['rtng_min_topic_level'];
// Either use the phpBB core function to get unread topics, or the custom function for default behavior
- if ($this->user_setting['user_rtng_unread_only'] && $this->user->data['user_id'] != ANONYMOUS)
+ if ($this->user_setting['user_rtng_unread_only'] && $this->user->data['is_registered'])
{
// Get unread topics
$sql_extra = ' AND ' . $this->db->sql_in_set('t.topic_id', $excluded_topics, true);
$sql_extra .= ' AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $forum_id_list, $table_alias = 't.');
+ $sql_extra .= ' AND t.topic_status <> ' . ITEM_MOVED;
$unread_topics = get_unread_topics(false, $sql_extra, '', $total_topics_limit);
$topics_count = count($unread_topics);
@@ -484,11 +485,7 @@ private function fill_template(array $icons, string $tpl_loopname, array $topic_
$s_type_switch_test = ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) ? 1 : 0;
$disp_topic_title = $this->user_setting['user_rtng_disp_last_post'] ? 'last_post' : 'first_post';
- if ($row['topic_status'] == ITEM_MOVED)
- {
- $topic_id = $row['topic_moved_id'];
- }
- else if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && $this->config['rtng_load_first_unrd_post'])
+ if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && $this->config['rtng_load_first_unrd_post'])
{
// Get author, posttime, id and title of first unread post in topic
$sql_array = [
diff --git a/imcger/recenttopicsng/language/en/rtng_common.php b/imcger/recenttopicsng/language/en/rtng_common.php
index 8069245..b9612fa 100644
--- a/imcger/recenttopicsng/language/en/rtng_common.php
+++ b/imcger/recenttopicsng/language/en/rtng_common.php
@@ -39,7 +39,7 @@
// ‚ ‘ ’ « » “ ” … „ “
//
$lang = array_merge($lang, [
- 'RTNG_NAME' => 'Recent Topics NG',
+ 'RTNG_NAME' => 'Recent Topics NG', // Please do not translate the name of the extension
'RTNG_DESIG' => 'Recent Topics',
'RTNG_NO_TOPICS' => 'There are no new topics to display.',
'RTNG_TOPICS_COUNT' => '%d Topics',
diff --git a/imcger/recenttopicsng/migrations/v_1_1_0.php b/imcger/recenttopicsng/migrations/v_1_1_0.php
index cee0587..efac2b8 100644
--- a/imcger/recenttopicsng/migrations/v_1_1_0.php
+++ b/imcger/recenttopicsng/migrations/v_1_1_0.php
@@ -30,6 +30,23 @@ public function update_data(): array
return [
// Add new config vars
['config.add', ['rtng_load_first_unrd_post', 0]],
+
+ // Set rtng_load_first_unrd_post to true when
+ // user_rtng_disp_first_unrd_post is set in one or more columm
+ ['custom', [[$this, 'isset_first_unrd_post']]],
];
}
+
+ public function isset_first_unrd_post()
+ {
+ $sql = 'SELECT COUNT(*) AS unrd_post
+ FROM ' . USERS_TABLE . '
+ WHERE user_rtng_disp_first_unrd_post = 1';
+
+ $result = $this->db->sql_query($sql);
+ $unrd_post = $this->db->sql_fetchfield('unrd_post');
+ $this->db->sql_freeresult($result);
+
+ $this->config->set('rtng_load_first_unrd_post', (bool) $unrd_post);
+ }
}
diff --git a/imcger/recenttopicsng/styles/all/template/rtng_body_side.html b/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
index c844614..267b512 100644
--- a/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
+++ b/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
@@ -11,7 +11,6 @@
#}
{% if S_RTNG_LOCATION_SIDE %}
-
diff --git a/imcger/recenttopicsng/styles/all/template/rtng_body_topbottom.html b/imcger/recenttopicsng/styles/all/template/rtng_body_topbottom.html
index 5b53611..4a1ab8a 100644
--- a/imcger/recenttopicsng/styles/all/template/rtng_body_topbottom.html
+++ b/imcger/recenttopicsng/styles/all/template/rtng_body_topbottom.html
@@ -29,8 +29,7 @@
{% endif %}
{% if rtng.S_FIRST_ROW || !rtng.S_TOPIC_TYPE_SWITCH %}
-
- {% EVENT forumlist_body_category_header_before %}
+{% EVENT forumlist_body_category_header_before %}
From c3c87cc3e2b8b8ec9045f55a5cf17ac14d597ba8 Mon Sep 17 00:00:00 2001
From: Thorsten <88725484+IMC-GER@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:15:19 +0100
Subject: [PATCH 15/30] v1.1.0-dev 2025-12-28
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Changed php min to v8.0.
- Changed Cached “rtng_user_data” reduces DB queries.
- Changed Improved SQL query for topic counting for better performance.
- Changed assign_block_vars() replaced in main_listener.
- Changed assign_block_vars() replaced in page_controller.
- Changed phpBB template code replaced with Twig syntax.
---
imcger/recenttopicsng/composer.json | 4 +-
.../controller/controller_common.php | 123 ++++++++----------
.../controller/page_controller.php | 6 +-
imcger/recenttopicsng/core/rtng_functions.php | 8 +-
imcger/recenttopicsng/docs/CHANGELOG.md | 19 ++-
imcger/recenttopicsng/event/main_listener.php | 9 +-
imcger/recenttopicsng/event/ucp_listener.php | 2 +-
imcger/recenttopicsng/ext.php | 2 +-
.../index_body_forumlist_body_after.html | 2 +-
.../event/index_body_markforums_after.html | 2 +-
.../event/overall_header_head_append.html | 2 +-
.../styles/all/template/rtng_body_side.html | 12 +-
.../all/template/rtng_body_topbottom.html | 16 +--
13 files changed, 101 insertions(+), 106 deletions(-)
diff --git a/imcger/recenttopicsng/composer.json b/imcger/recenttopicsng/composer.json
index de75de9..79acbee 100644
--- a/imcger/recenttopicsng/composer.json
+++ b/imcger/recenttopicsng/composer.json
@@ -4,7 +4,7 @@
"description": "Adds a list with a number of recent topics to the board index.",
"homepage": "https://github.com/IMC-GER/RecentTopicsNG",
"version": "1.1.0-dev",
- "time": "2025-11-01",
+ "time": "2025-12-27",
"license": "GPL-2.0-only",
"authors": [
{
@@ -32,7 +32,7 @@
}
],
"require": {
- "php": ">=7.4,<8.5.0@dev",
+ "php": ">=8.0,<8.6.0@dev",
"composer/installers": "~1.0"
},
"extra": {
diff --git a/imcger/recenttopicsng/controller/controller_common.php b/imcger/recenttopicsng/controller/controller_common.php
index 78847b2..1c3c035 100644
--- a/imcger/recenttopicsng/controller/controller_common.php
+++ b/imcger/recenttopicsng/controller/controller_common.php
@@ -19,6 +19,7 @@ class controller_common
protected object $auth;
protected object $db;
protected object $config;
+ protected array $rtng_user_data;
public function __construct
(
@@ -32,6 +33,8 @@ public function __construct
$this->auth = $auth;
$this->db = $db;
$this->config = $config;
+
+ $this->set_rtng_user_data($user->data);
}
/*
@@ -68,9 +71,9 @@ public function get_user_set_template_vars(int $user_id, array $template_setting
{
if ($user_id != $this->user->data['user_id'])
{
- $user_auth = new \phpbb\auth\auth();
- $userdata = $user_auth->obtain_user_data($user_id);
- $user_auth->acl($userdata);
+ $user_auth = new \phpbb\auth\auth();
+ $auth_userdata = $user_auth->obtain_user_data($user_id);
+ $user_auth->acl($auth_userdata);
}
else
{
@@ -111,8 +114,8 @@ public function get_user_set_template_vars(int $user_id, array $template_setting
if ($user_auth->acl_get('u_rtng_disp_last_post') || $uaec)
{
$template_vars['RTNG_DISP_LAST_POST_OPTIONS'] = $this->select_struct((int) $template_setting['user_rtng_disp_last_post'], [
- 'RTNG_FIRST_POST' => 0,
- 'RTNG_LAST_POST' => 1,
+ 'RTNG_FIRST_POST' => 0,
+ 'RTNG_LAST_POST' => 1,
]);
}
@@ -157,11 +160,40 @@ public function get_user_set_template_vars(int $user_id, array $template_setting
return $template_vars;
}
+ /**
+ * Store user data in cache array
+ */
+ public function set_rtng_user_data(array $user_data): bool
+ {
+ if (empty($user_data['user_id']))
+ {
+ return false;
+ }
+
+ $this->rtng_user_data[$user_data['user_id']] = [];
+
+ foreach ($user_data as $key => $value)
+ {
+ if (str_starts_with($key, 'user_rtng'))
+ {
+ $this->rtng_user_data[$user_data['user_id']][$key] = $value;
+ }
+ }
+
+ return true;
+ }
+
/**
* Returns the RTNG user data.
+ * Cache user data in an array
*/
public function get_rtng_user_data(int $user_id = ANONYMOUS): array
{
+ if (isset($this->rtng_user_data[$user_id]))
+ {
+ return $this->rtng_user_data[$user_id];
+ }
+
$sql_array = [
'SELECT' => 'user_rtng_enable, user_rtng_sort_start_time, user_rtng_unread_only,
user_rtng_location, user_rtng_disp_last_post, user_rtng_disp_first_unrd_post,
@@ -173,93 +205,44 @@ public function get_rtng_user_data(int $user_id = ANONYMOUS): array
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, 1);
- $data = $this->db->sql_fetchrow($result);
+ $this->rtng_user_data[$user_id] = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
- return $data;
+ return $this->rtng_user_data[$user_id];
}
/**
- * Returns the RTNG user settings depending on the user authorizations.
+ * Returns the RTNG user settings depending on the user permission.
*/
- public function get_user_setting(?int $user_id = null): array
+ public function get_user_setting(int $user_id = 0): array
{
- $default_data = $this->get_rtng_user_data();
-
- if (isset($user_id))
- {
- $user_data = $this->get_rtng_user_data($user_id);
- }
- else
- {
- $user_id = $this->user->data['user_id'];
- $user_data = $this->user->data;
- }
+ $user_id = $user_id ?: $this->user->data['user_id'];
+ $default_data = $this->get_rtng_user_data(ANONYMOUS);
if ($user_id == ANONYMOUS)
{
return $default_data;
}
+ $user_data = $this->get_rtng_user_data($user_id);
+
if ($user_id != $this->user->data['user_id'])
{
- $user_auth = new \phpbb\auth\auth();
- $userdata = $user_auth->obtain_user_data($user_id);
- $user_auth->acl($userdata);
+ $user_auth = new \phpbb\auth\auth();
+ $auth_userdata = $user_auth->obtain_user_data($user_id);
+ $user_auth->acl($auth_userdata);
}
else
{
$user_auth = $this->auth;
}
- if ($user_auth->acl_get('u_rtng_enable'))
- {
- $default_data['user_rtng_enable'] = $user_data['user_rtng_enable'];
- }
-
- if ($user_auth->acl_get('u_rtng_sort_start_time'))
- {
- $default_data['user_rtng_sort_start_time'] = $user_data['user_rtng_sort_start_time'];
- }
-
- if ($user_auth->acl_get('u_rtng_unread_only'))
- {
- $default_data['user_rtng_unread_only'] = $user_data['user_rtng_unread_only'];
- }
-
- if ($user_auth->acl_get('u_rtng_location'))
+ foreach ($default_data as $key => $value)
{
- $default_data['user_rtng_location'] = $user_data['user_rtng_location'];
- }
-
- if ($user_auth->acl_get('u_rtng_disp_last_post'))
- {
- $default_data['user_rtng_disp_last_post'] = $user_data['user_rtng_disp_last_post'];
- }
-
- if ($user_auth->acl_get('u_rtng_disp_first_unrd_post'))
- {
- $default_data['user_rtng_disp_first_unrd_post'] = $user_data['user_rtng_disp_first_unrd_post'];
- }
-
- if ($user_auth->acl_get('u_rtng_index_topics_qty'))
- {
- $default_data['user_rtng_index_topics_qty'] = $user_data['user_rtng_index_topics_qty'];
- }
-
- if ($user_auth->acl_get('u_rtng_index_page_qty'))
- {
- $default_data['user_rtng_index_page_qty'] = $user_data['user_rtng_index_page_qty'];
- }
-
- if ($user_auth->acl_get('u_rtng_separate_topics_qty'))
- {
- $default_data['user_rtng_separate_topics_qty'] = $user_data['user_rtng_separate_topics_qty'];
- }
-
- if ($user_auth->acl_get('u_rtng_separate_page_qty'))
- {
- $default_data['user_rtng_separate_page_qty'] = $user_data['user_rtng_separate_page_qty'];
+ if ($user_auth->acl_get('u_' . substr($key, 5)))
+ {
+ $default_data[$key] = $user_data[$key];
+ }
}
unset($user_auth);
diff --git a/imcger/recenttopicsng/controller/page_controller.php b/imcger/recenttopicsng/controller/page_controller.php
index b8ff751..d9b5db3 100644
--- a/imcger/recenttopicsng/controller/page_controller.php
+++ b/imcger/recenttopicsng/controller/page_controller.php
@@ -97,12 +97,14 @@ public function display(string $page): object
make_jumpbox(append_sid($this->phpbb_root_path . 'viewforum.' . $this->phpEx));
// Generate link in NavBar
- $this->template->assign_block_vars('navlinks', [
+ $navlinks = [];
+ $navlinks[] = [
'BREADCRUMB_NAME' => $this->language->lang('RTNG_DESIG'),
'U_BREADCRUMB' => $this->helper->route('imcger_recenttopicsng_page_controller', ['page' => 'separate']),
- ]);
+ ];
$this->template->assign_vars([
+ 'navlinks' => $navlinks,
'U_CANONICAL' => $this->helper->route('imcger_recenttopicsng_page_controller', ['page' => 'separate'], true, false, \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL),
]);
diff --git a/imcger/recenttopicsng/core/rtng_functions.php b/imcger/recenttopicsng/core/rtng_functions.php
index 2bc293d..503edef 100644
--- a/imcger/recenttopicsng/core/rtng_functions.php
+++ b/imcger/recenttopicsng/core/rtng_functions.php
@@ -68,8 +68,6 @@ public function __construct
$this->topics_per_page = 0;
$this->topics_page_number = 0;
-
- $this->user_setting = $this->ctrl_common->get_user_setting();
}
/**
@@ -103,8 +101,10 @@ public function set_topics_page_number(int $page_number): bool
/**
* Display recent topics
*/
- public function display_recent_topics(string $tpl_loopname = 'rtng'): void
+ public function display_recent_topics(string $tpl_loopname = 'rtng_topics'): void
{
+ $this->user_setting = $this->ctrl_common->get_user_setting();
+
// can view rtng ?
if (!($this->user_setting['user_rtng_enable'] && $this->auth->acl_get('u_rtng_view')))
{
@@ -154,6 +154,7 @@ public function display_recent_topics(string $tpl_loopname = 'rtng'): void
$count_sql_array = $sql_array;
$count_sql_array['SELECT'] = 'COUNT(t.topic_id) as topic_count';
unset($count_sql_array['ORDER_BY']);
+ unset($count_sql_array['LEFT_JOIN']);
$sql = $this->db->sql_build_query('SELECT', $count_sql_array);
$result = $this->db->sql_query($sql);
@@ -290,6 +291,7 @@ private function gettopiclist(bool &$obtain_icons, array &$forums, int $rtng_sta
$count_sql_array = $sql_array;
$count_sql_array['SELECT'] = 'COUNT(t.topic_id) as topic_count';
unset($count_sql_array['ORDER_BY']);
+ unset($count_sql_array['LEFT_JOIN']);
$sql = $this->db->sql_build_query('SELECT', $count_sql_array);
$result = $this->db->sql_query($sql);
diff --git a/imcger/recenttopicsng/docs/CHANGELOG.md b/imcger/recenttopicsng/docs/CHANGELOG.md
index 90f037c..c621717 100644
--- a/imcger/recenttopicsng/docs/CHANGELOG.md
+++ b/imcger/recenttopicsng/docs/CHANGELOG.md
@@ -2,13 +2,18 @@
This is a non-exhaustive (but still near complete) changelog for Recent Topics NG 1.x including release candidate versions.
#### Changes since V1.0.1 (xx/xx/2025)
- - [Changed] Optimization of loops that adjust arrays in `rtng_functions`.
- - [Changed] Only reads the topics that are necessary to load the page.
- - [Changed] Required tag in number macro in `rtng_macros.html` added.
- - [Changed] Var name $num_rows to $topics_count.
- - [Changed] Improved vars for `sql_query_limit()`.
- - [Changed] Better support for phpBB Collapsed Categories.
- - [Changed] Improved sql query for first unread post.
+ - [Change] php min to v8.0.
+ - [Change] Cached “rtng_user_data” reduces DB queries.
+ - [Change] Improved SQL query for topic counting for better performance.
+ - [Change] assign_block_vars() replaced in page_controller.
+ - [Change] phpBB template code replaced with Twig syntax.
+ - [Change] Optimization of loops that adjust arrays in `rtng_functions`.
+ - [Change] Only reads the topics that are necessary to load the page.
+ - [Change] Required tag in number macro in `rtng_macros.html` added.
+ - [Change] Var name $num_rows to $topics_count.
+ - [Change] Improved vars for `sql_query_limit()`.
+ - [Change] Better support for phpBB Collapsed Categories.
+ - [Change] Improved sql query for first unread post.
- [Feature] Added switch in load settings to disable sql request for first unread post in RTNG.
- [Feature] Added events to `rtng_body_site`.
- [Feature] Added events to `rtng_body_topbottom`.
diff --git a/imcger/recenttopicsng/event/main_listener.php b/imcger/recenttopicsng/event/main_listener.php
index f9d4ed6..5a2d0d6 100644
--- a/imcger/recenttopicsng/event/main_listener.php
+++ b/imcger/recenttopicsng/event/main_listener.php
@@ -70,11 +70,14 @@ public function display_forums_before(): void
// support for phpbb collapsable categories extension
if (isset($this->collapsable_categories))
{
- $fid = 'fid_rtng'; // can be any unique string to identify the collapsible element of your extension.
- $this->template->assign_block_vars('rtng_cc', [
+ $rtng_cc = [];
+ $fid = 'fid_rtng'; // can be any unique string to identify the collapsible element of your extension.
+ $rtng_cc[] = [
'S_FORUM_HIDDEN' => $this->collapsable_categories->is_collapsed($fid),
'U_COLLAPSE_URL' => $this->collapsable_categories->get_collapsible_link($fid),
- ]);
+ ];
+
+ $this->template->assign_vars(['rtng_cc' => $rtng_cc]);
}
}
diff --git a/imcger/recenttopicsng/event/ucp_listener.php b/imcger/recenttopicsng/event/ucp_listener.php
index 71f40df..7ae3d02 100644
--- a/imcger/recenttopicsng/event/ucp_listener.php
+++ b/imcger/recenttopicsng/event/ucp_listener.php
@@ -115,7 +115,7 @@ public function ucp_prefs_set_data(object $event): void
public function ucp_register_set_data(object $event): void
{
// Read guest account settings as default
- $user_data = $this->ctrl_common->get_rtng_user_data();
+ $user_data = $this->ctrl_common->get_rtng_user_data(ANONYMOUS);
$sql = 'UPDATE ' . USERS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $user_data) . '
diff --git a/imcger/recenttopicsng/ext.php b/imcger/recenttopicsng/ext.php
index 156a925..2ebc20f 100644
--- a/imcger/recenttopicsng/ext.php
+++ b/imcger/recenttopicsng/ext.php
@@ -18,7 +18,7 @@ class ext extends \phpbb\extension\base
public function is_enableable()
{
$valid_phpbb = phpbb_version_compare(PHPBB_VERSION, '3.3.5', '>=') && phpbb_version_compare(PHPBB_VERSION, '3.4.0-dev', '<');
- $valid_php = phpbb_version_compare(PHP_VERSION, '7.4.0', '>=') && phpbb_version_compare(PHP_VERSION, '8.5.0-dev', '<');
+ $valid_php = phpbb_version_compare(PHP_VERSION, '8.0.0', '>=') && phpbb_version_compare(PHP_VERSION, '8.6.0-dev', '<');
return ($valid_phpbb && $valid_php);
}
diff --git a/imcger/recenttopicsng/styles/all/template/event/index_body_forumlist_body_after.html b/imcger/recenttopicsng/styles/all/template/event/index_body_forumlist_body_after.html
index 9e4ada1..ec3fed0 100644
--- a/imcger/recenttopicsng/styles/all/template/event/index_body_forumlist_body_after.html
+++ b/imcger/recenttopicsng/styles/all/template/event/index_body_forumlist_body_after.html
@@ -10,7 +10,7 @@
* Based on the original NV Recent Topics by Joas Schilling (nickvergessen)
#}
-{% if RTNG_DISPLAY %}
+{% if RTNG_TOPICS_DISPLAY %}
{% if S_RTNG_LOCATION_BOTTOM %}
{% include '@imcger_recenttopicsng/rtng_body_topbottom.html' %}
diff --git a/imcger/recenttopicsng/styles/all/template/event/index_body_markforums_after.html b/imcger/recenttopicsng/styles/all/template/event/index_body_markforums_after.html
index cc18afb..34cc28d 100644
--- a/imcger/recenttopicsng/styles/all/template/event/index_body_markforums_after.html
+++ b/imcger/recenttopicsng/styles/all/template/event/index_body_markforums_after.html
@@ -10,7 +10,7 @@
* Based on the original NV Recent Topics by Joas Schilling (nickvergessen)
#}
-{% if RTNG_DISPLAY %}
+{% if RTNG_TOPICS_DISPLAY %}
{% if S_RTNG_LOCATION_TOP %}
{% include '@imcger_recenttopicsng/rtng_body_topbottom.html' %}
diff --git a/imcger/recenttopicsng/styles/all/template/event/overall_header_head_append.html b/imcger/recenttopicsng/styles/all/template/event/overall_header_head_append.html
index d60a0ca..9139f1f 100644
--- a/imcger/recenttopicsng/styles/all/template/event/overall_header_head_append.html
+++ b/imcger/recenttopicsng/styles/all/template/event/overall_header_head_append.html
@@ -10,7 +10,7 @@
* Based on the original NV Recent Topics by Joas Schilling (nickvergessen)
#}
-{% if RTNG_DISPLAY %}
+{% if RTNG_TOPICS_DISPLAY %}
{% INCLUDEJS '@imcger_recenttopicsng/recenttopicsng.js' %}
{% INCLUDECSS '@imcger_recenttopicsng/recenttopicsng.css' %}
{% endif %}
diff --git a/imcger/recenttopicsng/styles/all/template/rtng_body_side.html b/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
index 267b512..cb35a33 100644
--- a/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
+++ b/imcger/recenttopicsng/styles/all/template/rtng_body_side.html
@@ -33,15 +33,15 @@
-{% for rtng in loops.rtng %}
- {% if !rtng.S_TOPIC_TYPE_SWITCH && !rtng.S_FIRST_ROW %}
+{% for rtng in rtng_topics %}
+ {% if !rtng.S_TOPIC_TYPE_SWITCH && !loop.first %}
{% endif %}
- {% if rtng.S_FIRST_ROW || !rtng.S_TOPIC_TYPE_SWITCH %}
+ {% if loop.first || !rtng.S_TOPIC_TYPE_SWITCH %}
{% endif %}
- -
- {% if rtng.S_LAST_ROW %}
+ {% if loop.last %}
{% endif %}
{% else %}
@@ -122,7 +122,7 @@
-{% if loops.pagination|length %}
+{% if pagination is defined %}
{% endif %}
-{% if rtng.S_FIRST_ROW || !rtng.S_TOPIC_TYPE_SWITCH %}
+{% if loop.first || !rtng.S_TOPIC_TYPE_SWITCH %}
{% EVENT forumlist_body_category_header_before %}
@@ -54,7 +54,7 @@
{% endif %}
{% EVENT viewforum_body_topicrow_row_before %}
- -
+
-
{% EVENT viewforum_body_topic_row_prepend %}
@@ -97,7 +97,7 @@
{% if rtng.REPLIES %}{{ lang('REPLIES') }}{{ lang('COLON') }} {{ rtng.REPLIES }}{% endif %}
{% endif %}
- {% if rtng.pagination|length %}
+ {% if rtng.pagination is defined %}
@@ -168,7 +168,7 @@
{% endfor %}
-{% if loops.pagination|length && (S_RTNG_LOCATION_BOTTOM) %}
+{% if pagination is defined && S_RTNG_LOCATION_BOTTOM %}