diff --git a/adm/style/wpn_acp_pwa.html b/adm/style/wpn_acp_pwa.html index bf45709..3b2542c 100644 --- a/adm/style/wpn_acp_pwa.html +++ b/adm/style/wpn_acp_pwa.html @@ -18,6 +18,11 @@

{{ lang('WARNING') }}

{{ lang('GENERAL_SETTINGS') }} +
+

{{ lang('PWA_METADATA_ENABLED_EXPLAIN') }}
+
+
+

{{ lang('PWA_SHORT_NAME_EXPLAIN') }}
diff --git a/composer.json b/composer.json index 926ed34..6e3c08c 100644 --- a/composer.json +++ b/composer.json @@ -42,6 +42,9 @@ "ext-gmp": "Optional but better for performance" }, "config": { + "platform": { + "php": "7.3" + }, "allow-plugins": { "composer/installers": true } diff --git a/composer.lock b/composer.lock index 9dabe15..fc5fc63 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bc026c93f95601aa865acfd69042c74e", + "content-hash": "e5c2801135f7590ea563271378cbaff2", "packages": [ { "name": "brick/math", @@ -295,22 +295,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.15.5", + "version": "7.16.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "ee80339fd9177ba44c49cdb653ff02a4d1106b9a" + "reference": "81755d989b3007ca7f88a069857553cd08e7dc2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ee80339fd9177ba44c49cdb653ff02a4d1106b9a", - "reference": "ee80339fd9177ba44c49cdb653ff02a4d1106b9a", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/81755d989b3007ca7f88a069857553cd08e7dc2e", + "reference": "81755d989b3007ca7f88a069857553cd08e7dc2e", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^2.5.3", - "guzzlehttp/psr7": "^2.13.1", + "guzzlehttp/promises": "^2.6", + "guzzlehttp/psr7": "^2.13.2", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", @@ -403,7 +403,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.15.5" + "source": "https://github.com/guzzle/guzzle/tree/7.16.1" }, "funding": [ { @@ -419,20 +419,20 @@ "type": "tidelift" } ], - "time": "2026-08-24T09:21:06+00:00" + "time": "2026-10-25T21:35:21+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.5.3", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "cde49999552d185d64715fe9c1f77a2aadd2f9f1" + "reference": "3d88c829bd5f13d13847b39067dbf09a60af2154" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/cde49999552d185d64715fe9c1f77a2aadd2f9f1", - "reference": "cde49999552d185d64715fe9c1f77a2aadd2f9f1", + "url": "https://api.github.com/repos/guzzle/promises/zipball/3d88c829bd5f13d13847b39067dbf09a60af2154", + "reference": "3d88c829bd5f13d13847b39067dbf09a60af2154", "shasum": "" }, "require": { @@ -487,7 +487,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.5.3" + "source": "https://github.com/guzzle/promises/tree/2.6.0" }, "funding": [ { @@ -503,20 +503,20 @@ "type": "tidelift" } ], - "time": "2026-08-24T09:11:28+00:00" + "time": "2026-10-18T12:46:59+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.13.1", + "version": "2.13.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "95e7828100de18b4e269fb1703be530082d5166d" + "reference": "adee536f95101929f262b8c59e8a61472f347d58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/95e7828100de18b4e269fb1703be530082d5166d", - "reference": "95e7828100de18b4e269fb1703be530082d5166d", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/adee536f95101929f262b8c59e8a61472f347d58", + "reference": "adee536f95101929f262b8c59e8a61472f347d58", "shasum": "" }, "require": { @@ -606,7 +606,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.13.1" + "source": "https://github.com/guzzle/psr7/tree/2.13.2" }, "funding": [ { @@ -622,7 +622,7 @@ "type": "tidelift" } ], - "time": "2026-08-24T09:13:11+00:00" + "time": "2026-10-17T23:49:46+00:00" }, { "name": "minishlink/web-push", @@ -1600,7 +1600,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -1610,6 +1610,9 @@ "ext-mbstring": "*", "ext-openssl": "*" }, - "platform-dev": {}, - "plugin-api-version": "2.9.0" + "platform-dev": [], + "platform-overrides": { + "php": "7.3" + }, + "plugin-api-version": "2.6.0" } diff --git a/controller/acp_controller.php b/controller/acp_controller.php index fc0e6db..8fceae6 100644 --- a/controller/acp_controller.php +++ b/controller/acp_controller.php @@ -249,6 +249,7 @@ protected function save_settings() protected function display_pwa_settings() { $this->template->assign_vars([ + 'S_PWA_METADATA_ENABLED' => (bool) $this->config['pwa_metadata_enabled'], 'S_PWA_SHOW_INSTALL_BANNER' => (bool) $this->config['pwa_show_install_banner'], 'PWA_SHORT_NAME' => $this->config['pwa_short_name'], 'PWA_SHORT_NAME_PLACEHOLDER'=> utf8_substr(ext::decode_entities($this->config['sitename'], ENT_QUOTES), 0, 12), @@ -307,6 +308,7 @@ protected function save_pwa_settings() $config_array['pwa_short_name'] = utf8_encode_ucr($config_array['pwa_short_name']); foreach ([ + 'pwa_metadata_enabled', 'pwa_short_name', 'pwa_icon_small', 'pwa_icon_large', diff --git a/event/listener.php b/event/listener.php index 6be2e18..ccd3f58 100644 --- a/event/listener.php +++ b/event/listener.php @@ -170,6 +170,7 @@ public function compatibility_notice() public function pwa_manifest() { $this->template->assign_vars([ + 'S_PWA_METADATA_ENABLED' => !empty($this->config['pwa_metadata_enabled']), 'U_MANIFEST_URL' => $this->controller_helper->route('phpbb_webpushnotifications_manifest_controller'), 'U_TOUCH_ICON' => $this->config['pwa_icon_small'] ? ext::PWA_ICON_DIR . '/' . $this->config['pwa_icon_small'] : null, 'SHORT_SITE_NAME' => $this->config['pwa_short_name'] ?: $this->trim_shortname($this->config['sitename']), diff --git a/language/en/webpushnotifications_module_acp.php b/language/en/webpushnotifications_module_acp.php index 14b6360..18c732b 100644 --- a/language/en/webpushnotifications_module_acp.php +++ b/language/en/webpushnotifications_module_acp.php @@ -72,6 +72,8 @@ // PWA Settings 'ACP_PWA_SETTINGS_EXPLAIN' => 'Progressive Web Apps (PWAs) allow users to install your board on their mobile device and use it like an app. These settings control the app name, icons, colours, and install prompts shown to users.', + 'PWA_METADATA_ENABLED' => 'Output PWA metadata', + 'PWA_METADATA_ENABLED_EXPLAIN'=> 'Output the web app manifest link and related PWA metadata in the page header. Disable this if another extension or your style already provides the board’s PWA metadata. This does not disable Web Push or the app install banner.', 'PWA_SHORT_NAME' => 'Short site name', 'PWA_SHORT_NAME_EXPLAIN' => 'Your site name in 12 characters or fewer, which may be used as a label for an icon on a mobile device’s home screen. (If this field is left empty, the first 12 characters of the Site name will be used.)', 'PWA_SHORT_NAME_INVALID' => '“Short site name” exceeds the 12 character limit.', diff --git a/language/ru/webpushnotifications_module_acp.php b/language/ru/webpushnotifications_module_acp.php index 4d53b52..734c8f5 100644 --- a/language/ru/webpushnotifications_module_acp.php +++ b/language/ru/webpushnotifications_module_acp.php @@ -72,6 +72,8 @@ // PWA Settings 'ACP_PWA_SETTINGS_EXPLAIN' => 'Здесь вы можете настроить функции прогрессивного веб-приложения (PWA), включая метаданные приложения, значки, цвета темы и приглашения к установке.', + 'PWA_METADATA_ENABLED' => 'Выводить метаданные PWA', + 'PWA_METADATA_ENABLED_EXPLAIN'=> 'Вывод ссылки на манифест и метаданных прогрессивного веб-приложения (PWA) в коде заголовков страниц конференции. Отключите, если другое расширение или стиль уже выводят такие данные. При этом браузерные push-уведомления и баннер установки прогрессивного веб-приложения (PWA) не будут отключены.', 'PWA_SHORT_NAME' => 'Краткое название сайта', 'PWA_SHORT_NAME_EXPLAIN' => 'Название сайта длиной не более 12 символов, которое может использоваться как подпись к значку на главном экране мобильного устройства. (Если оставить это поле пустым, будут использованы первые 12 символов значения Название сайта.)', 'PWA_SHORT_NAME_INVALID' => 'Значение поля «Краткое название сайта» превышает ограничение в 12 символов.', diff --git a/migrations/add_pwa_metadata_toggle.php b/migrations/add_pwa_metadata_toggle.php new file mode 100644 index 0000000..ba22472 --- /dev/null +++ b/migrations/add_pwa_metadata_toggle.php @@ -0,0 +1,40 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + */ + +namespace phpbb\webpushnotifications\migrations; + +use phpbb\db\migration\migration; + +class add_pwa_metadata_toggle extends migration +{ + public function effectively_installed(): bool + { + return $this->config->offsetExists('pwa_metadata_enabled'); + } + + public static function depends_on() + { + return ['\phpbb\webpushnotifications\migrations\add_pwa_enhancer_schema']; + } + + public function update_data(): array + { + return [ + ['config.add', ['pwa_metadata_enabled', 1]], + ]; + } + + public function revert_data(): array + { + return [ + ['config.remove', ['pwa_metadata_enabled']], + ]; + } +} diff --git a/styles/all/template/event/overall_header_head_append.html b/styles/all/template/event/overall_header_head_append.html index 300026c..b7bd43d 100644 --- a/styles/all/template/event/overall_header_head_append.html +++ b/styles/all/template/event/overall_header_head_append.html @@ -1,15 +1,17 @@ - - - - -{% if PWA_THEME_COLOR %} - - -{% endif %} +{% if S_PWA_METADATA_ENABLED %} + + + + + {% if PWA_THEME_COLOR %} + + + {% endif %} - -{% if U_TOUCH_ICON %}{% endif %} + + {% if U_TOUCH_ICON %}{% endif %} +{% endif %} {% if NOTIFICATIONS_WEBPUSH_ENABLE %} {% include '@phpbb_webpushnotifications/ucp_notifications_webpush.html' %} diff --git a/tests/controller/controller_acp_test.php b/tests/controller/controller_acp_test.php index 25b087e..b8c478c 100644 --- a/tests/controller/controller_acp_test.php +++ b/tests/controller/controller_acp_test.php @@ -376,6 +376,7 @@ public function test_save_settings_ignores_unrelated_config(): void public function pwa_save_data(): array { $valid = [ + 'pwa_metadata_enabled' => 0, 'pwa_short_name' => 'Forum', 'pwa_icon_small' => 'icon192.png', 'pwa_icon_large' => 'icon512.png', @@ -413,6 +414,7 @@ public function pwa_save_data(): array 'ERROR_MSG' => '', ], [ + 'pwa_metadata_enabled' => 0, 'pwa_short_name' => 'Forum', 'pwa_icon_small' => 'icon192.png', 'pwa_icon_large' => 'icon512.png', @@ -430,6 +432,7 @@ public function pwa_save_data(): array 'ERROR_MSG' => '', ], [ + 'pwa_metadata_enabled' => 0, 'pwa_short_name' => '', 'pwa_icon_small' => '', 'pwa_icon_large' => '', @@ -460,6 +463,7 @@ public function pwa_save_data(): array 'ERROR_MSG' => '', ], [ + 'pwa_metadata_enabled' => 0, 'pwa_short_name' => 'Forum', 'pwa_icon_small' => 'icon192.png', 'pwa_icon_large' => 'icon512.png', @@ -770,6 +774,7 @@ protected function default_config(): array 'wpn_webpush_method_enabled' => 1, 'wpn_webpush_popup_prompt' => 1, 'pwa_show_install_banner' => 1, + 'pwa_metadata_enabled' => 1, 'pwa_short_name' => 'Old', 'pwa_icon_small' => 'old-small.png', 'pwa_icon_large' => 'old-large.png', @@ -811,6 +816,7 @@ protected function webpush_template_vars($u_action): array protected function pwa_template_vars($u_action): array { return [ + 'S_PWA_METADATA_ENABLED' => true, 'S_PWA_SHOW_INSTALL_BANNER' => true, 'PWA_SHORT_NAME' => 'Old', 'PWA_SHORT_NAME_PLACEHOLDER' => 'Board & 😀 Fo', diff --git a/tests/event/listener_test.php b/tests/event/listener_test.php index 438f3ae..8f6758b 100644 --- a/tests/event/listener_test.php +++ b/tests/event/listener_test.php @@ -98,6 +98,7 @@ protected function setUp(): void 'sitename' => 'phpBB', 'cookie_name' => 'phpbb3', 'pwa_show_install_banner' => true, + 'pwa_metadata_enabled' => true, 'pwa_icon_small' => '', 'pwa_icon_large' => '', 'pwa_short_name' => '', @@ -387,6 +388,7 @@ public function test_pwa_manifest() $this->template->expects(self::once()) ->method('assign_vars') ->with([ + 'S_PWA_METADATA_ENABLED' => true, 'U_MANIFEST_URL' => $this->controller_helper->route('phpbb_webpushnotifications_manifest_controller'), 'U_TOUCH_ICON' => ext::PWA_ICON_DIR . '/icon-192x192.png', 'SHORT_SITE_NAME' => 'Test', @@ -412,6 +414,7 @@ public function test_load_template_data_returns_when_notifications_unavailable() public function test_pwa_manifest_builds_fallback_name_and_mobile_banner() { $this->config['sitename'] = 'Long & Mobile Site'; + $this->config['pwa_metadata_enabled'] = false; $this->user->style = [ 'pwa_theme_color' => '#112233', 'pwa_bg_color' => '#445566', @@ -419,6 +422,7 @@ public function test_pwa_manifest_builds_fallback_name_and_mobile_banner() $this->request->method('server')->with('HTTP_USER_AGENT', '')->willReturn('Mozilla/5.0 iPhone Mobile'); $this->template->expects(self::once())->method('assign_vars')->with([ + 'S_PWA_METADATA_ENABLED' => false, 'U_MANIFEST_URL' => $this->controller_helper->route('phpbb_webpushnotifications_manifest_controller'), 'U_TOUCH_ICON' => null, 'SHORT_SITE_NAME' => 'Long & Mobil', diff --git a/tests/functional/functional_test.php b/tests/functional/functional_test.php index ebebc27..f2d0da6 100644 --- a/tests/functional/functional_test.php +++ b/tests/functional/functional_test.php @@ -177,6 +177,25 @@ public function test_manifest() $this->assertEquals(json_encode($expected), self::get_content()); } + public function test_pwa_metadata_output_can_be_disabled() + { + $this->login(); + $this->admin_login(); + + $crawler = self::request('GET', 'index.php'); + $this->assertCount(1, $crawler->filter('link[rel="manifest"]')); + $this->assertCount(1, $crawler->filter('meta[name="apple-mobile-web-app-capable"]')); + + $this->set_pwa_option('pwa_metadata_enabled', 0); + + $crawler = self::request('GET', 'index.php'); + $this->assertCount(0, $crawler->filter('link[rel="manifest"]')); + $this->assertCount(0, $crawler->filter('meta[name="mobile-web-app-capable"]')); + $this->assertCount(0, $crawler->filter('meta[name="apple-mobile-web-app-capable"]')); + + $this->set_pwa_option('pwa_metadata_enabled', 1); + } + public function test_popup_prompt() { $this->login(); @@ -259,4 +278,15 @@ protected function set_acp_option($option, $value) $crawler = self::submit($form); $this->assertEquals(1, $crawler->filter('.successbox')->count()); } + + protected function set_pwa_option($option, $value) + { + $crawler = self::request('GET', 'adm/index.php?i=-phpbb-webpushnotifications-acp-wpn_acp_module&mode=pwa&sid=' . $this->sid); + $form = $crawler->selectButton('submit')->form(); + $values = $form->getValues(); + $values["config[{$option}]"] = $value; + $form->setValues($values); + $crawler = self::submit($form); + $this->assertEquals(1, $crawler->filter('.successbox')->count()); + } }