diff --git a/acp/recenttopics_module.php b/acp/recenttopics_module.php index 8b0efa0..11d9655 100644 --- a/acp/recenttopics_module.php +++ b/acp/recenttopics_module.php @@ -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'); @@ -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, diff --git a/adm/style/acp_recenttopics.html b/adm/style/acp_recenttopics.html index ba24c1b..99d54d3 100644 --- a/adm/style/acp_recenttopics.html +++ b/adm/style/acp_recenttopics.html @@ -171,7 +171,7 @@

{{ lang('RECENT_TOPICS') }}

{{ lang('RT_DONATE') }}

{{ lang('RT_DONATE_EXPLAIN') }}
-
{{ lang('PATREON_ALT')|e('html_attr') }}
+
{{ lang('PATREON_ALT')|e('html_attr') }}
diff --git a/adm/style/images/become_a_patron_button.png b/adm/style/images/become_a_patron_button.png new file mode 100644 index 0000000..291b7bc Binary files /dev/null and b/adm/style/images/become_a_patron_button.png differ diff --git a/tests/acp/acp_template_test.php b/tests/acp/acp_template_test.php new file mode 100644 index 0000000..de04d01 --- /dev/null +++ b/tests/acp/acp_template_test.php @@ -0,0 +1,47 @@ +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)); + } +} diff --git a/tests/functional/recenttopics_test.php b/tests/functional/recenttopics_test.php index 0e30330..701124c 100644 --- a/tests/functional/recenttopics_test.php +++ b/tests/functional/recenttopics_test.php @@ -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 // ----------------------------------------------------------------------- diff --git a/tests/tests.md b/tests/tests.md index f5b9346..3c71767 100644 --- a/tests/tests.md +++ b/tests/tests.md @@ -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 @@ -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. @@ -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` | `` is present | | `test_rt_page_disabled` | `rt_page_enable` = 0; GET `/app.php/rt` | Page still loads (no 500 error); `` is present; `#recent-topics-box` must NOT appear | | `test_index_has_recent_topics` | `rt_index` = 1; create a topic; GET `index.php` | `` 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 | ---