Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 41 additions & 16 deletions acp/recenttopics_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ public function main($id, $mode)
trigger_error($language->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
}

// Check the excluded topic IDs before saving anything, so invalid input is reported
// instead of being dropped while the page says the settings were saved (issue #217)
$rt_anti_topics = self::normalise_anti_topics($request->variable('rt_anti_topics', ''));
if ($rt_anti_topics === null)
{
trigger_error($language->lang('RT_ANTI_TOPICS_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
}

/*
* acp options for everyone
*/
Expand All @@ -95,22 +103,8 @@ public function main($id, $mode)
// Show announcements first
$config->set('rt_announcements_first', $request->variable('rt_announcements_first', 0) ? 1 : 0);

// variable should be '' as it is a string ("1, 2, 3928") here, not an integer.
$rt_anti_topics = $request->variable('rt_anti_topics', '');
$ants = explode(',', $rt_anti_topics);
$check_ants = true;
foreach ($ants as $ant)
{
if (!is_numeric($ant))
{
$check_ants = false;
}
}

if ($check_ants)
{
$config->set('rt_anti_topics', $rt_anti_topics);
}
// Excluded topic IDs, already checked above
$config->set('rt_anti_topics', $rt_anti_topics);

$rt_parents = $request->variable('rt_parents', false);
$config->set('rt_parents', $rt_parents);
Expand Down Expand Up @@ -315,6 +309,37 @@ public function main($id, $mode)

}

/**
* Turn the ACP "Excluded topic IDs" input into the value to store (issue #217).
*
* Entries are trimmed and empty ones (a trailing comma, a blank field) are dropped; duplicates
* are removed. An empty result becomes '0', which excludes nothing, so the field can be cleared.
*
* @param string $input Raw comma-separated input, e.g. "7, 9"
* @return string|null Normalised list such as "7,9", or null if an entry is not a whole number
*/
public static function normalise_anti_topics($input)
{
$ids = [];
foreach (explode(',', (string) $input) as $entry)
{
$entry = trim($entry);
if ($entry === '')
{
continue;
}
if (!ctype_digit($entry))
{
return null;
}
$ids[] = (string) (int) $entry;
}

$ids = array_values(array_unique($ids));

return $ids === [] ? '0' : implode(',', $ids);
}

/**
* Retrieve latest version using phpBB's file_downloader
*
Expand Down
1 change: 1 addition & 0 deletions language/ar/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'ينقل الإعلانات والإعلانات العامة في كل صفحة من القائمة إلى أعلى تلك الصفحة. لا تتم إضافة الإعلانات الأقدم غير الموجودة في الصفحة.',
'RT_ANTI_TOPICS' => 'المواضيع المُستبعدة ',
'RT_ANTI_TOPICS_EXP' => 'اكتب علامة الفاصلة ", " بين أرقام المواضيع التي تريد عدم ظهورها في "أحدث المواضيع" ( مثال : 7,9 )',
'RT_ANTI_TOPICS_INVALID' => 'يجب أن تكون معرفات المواضيع المستثناة أرقامًا صحيحة مفصولة بفواصل، مثل 7,9. لم يتم حفظ أي شيء.',
'RT_PARENTS' => 'إظهار المنتدى الأب ',
'RT_PARENTS_EXP' => 'إظهار اسم "المنتدى الأب" في التفاصيل المذكورة تحت اسم الموضوع.',
'RT_TOPIC_LINK_TO' => 'رابط عنوان الموضوع يؤدي إلى',
Expand Down
1 change: 1 addition & 0 deletions language/cs/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Přesune oznámení a globální oznámení na každé stránce seznamu na začátek dané stránky. Starší oznámení, která na stránce nejsou, se nepřidávají.',
'RT_ANTI_TOPICS' => 'Vyloučená témata',
'RT_ANTI_TOPICS_EXP' => 'Identifikátory témat k vyloučení, oddělené čárkou „,“ (příklad: 7,9)<br />',
'RT_ANTI_TOPICS_INVALID' => 'ID vyloučených témat musí být celá čísla oddělená čárkami, například 7,9. Nic nebylo uloženo.',
'RT_PARENTS' => 'Zobrazit nadřazená fóra',
'RT_PARENTS_EXP' => 'Zobrazit nadřazená fóra v řádku podrobností pod názvem nedávného tématu.',
'RT_TOPIC_LINK_TO' => 'Odkaz názvu tématu vede na',
Expand Down
1 change: 1 addition & 0 deletions language/de/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Verschiebt die Bekanntmachungen und globalen Bekanntmachungen auf jeder Seite der Liste an den Anfang dieser Seite. Ältere Bekanntmachungen, die nicht auf der Seite stehen, werden nicht hinzugefügt.',
'RT_ANTI_TOPICS' => 'Ausgeschlossene Themen',
'RT_ANTI_TOPICS_EXP' => 'Gib die Themen-IDs ein, kommagetrennt (z. B. 7,9), andernfalls 0, um alle Themen anzuzeigen (wie in der URL viewtopic.php?t=12345).',
'RT_ANTI_TOPICS_INVALID' => 'Die ausgeschlossenen Themen-IDs müssen ganze Zahlen sein, durch Kommas getrennt, zum Beispiel 7,9. Es wurde nichts gespeichert.',
'RT_PARENTS' => 'Übergeordnete Foren anzeigen',
'RT_PARENTS_EXP' => 'Übergeordnete Foren in der Liste der aktuellen Themen anzeigen.',
'RT_TOPIC_LINK_TO' => 'Thementitel verlinkt auf',
Expand Down
1 change: 1 addition & 0 deletions language/de_x_sie/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Verschiebt die Bekanntmachungen und globalen Bekanntmachungen auf jeder Seite der Liste an den Anfang dieser Seite. Ältere Bekanntmachungen, die nicht auf der Seite stehen, werden nicht hinzugefügt.',
'RT_ANTI_TOPICS' => 'Ausgeschlossene Themen',
'RT_ANTI_TOPICS_EXP' => 'Geben Sie die Themen-IDs ein, kommagetrennt (z. B. 7,9), andernfalls 0, um alle Themen anzuzeigen (wie in der URL viewtopic.php?t=12345).',
'RT_ANTI_TOPICS_INVALID' => 'Die ausgeschlossenen Themen-IDs müssen ganze Zahlen sein, durch Kommas getrennt, zum Beispiel 7,9. Es wurde nichts gespeichert.',
'RT_PARENTS' => 'Übergeordnete Foren anzeigen',
'RT_PARENTS_EXP' => 'Übergeordnete Foren in der Liste der aktuellen Themen anzeigen.',
'RT_TOPIC_LINK_TO' => 'Thementitel verlinkt auf',
Expand Down
1 change: 1 addition & 0 deletions language/en/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Moves the announcements and global announcements on each page of the list to the top of that page. Older announcements that are not on the page are not added.',
'RT_ANTI_TOPICS' => 'Excluded topic IDs',
'RT_ANTI_TOPICS_EXP' => 'The IDs of topics to exclude, separated by “,” (Example: 7,9)<br />The value 0 disables this behaviour.',
'RT_ANTI_TOPICS_INVALID' => 'Excluded topic IDs must be whole numbers separated by commas, for example 7,9. Nothing was saved.',
'RT_PARENTS' => 'Display parent forums',
'RT_PARENTS_EXP' => 'Display parent forums inside the topic row of recent topics.',
'RT_TOPIC_LINK_TO' => 'Topic title links to',
Expand Down
1 change: 1 addition & 0 deletions language/es/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Coloca los anuncios y anuncios globales de cada página de la lista al principio de esa página. Los anuncios más antiguos que no estén en la página no se añaden.',
'RT_ANTI_TOPICS' => 'Temas excluidos',
'RT_ANTI_TOPICS_EXP' => 'Las IDs de los temas a excluir, separados por "," (Por ejemplo: 7,9)<br />Si no quiere excluir un tema, simplemente introduzca 0.',
'RT_ANTI_TOPICS_INVALID' => 'Los ID de temas excluidos deben ser números enteros separados por comas, por ejemplo 7,9. No se ha guardado nada.',
'RT_PARENTS' => 'Mostrar foros padre',
'RT_PARENTS_EXP' => 'Mostrar foros padre dentro de la fila del tema de "Temas Recientes".',
'RT_TOPIC_LINK_TO' => 'El título del tema enlaza a',
Expand Down
1 change: 1 addition & 0 deletions language/es_x_tu/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Coloca los anuncios y anuncios globales de cada página de la lista al principio de esa página. Los anuncios más antiguos que no estén en la página no se añaden.',
'RT_ANTI_TOPICS' => 'Temas excluidos',
'RT_ANTI_TOPICS_EXP' => 'Las IDs de los temas a excluír, separados por "," (Por ejemplo: 7,9)<br />Si no quieres excluir un tema, simplemente introduce 0.',
'RT_ANTI_TOPICS_INVALID' => 'Los ID de temas excluidos deben ser números enteros separados por comas, por ejemplo 7,9. No se ha guardado nada.',
'RT_PARENTS' => 'Mostrar foros padre',
'RT_PARENTS_EXP' => 'Mostrar foros padre dentro de la fila del tema de "Temas Recientes".',
'RT_TOPIC_LINK_TO' => 'El título del tema enlaza a',
Expand Down
1 change: 1 addition & 0 deletions language/fr/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Place les annonces et annonces globales de chaque page de la liste en haut de cette page. Les annonces plus anciennes qui ne figurent pas sur la page ne sont pas ajoutées.',
'RT_ANTI_TOPICS' => 'Exclure des sujets de l’affichage',
'RT_ANTI_TOPICS_EXP' => 'Permet de saisir les ID, séparés par une virgule (exemple : 7,9), des sujets à exclure de l’affichage des sujets récents.<br />Pour afficher tous les sujets saisir la valeur 0.',
'RT_ANTI_TOPICS_INVALID' => 'Les ID des sujets exclus doivent être des nombres entiers séparés par des virgules, par exemple 7,9. Rien n’a été enregistré.',
'RT_PARENTS' => 'Afficher les forums parents',
'RT_PARENTS_EXP' => 'Permet d’afficher les forums parents dans l’arborescence des forums de l’affichage des sujets récents.',
'RT_TOPIC_LINK_TO' => 'Le titre du sujet renvoie vers',
Expand Down
1 change: 1 addition & 0 deletions language/nl/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Plaatst de mededelingen en algemene mededelingen op elke pagina van de lijst bovenaan die pagina. Oudere mededelingen die niet op de pagina staan, worden niet toegevoegd.',
'RT_ANTI_TOPICS' => 'Uitgesloten onderwerpen',
'RT_ANTI_TOPICS_EXP' => 'Vul de onderwerp id’s in (bijvoorbeeld 7,9), anders 0. (deze nummers vind je in de url viewtopic.php?t=12345)',
'RT_ANTI_TOPICS_INVALID' => 'Uitgesloten onderwerp-ID’s moeten gehele getallen zijn, gescheiden door komma’s, bijvoorbeeld 7,9. Er is niets opgeslagen.',
'RT_PARENTS' => 'Weergeven van hoofdforums',
'RT_PARENTS_EXP' => 'Toon de hoofdforums in de onderwerpregel van de recente onderwerpen.',
'RT_TOPIC_LINK_TO' => 'Onderwerptitel linkt naar',
Expand Down
1 change: 1 addition & 0 deletions language/pt/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Coloca os anúncios e anúncios globais de cada página da lista no topo dessa página. Anúncios mais antigos que não estejam na página não são adicionados.',
'RT_ANTI_TOPICS' => 'ID de tópico excluído',
'RT_ANTI_TOPICS_EXP' => 'Os IDs de tópicos a excluir, separados por "," (Exemplo: 7,9) <br />O valor 0 desabilita esse comportamento.',
'RT_ANTI_TOPICS_INVALID' => 'Os IDs dos tópicos excluídos devem ser números inteiros separados por vírgulas, por exemplo 7,9. Nada foi guardado.',
'RT_PARENTS' => 'Mostrar Fórum Pai',
'RT_PARENTS_EXP' => 'Exibir fóruns pai dentro da linha tópico de tópicos recentes.',
'RT_TOPIC_LINK_TO' => 'Título do tópico liga para',
Expand Down
1 change: 1 addition & 0 deletions language/ru/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Перемещает объявления и глобальные объявления на каждой странице списка в начало этой страницы. Более старые объявления, которых нет на странице, не добавляются.',
'RT_ANTI_TOPICS' => 'Исключённые темы',
'RT_ANTI_TOPICS_EXP' => 'Разделённый запятыми список идентификаторов тем, которые не должны отображаться в списке последних тем (например: 7, 9)<br />Установите 0 для отключения данной функции.',
'RT_ANTI_TOPICS_INVALID' => 'ID исключённых тем должны быть целыми числами, разделёнными запятыми, например 7,9. Ничего не сохранено.',
'RT_PARENTS' => 'Показать родительские форумы',
'RT_PARENTS_EXP' => 'Показать родительские форумы внутри тем в блоке последних тем.',
'RT_TOPIC_LINK_TO' => 'Ссылка заголовка темы ведёт на',
Expand Down
1 change: 1 addition & 0 deletions language/sk/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Presunie oznámenia a globálne oznámenia na každej stránke zoznamu na začiatok danej stránky. Staršie oznámenia, ktoré na stránke nie sú, sa nepridávajú.',
'RT_ANTI_TOPICS' => 'Vylúčené témy',
'RT_ANTI_TOPICS_EXP' => 'ID tém na vylúčenie, oddelené čiarkou „," (príklad: 7,9)<br />Hodnota 0 túto funkciu vypne.',
'RT_ANTI_TOPICS_INVALID' => 'ID vylúčených tém musia byť celé čísla oddelené čiarkami, napríklad 7,9. Nič nebolo uložené.',
'RT_PARENTS' => 'Zobraziť nadradené fóra',
'RT_PARENTS_EXP' => 'Zobraziť nadradené fóra v riadku podrobností pod názvom najnovšej témy.',
'RT_TOPIC_LINK_TO' => 'Odkaz názvu témy vedie na',
Expand Down
1 change: 1 addition & 0 deletions language/sv/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Flyttar meddelanden och globala meddelanden på varje sida i listan överst på den sidan. Äldre meddelanden som inte finns på sidan läggs inte till.',
'RT_ANTI_TOPICS' => 'Exkluderade tråd-ID:n',
'RT_ANTI_TOPICS_EXP' => 'ID:n för trådar att exkludera, separerade med "," (Exempel: 7,9)<br />Värdet 0 inaktiverar denna funktion.',
'RT_ANTI_TOPICS_INVALID' => 'Uteslutna tråd-ID:n måste vara heltal åtskilda med kommatecken, till exempel 7,9. Inget sparades.',
'RT_PARENTS' => 'Visa överordnade forum',
'RT_PARENTS_EXP' => 'Visa överordnade forum i trådraden för senaste trådar.',
'RT_TOPIC_LINK_TO' => 'Trådtiteln länkar till',
Expand Down
1 change: 1 addition & 0 deletions language/uk/info_acp_recenttopics.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'RT_ANNOUNCEMENTS_FIRST_EXP' => 'Переміщує оголошення та глобальні оголошення на кожній сторінці списку на початок цієї сторінки. Старіші оголошення, яких немає на сторінці, не додаються.',
'RT_ANTI_TOPICS' => 'Не відображати теми з вказаними ID',
'RT_ANTI_TOPICS_EXP' => 'Теми з вказаними ID будуть виключені зі списку відображення. Кожен ID теми має бути розділений комою “,” (Наприклад: 7,9)<br />Значення "0" деактивує цей список виключення.',
'RT_ANTI_TOPICS_INVALID' => 'ID виключених тем мають бути цілими числами, розділеними комами, наприклад 7,9. Нічого не збережено.',
'RT_PARENTS' => 'Відображати батьківські форуми',
'RT_PARENTS_EXP' => 'Відображати батьківські форуми в рядку теми.',
'RT_TOPIC_LINK_TO' => 'Посилання заголовка теми веде на',
Expand Down
47 changes: 47 additions & 0 deletions tests/acp/anti_topics_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
*
* @package Recent Topics Extension
* @copyright (c) 2026 Andreas Vandenberghe
* @license GNU General Public License, version 2 (GPL-2.0)
*
* Tests for the ACP "Excluded topic IDs" input (rt_anti_topics).
*
* See: https://github.com/avatharbe/RecentTopics/issues/217
*/

namespace avathar\recenttopics\tests\acp;

class anti_topics_test extends \phpbb_test_case
{
/**
* Raw ACP input => value to store, or null when the input must be rejected.
*/
public function anti_topics_data()
{
return [
'single id' => ['7', '7'],
'list' => ['7,9', '7,9'],
'spaces are trimmed' => [' 7 , 9 ', '7,9'],
'duplicates are dropped' => ['7,9,7', '7,9'],
'trailing comma is ignored' => ['7,9,', '7,9'],
'empty field excludes nothing' => ['', '0'],
'blank field excludes nothing' => [' ', '0'],
'zero keeps meaning nothing' => ['0', '0'],
'text is rejected' => ['7,abc', null],
'decimal is rejected' => ['7.5', null],
'negative is rejected' => ['-3', null],
];
}

/**
* Clearing the field must be possible and invalid entries must be reported, not silently
* dropped while the ACP says the settings were saved (#217).
*
* @dataProvider anti_topics_data
*/
public function test_normalise_anti_topics($input, $expected)
{
$this->assertSame($expected, \avathar\recenttopics\acp\recenttopics_module::normalise_anti_topics($input));
}
}
50 changes: 50 additions & 0 deletions tests/functional/recenttopics_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,42 @@ public function test_acp_saves_announcements_first()
$this->set_config('rt_announcements_first', 0);
}

