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
6 changes: 4 additions & 2 deletions acp/recenttopics_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class recenttopics_module
*/
public function main($id, $mode)
{
global $phpbb_container;
global $phpbb_container, $phpbb_root_path;

$config = $phpbb_container->get('config');
$request = $phpbb_container->get('request');
Expand Down Expand Up @@ -298,7 +298,9 @@ public function main($id, $mode)
'RT_SHOW_LIKES' => (int) $config['rt_show_likes'],
'RT_SIDE_SHOW_DATE' => (int) $config['rt_side_show_date'],
'S_POSTLOVE' => $phpbb_container->has('avathar.postlove.topic_likes'),
'S_RT_OK' => version_compare($ext_version, $latest_version, '=='),
// Bundled copy, so the ACP page makes no request to Patreon's CDN (issue #200)
'U_PATREON_BUTTON' => $phpbb_root_path . 'ext/avathar/recenttopics/adm/style/images/become_a_patron_button.png',
'S_RT_OK' => version_compare($ext_version, $latest_version, '=='),
'S_RT_OLD' => version_compare($ext_version, $latest_version, '<'),
'S_RT_DEV' => version_compare($ext_version, $latest_version, '>'),
'EXT_VERSION' => $ext_version,
Expand Down
2 changes: 1 addition & 1 deletion adm/style/acp_recenttopics.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ <h1>{{ lang('RECENT_TOPICS') }}</h1>
<legend>{{ lang('RT_DONATE') }}</legend>
<dl>
<dt><label>{{ lang('RT_DONATE_SHORT') }}{{ lang('COLON') }}</label><br /><span>{{ lang('RT_DONATE_EXPLAIN') }}</span></dt>
<dd><a href="https://www.patreon.com/cw/avathar/membership" target="_blank"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" border="0" alt="{{ lang('PATREON_ALT')|e('html_attr') }}" style="cursor:pointer"></a></dd>
<dd><a href="https://www.patreon.com/cw/avathar/membership" target="_blank"><img src="{{ U_PATREON_BUTTON }}" border="0" alt="{{ lang('PATREON_ALT')|e('html_attr') }}" style="cursor:pointer"></a></dd>
</dl>
</fieldset>

Expand Down
Binary file added adm/style/images/become_a_patron_button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions tests/acp/acp_template_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)
*
* Static checks on the ACP template's assets.
*
* See: https://github.com/avatharbe/RecentTopics/issues/200
*/

namespace avathar\recenttopics\tests\acp;

class acp_template_test extends \phpbb_test_case
{
/** @var string Extension root */
private $ext_root;

protected function setUp(): void
{
parent::setUp();
$this->ext_root = dirname(__DIR__, 2);
}

/**
* Opening the ACP page must not make the admin's browser call Patreon's CDN (#200).
*/
public function test_acp_template_loads_no_external_patreon_image()
{
$template = file_get_contents($this->ext_root . '/adm/style/acp_recenttopics.html');

$this->assertStringNotContainsString('patreon.com/external', $template);
$this->assertStringContainsString('{{ U_PATREON_BUTTON }}', $template);
}

/**
* The bundled button the template points to ships with the extension.
*/
public function test_patreon_button_is_bundled()
{
$file = $this->ext_root . '/adm/style/images/become_a_patron_button.png';

$this->assertFileExists($file);
$this->assertSame('image/png', mime_content_type($file));
}
}
19 changes: 19 additions & 0 deletions tests/functional/recenttopics_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,25 @@ public function test_acp_reset_works_with_valid_form_token()
'Submitting the genuine ACP form must still reset user preferences');
}

/**
* The ACP donate button uses the extension's bundled image, not Patreon's CDN,
* and that image is actually served (#200).
*/
public function test_acp_patreon_button_is_local()
{
$this->login();
$this->admin_login();

$crawler = self::request('GET', $this->acp_module_url());
$src = $crawler->filter('a[href*="patreon.com"] img')->attr('src');

$this->assertStringNotContainsString('patreon.com', $src);
$this->assertStringEndsWith('ext/avathar/recenttopics/adm/style/images/become_a_patron_button.png', $src);

self::request('GET', 'ext/avathar/recenttopics/adm/style/images/become_a_patron_button.png', array(), false);
$this->assertSame(200, self::$client->getResponse()->getStatus());
}

// -----------------------------------------------------------------------
// Helper
// -----------------------------------------------------------------------
Expand Down
20 changes: 19 additions & 1 deletion tests/tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ phpBB fires named events as it runs (see `contrib/events.md`). An event dispatch

```
tests/
├── acp/
│ └── acp_template_test.php ACP template assets (no external images)
├── event/
│ ├── listener_test.php Main event listener (board index, ACP, WOL, permissions)
│ └── ucp_listener_test.php UCP preferences listener
Expand Down Expand Up @@ -224,7 +226,22 @@ It loads `recenttopics.php` from every language pack and checks that `VIEWING_RE

---

## 9. Functional tests (`functional/recenttopics_test.php`)
## 9. ACP template assets (`acp/acp_template_test.php`)

**What this code does:**
The ACP page shows a "Become a patron" button. The image ships with the extension (`adm/style/images/become_a_patron_button.png`), and the ACP module passes its URL to the template as `U_PATREON_BUTTON`.

**What this test file does:**
It reads the template and the image straight from disk.

| Test | Scenario | What it verifies |
|------|----------|-----------------|
| `test_acp_template_loads_no_external_patreon_image` | `adm/style/acp_recenttopics.html` | No `patreon.com/external` URL; the image uses `{{ U_PATREON_BUTTON }}`. Before the fix every ACP page view made the admin's browser call Patreon's CDN (#200) |
| `test_patreon_button_is_bundled` | `adm/style/images/become_a_patron_button.png` | The file exists and is a PNG |

---

## 10. Functional tests (`functional/recenttopics_test.php`)

**What this code does:**
These tests start a real phpBB installation (using the test framework's built-in install), enable the extension, and make HTTP requests using a real browser-like crawler (Symfony DomCrawler). They check the actual rendered HTML for specific elements.
Expand All @@ -240,6 +257,7 @@ Logs in as the admin account, optionally creates topics or changes config values
| `test_rt_simple_page` | `rt_page_enable` = 1; GET `/app.php/rt/simple` | `<a id="recent-topics">` is present |
| `test_rt_page_disabled` | `rt_page_enable` = 0; GET `/app.php/rt` | Page still loads (no 500 error); `<a id="recent-topics">` is present; `#recent-topics-box` must NOT appear |
| `test_index_has_recent_topics` | `rt_index` = 1; create a topic; GET `index.php` | `<a id="recent-topics">` is present; `#recent-topics-box` contains the created topic title |
| `test_acp_patreon_button_is_local` | Logged in as admin; GET the Recent Topics ACP page | The Patreon button's `src` is the bundled image, not `patreon.com`, and that image URL returns 200 (#200) |
| `test_ucp_preferences` | Logged in as admin; GET `/ucp.php?i=ucp_prefs&mode=view` | `input[name="rt_enable"]` and `input[name="rt_number"]` are present on the preferences page |

---
Expand Down
Loading