/**
* Invalid "Excluded topic IDs" input is reported and nothing is saved (#217).
*/
public function test_acp_rejects_invalid_anti_topics()
{
$this->login();
$this->admin_login();
$this->add_lang_ext('avathar/recenttopics', 'info_acp_recenttopics');
$this->set_config('rt_anti_topics', '7');

$crawler = self::request('GET', $this->acp_module_url());
$form = $crawler->selectButton('submit')->form();
$form['rt_anti_topics'] = '7,abc';
$crawler = self::submit($form);

$this->assertStringContainsString($this->lang('RT_ANTI_TOPICS_INVALID'), $crawler->text());
$this->assertSame('7', $this->get_config_value('rt_anti_topics'), 'An invalid list must not be saved');
}

/**
* Clearing "Excluded topic IDs" is saved as 0, excluding nothing (#217).
*/
public function test_acp_clears_anti_topics()
{
$this->login();
$this->admin_login();
$this->set_config('rt_anti_topics', '7');

$crawler = self::request('GET', $this->acp_module_url());
$form = $crawler->selectButton('submit')->form();
$form['rt_anti_topics'] = '';
self::submit($form);

$this->assertSame('0', $this->get_config_value('rt_anti_topics'), 'An empty field must clear the list');
}

// -----------------------------------------------------------------------
// Helper
// -----------------------------------------------------------------------
Expand All @@ -275,6 +311,20 @@ private function acp_module_url()
return 'adm/index.php?i=-avathar-recenttopics-acp-recenttopics_module&mode=recenttopics_config&sid=' . $this->sid;
}

/**
* Read a phpBB config value straight from the database.
*/
private function get_config_value($name)
{
$db = $this->get_db();

$result = $db->sql_query("SELECT config_value FROM phpbb_config WHERE config_name = '" . $db->sql_escape($name) . "'");
$value = $db->sql_fetchfield('config_value');
$db->sql_freeresult($result);

return (string) $value;
}

/**
* Read the admin account's stored topics-per-page preference.
*/
Expand Down
Loading
Loading