From 1738eeda3ad9900d966d9813ce0607cd66938e9a Mon Sep 17 00:00:00 2001 From: Tsvetan Stoychev Date: Wed, 26 Aug 2026 19:17:57 +0200 Subject: [PATCH 1/3] Scope Basicrum admin notices --- plugins/basicrum/basicrum.php | 4 +- plugins/basicrum/src/Admin/Settings/Page.php | 14 ++-- plugins/basicrum/tests/unit/BootstrapTest.php | 25 ++++++- .../basicrum/tests/unit/SettingsPageTest.php | 74 +++++++++++++------ 4 files changed, 81 insertions(+), 36 deletions(-) diff --git a/plugins/basicrum/basicrum.php b/plugins/basicrum/basicrum.php index f2e6cfc..6d36603 100644 --- a/plugins/basicrum/basicrum.php +++ b/plugins/basicrum/basicrum.php @@ -28,7 +28,9 @@ if ( ! is_readable( $basicrum_autoloader ) ) { $basicrum_missing_autoloader_notice = static function () { - if ( ! current_user_can( 'activate_plugins' ) ) { + global $pagenow; + + if ( 'plugins.php' !== $pagenow || ! current_user_can( 'activate_plugins' ) ) { return; } diff --git a/plugins/basicrum/src/Admin/Settings/Page.php b/plugins/basicrum/src/Admin/Settings/Page.php index 2e54f6a..eee70de 100644 --- a/plugins/basicrum/src/Admin/Settings/Page.php +++ b/plugins/basicrum/src/Admin/Settings/Page.php @@ -53,7 +53,6 @@ class Page { public function __construct() { add_action( 'admin_menu', array( $this, 'add_menu_page' ) ); add_action( 'admin_init', array( $this, 'register_settings' ) ); - add_action( 'admin_notices', array( $this, 'admin_notices' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) ); } @@ -531,6 +530,7 @@ class="basicrum-settings-logo" />

+ render_settings_notices(); ?>
add_required_settings_notice(); - } - + private function render_settings_notices() { + $this->add_required_settings_notice(); settings_errors(); } diff --git a/plugins/basicrum/tests/unit/BootstrapTest.php b/plugins/basicrum/tests/unit/BootstrapTest.php index 29fec42..b7f2823 100644 --- a/plugins/basicrum/tests/unit/BootstrapTest.php +++ b/plugins/basicrum/tests/unit/BootstrapTest.php @@ -15,7 +15,7 @@ class BootstrapTest extends TestCase { /** - * Ensure a missing Composer autoloader produces an administrator notice. + * Ensure a missing Composer autoloader warns only on plugin screens. * * The bootstrap is executed in a separate PHP process because it defines * plugin constants and returns early when the autoloader is unavailable. @@ -33,6 +33,7 @@ public function test_missing_composer_autoloader_registers_admin_notice() { $runner = <<<'PHP' define( 'ABSPATH', sys_get_temp_dir() . '/' ); $GLOBALS['basicrum_test_actions'] = array(); +$GLOBALS['pagenow'] = 'index.php'; function plugin_dir_path( $file ) { return dirname( $file ) . DIRECTORY_SEPARATOR; @@ -57,12 +58,28 @@ function current_user_can( $capability ) { exit( 1 ); } +if ( ! isset( $GLOBALS['basicrum_test_actions']['network_admin_notices'] ) ) { + fwrite( STDERR, "Missing network admin notice callback.\n" ); + exit( 1 ); +} + +ob_start(); +call_user_func( $GLOBALS['basicrum_test_actions']['admin_notices'] ); +$dashboard_notice = ob_get_clean(); + +if ( '' !== $dashboard_notice ) { + fwrite( STDERR, "Unexpected dashboard notice: $dashboard_notice\n" ); + exit( 1 ); +} + +$GLOBALS['pagenow'] = 'plugins.php'; + ob_start(); call_user_func( $GLOBALS['basicrum_test_actions']['admin_notices'] ); -$notice = ob_get_clean(); +$plugins_notice = ob_get_clean(); -if ( false === strpos( $notice, 'Composer dependencies are missing' ) ) { - fwrite( STDERR, "Unexpected admin notice: $notice\n" ); +if ( false === strpos( $plugins_notice, 'Composer dependencies are missing' ) ) { + fwrite( STDERR, "Unexpected Plugins-screen notice: $plugins_notice\n" ); exit( 1 ); } PHP; diff --git a/plugins/basicrum/tests/unit/SettingsPageTest.php b/plugins/basicrum/tests/unit/SettingsPageTest.php index affe38e..4055c70 100644 --- a/plugins/basicrum/tests/unit/SettingsPageTest.php +++ b/plugins/basicrum/tests/unit/SettingsPageTest.php @@ -51,22 +51,10 @@ public function test_hidden_error_icon_has_explicit_display_rule() { * Test the settings page renders the packaged Basicrum logo. */ public function test_settings_page_renders_brand_logo() { - Functions\when( 'plugins_url' )->alias( - function( $path ) { - return 'https://example.com/wp-content/plugins/basicrum/' . $path; - } - ); - Functions\expect( 'current_user_can' )->once()->with( 'manage_options' )->andReturn( true ); - Functions\when( 'get_admin_page_title' )->justReturn( 'Basicrum Settings' ); - Functions\when( 'settings_fields' )->justReturn(); - Functions\when( 'do_settings_sections' )->justReturn(); - Functions\when( 'submit_button' )->justReturn(); - - $page = new Page(); + $this->set_settings( array( 'enabled' => '0' ) ); + Functions\expect( 'settings_errors' )->once(); - ob_start(); - $page->render_settings_page(); - $html = ob_get_clean(); + $html = $this->render_settings_page_html(); $this->assertStringContainsString( 'class="basicrum-settings-header"', $html ); $this->assertStringContainsString( 'class="basicrum-settings-logo"', $html ); @@ -76,6 +64,26 @@ function( $path ) { $this->assertStringContainsString( 'height="48"', $html ); } + /** + * Test settings notices are not registered across the administration area. + */ + public function test_settings_notices_are_not_hooked_globally() { + $hooks = array(); + + Functions\when( 'add_action' )->alias( + function( $hook_name ) use ( &$hooks ) { + $hooks[] = $hook_name; + } + ); + + new Page(); + + $this->assertContains( 'admin_menu', $hooks ); + $this->assertContains( 'admin_init', $hooks ); + $this->assertContains( 'admin_enqueue_scripts', $hooks ); + $this->assertNotContains( 'admin_notices', $hooks ); + } + /** * Test the top-level menu uses the packaged monochrome Basicrum mark. */ @@ -890,7 +898,7 @@ public function test_settings_script_is_not_enqueued_on_other_pages() { * @param string $brum_site_id Brum Site ID setting. * @param string $expected_message Expected warning fragment. */ - public function test_admin_notice_when_required_settings_are_missing( $beacon_url, $brum_site_id, $expected_message ) { + public function test_settings_notice_when_required_settings_are_missing( $beacon_url, $brum_site_id, $expected_message ) { $this->set_settings( array( 'enabled' => '1', @@ -899,7 +907,6 @@ public function test_admin_notice_when_required_settings_are_missing( $beacon_ur ) ); - Functions\expect( 'current_user_can' )->once()->with( 'manage_options' )->andReturn( true ); Functions\expect( 'add_settings_error' ) ->once() ->with( @@ -915,8 +922,7 @@ function( $message ) use ( $expected_message ) { ); Functions\expect( 'settings_errors' )->once(); - $page = new Page(); - $page->admin_notices(); + $this->render_settings_page_html(); } /** @@ -944,12 +950,10 @@ public function test_no_admin_notice_when_required_settings_are_present() { ) ); - Functions\expect( 'current_user_can' )->once()->with( 'manage_options' )->andReturn( true ); Functions\expect( 'add_settings_error' )->never(); Functions\expect( 'settings_errors' )->once(); - $page = new Page(); - $page->admin_notices(); + $this->render_settings_page_html(); } /** @@ -964,11 +968,33 @@ public function test_no_admin_notice_when_monitoring_is_disabled() { ) ); - Functions\expect( 'current_user_can' )->once()->with( 'manage_options' )->andReturn( true ); Functions\expect( 'add_settings_error' )->never(); Functions\expect( 'settings_errors' )->once(); + $this->render_settings_page_html(); + } + + /** + * Render the Basicrum settings page with its WordPress dependencies stubbed. + * + * @return string Rendered settings page HTML. + */ + private function render_settings_page_html() { + Functions\when( 'plugins_url' )->alias( + function( $path ) { + return 'https://example.com/wp-content/plugins/basicrum/' . $path; + } + ); + Functions\expect( 'current_user_can' )->once()->with( 'manage_options' )->andReturn( true ); + Functions\when( 'get_admin_page_title' )->justReturn( 'Basicrum Settings' ); + Functions\when( 'settings_fields' )->justReturn(); + Functions\when( 'do_settings_sections' )->justReturn(); + Functions\when( 'submit_button' )->justReturn(); + $page = new Page(); - $page->admin_notices(); + + ob_start(); + $page->render_settings_page(); + return ob_get_clean(); } } From 66de0794ccae170dc39ac8790a10fa2c2f4cd030 Mon Sep 17 00:00:00 2001 From: Tsvetan Stoychev Date: Thu, 27 Aug 2026 10:23:21 +0200 Subject: [PATCH 2/3] Harden settings sanitization --- plugins/basicrum/src/Admin/Settings/Page.php | 2 + .../basicrum/src/Admin/Settings/Validate.php | 17 ++++--- .../basicrum/tests/unit/SettingsPageTest.php | 29 ++++++++++++ plugins/basicrum/tests/unit/ValidateTest.php | 46 +++++++++++++++++++ 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/plugins/basicrum/src/Admin/Settings/Page.php b/plugins/basicrum/src/Admin/Settings/Page.php index eee70de..e669103 100644 --- a/plugins/basicrum/src/Admin/Settings/Page.php +++ b/plugins/basicrum/src/Admin/Settings/Page.php @@ -158,6 +158,8 @@ public function register_settings() { self::GROUP, Helpers::OPTION_KEY, array( + 'type' => 'array', + 'default' => Helpers::get_defaults(), 'sanitize_callback' => array( new Validate(), 'sanitize' ), ) ); diff --git a/plugins/basicrum/src/Admin/Settings/Validate.php b/plugins/basicrum/src/Admin/Settings/Validate.php index 98637fe..f540693 100644 --- a/plugins/basicrum/src/Admin/Settings/Validate.php +++ b/plugins/basicrum/src/Admin/Settings/Validate.php @@ -36,13 +36,18 @@ class Validate { /** * Sanitize and validate all settings input. * - * @param array $input Raw input from the settings form. + * @param mixed $input Raw input from the settings form. * @return array Sanitized settings. */ public function sanitize( $input ) { - $output = array(); $defaults = Helpers::get_defaults(); + if ( ! is_array( $input ) ) { + return $defaults; + } + + $output = array(); + // Enabled (checkbox). $output['enabled'] = $this->sanitize_checkbox( $input, 'enabled' ); @@ -95,7 +100,7 @@ public function sanitize( $input ) { * @return string '1' or '0'. */ private function sanitize_checkbox( $input, $key ) { - return ! empty( $input[ $key ] ) ? '1' : '0'; + return isset( $input[ $key ] ) && '1' === $input[ $key ] ? '1' : '0'; } /** @@ -107,7 +112,7 @@ private function sanitize_checkbox( $input, $key ) { * @return string Sanitized URL. */ private function sanitize_beacon_url( $input, $defaults, $development_mode ) { - if ( empty( $input['beacon_url'] ) ) { + if ( empty( $input['beacon_url'] ) || ! is_string( $input['beacon_url'] ) ) { return $defaults['beacon_url']; } @@ -145,7 +150,7 @@ private function sanitize_beacon_url( $input, $defaults, $development_mode ) { * @return string Sanitized Brum Site ID or empty string. */ private function sanitize_brum_site_id( $input ) { - if ( empty( $input['brum_site_id'] ) ) { + if ( empty( $input['brum_site_id'] ) || ! is_string( $input['brum_site_id'] ) ) { return ''; } @@ -172,7 +177,7 @@ private function sanitize_brum_site_id( $input ) { * @return int Sanitized delay in milliseconds. */ private function sanitize_delay( $input, $defaults ) { - if ( ! isset( $input['delay_ms'] ) ) { + if ( ! isset( $input['delay_ms'] ) || ! is_scalar( $input['delay_ms'] ) ) { return (int) $defaults['delay_ms']; } diff --git a/plugins/basicrum/tests/unit/SettingsPageTest.php b/plugins/basicrum/tests/unit/SettingsPageTest.php index 4055c70..d1f296a 100644 --- a/plugins/basicrum/tests/unit/SettingsPageTest.php +++ b/plugins/basicrum/tests/unit/SettingsPageTest.php @@ -8,7 +8,9 @@ namespace Basicrum\WP\Tests\Unit; use Basicrum\WP\Admin\Settings\Page; +use Basicrum\WP\Admin\Settings\Validate; use Basicrum\WP\ConsentIntegration; +use Basicrum\WP\Helpers; use Basicrum\WP\Tests\TestCase; use Brain\Monkey\Functions; use Mockery; @@ -84,6 +86,33 @@ function( $hook_name ) use ( &$hooks ) { $this->assertNotContains( 'admin_notices', $hooks ); } + /** + * Test the compound settings option declares its schema and sanitizer. + */ + public function test_settings_registration_declares_array_sanitization() { + $registration = array(); + + Functions\when( 'get_option' )->justReturn( Helpers::get_defaults() ); + Functions\when( 'register_setting' )->alias( + function( $group, $option, $args ) use ( &$registration ) { + $registration = array( $group, $option, $args ); + } + ); + Functions\when( 'add_settings_section' )->justReturn(); + Functions\when( 'add_settings_field' )->justReturn(); + + $page = new Page(); + $page->register_settings(); + + $this->assertSame( Page::GROUP, $registration[0] ); + $this->assertSame( Helpers::OPTION_KEY, $registration[1] ); + $this->assertSame( 'array', $registration[2]['type'] ); + $this->assertSame( Helpers::get_defaults(), $registration[2]['default'] ); + $this->assertIsCallable( $registration[2]['sanitize_callback'] ); + $this->assertInstanceOf( Validate::class, $registration[2]['sanitize_callback'][0] ); + $this->assertSame( 'sanitize', $registration[2]['sanitize_callback'][1] ); + } + /** * Test the top-level menu uses the packaged monochrome Basicrum mark. */ diff --git a/plugins/basicrum/tests/unit/ValidateTest.php b/plugins/basicrum/tests/unit/ValidateTest.php index d01a31e..9273d8a 100644 --- a/plugins/basicrum/tests/unit/ValidateTest.php +++ b/plugins/basicrum/tests/unit/ValidateTest.php @@ -274,6 +274,52 @@ public function test_checkbox_disabled() { $this->assertSame( '0', $result['enabled'] ); } + /** + * Test malformed top-level input fails closed to canonical defaults. + * + * @dataProvider malformed_input_provider + * + * @param mixed $input Malformed option input. + */ + public function test_malformed_top_level_input_returns_defaults( $input ) { + $this->assertSame( \Basicrum\WP\Helpers::get_defaults(), $this->validate->sanitize( $input ) ); + } + + /** + * Provide malformed top-level option values. + * + * @return array[] Test cases. + */ + public function malformed_input_provider() { + return array( + 'null' => array( null ), + 'string' => array( 'enabled=1' ), + 'integer' => array( 1 ), + 'object' => array( new \stdClass() ), + ); + } + + /** + * Test nested values cannot bypass field-specific sanitization. + */ + public function test_nested_field_values_are_rejected() { + $input = $this->full_input( + array( + 'enabled' => array( '1' ), + 'beacon_url' => array( 'https://example.com/beacon' ), + 'brum_site_id' => array( '550e8400-e29b-41d4-a716-446655440000' ), + 'delay_ms' => array( '3000' ), + ) + ); + + $result = $this->validate->sanitize( $input ); + + $this->assertSame( '0', $result['enabled'] ); + $this->assertSame( '', $result['beacon_url'] ); + $this->assertSame( '', $result['brum_site_id'] ); + $this->assertSame( 0, $result['delay_ms'] ); + } + /** * Build a full input array with defaults, overridden by given values. * From c33f6da7b8e1b74585e39be8663c1b4424d31d91 Mon Sep 17 00:00:00 2001 From: Tsvetan Stoychev Date: Thu, 27 Aug 2026 11:25:59 +0200 Subject: [PATCH 3/3] Align plugin identity with WordPress.org slug --- .github/workflows/ci.yml | 6 +- .github/workflows/prerelease.yml | 6 +- .github/workflows/release.yml | 6 +- .gitignore | 2 +- AGENTS.md | 3 +- CONTRIBUTING.md | 2 +- Makefile | 9 +- README.md | 8 +- checklist.md | 7 +- docker-compose.yml | 4 +- docker/release-smoke.yml | 2 +- docker/woocommerce-e2e.yml | 4 +- docs/audits/evidence.md | 2 +- docs/audits/privacy-audit.md | 5 +- docs/audits/wporg-submission-checklist.md | 33 +- plugins/basicrum/.distignore | 2 +- plugins/basicrum/basicrum.php | 4 +- plugins/basicrum/composer.json | 3 + plugins/basicrum/composer.lock | 2 +- ....pot => basicrum-real-user-monitoring.pot} | 314 +++++++++--------- plugins/basicrum/phpcs.ruleset.xml | 2 +- plugins/basicrum/src/Admin/Privacy.php | 20 +- plugins/basicrum/src/Admin/Settings/Page.php | 284 ++++++++-------- .../basicrum/src/Admin/Settings/Validate.php | 12 +- plugins/basicrum/tests/unit/AssetsTest.php | 6 +- .../basicrum/tests/unit/SettingsPageTest.php | 10 +- tools/build-release.sh | 9 +- tools/setup-woocommerce-e2e.sh | 2 +- tools/setup-wordpress.sh | 4 +- tools/smoke-test-release.sh | 4 +- tools/update-translations.sh | 4 +- tools/verify-release.sh | 88 ++--- tools/verify-text-domain.sh | 67 ++++ 33 files changed, 506 insertions(+), 430 deletions(-) rename plugins/basicrum/languages/{basicrum.pot => basicrum-real-user-monitoring.pot} (80%) create mode 100755 tools/verify-text-domain.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c94d46..d5568a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -242,13 +242,13 @@ jobs: run: sh tools/build-release.sh - name: Install and test packaged plugin - run: sh tools/smoke-test-release.sh release/basicrum.zip + run: sh tools/smoke-test-release.sh release/basicrum-real-user-monitoring.zip - name: Upload release artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: basicrum-release path: | - release/basicrum.zip - release/basicrum.zip.sha256 + release/basicrum-real-user-monitoring.zip + release/basicrum-real-user-monitoring.zip.sha256 if-no-files-found: error diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 489bba1..c832158 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -42,11 +42,11 @@ jobs: run: sh tools/build-release.sh - name: Install and test packaged plugin - run: sh tools/smoke-test-release.sh release/basicrum.zip + run: sh tools/smoke-test-release.sh release/basicrum-real-user-monitoring.zip - name: Upload release assets uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: files: | - release/basicrum.zip - release/basicrum.zip.sha256 + release/basicrum-real-user-monitoring.zip + release/basicrum-real-user-monitoring.zip.sha256 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f1803b1..5c2b62b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,7 @@ jobs: run: sh tools/build-release.sh - name: Install and test packaged plugin - run: sh tools/smoke-test-release.sh release/basicrum.zip + run: sh tools/smoke-test-release.sh release/basicrum-real-user-monitoring.zip - name: Create GitHub release and upload assets uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 @@ -54,5 +54,5 @@ jobs: generate_release_notes: true fail_on_unmatched_files: true files: | - release/basicrum.zip - release/basicrum.zip.sha256 + release/basicrum-real-user-monitoring.zip + release/basicrum-real-user-monitoring.zip.sha256 diff --git a/.gitignore b/.gitignore index 223f9e7..274924b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ coverage.xml # Release artifacts /release/ -/basicrum.zip +/basicrum-real-user-monitoring.zip # Local research and planning notes /plan-refs/ diff --git a/AGENTS.md b/AGENTS.md index 4ffe0fe..985538f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,7 +50,8 @@ in the matching skill. ## Conventions -- Follow WordPress-Core/WPCS. The text domain is `basicrum`. +- Follow WordPress-Core/WPCS. The WordPress.org slug and text domain are + `basicrum-real-user-monitoring`. - Guard PHP files with `ABSPATH`; escape output and sanitize all input. - Use ASCII hyphens (`-`); do not use typographic dashes in source, comments, documentation, or user-facing text. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94ea030..fc069a9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ The development site is available at with `admin` / `ba The installable plugin is [`plugins/basicrum/`](plugins/basicrum/). Repository root files provide development, browser-test, Docker, CI, and release tooling. -Follow the permanent conventions in [AGENTS.md](AGENTS.md), including WordPress Coding Standards, PHP 7.4 compatibility, ASCII hyphens, synchronized version metadata, privacy-safe consent behavior, and immutable GitHub Actions pins. +Follow the permanent conventions in [AGENTS.md](AGENTS.md), including WordPress Coding Standards, PHP 7.4 compatibility, ASCII hyphens, the assigned WordPress.org text domain, synchronized version metadata, privacy-safe consent behavior, and immutable GitHub Actions pins. When changing user-facing text, regenerate the WordPress POT template. Locale-specific PO and MO files are not bundled. When changing settings, keep defaults, rendering, validation, runtime behavior, tests, and documentation synchronized. diff --git a/Makefile b/Makefile index 3c19fc2..2ab5322 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,9 @@ WP_SERVICE = wordpress DB_SERVICE = db WPCLI_SERVICE = wpcli JS_SERVICE = javascript -WPCLI_PLUGIN_WORKDIR = /var/www/html/wp-content/plugins/basicrum +PLUGIN_SLUG = basicrum-real-user-monitoring +RELEASE_ARCHIVE = release/$(PLUGIN_SLUG).zip +WPCLI_PLUGIN_WORKDIR = /var/www/html/wp-content/plugins/$(PLUGIN_SLUG) PLUGIN_DIR = plugins/basicrum PLUGIN_WORKDIR = /workspace TEST_DB_NAME = wordpress_test @@ -92,6 +94,7 @@ composer-audit: conventions: sh tools/verify-ascii-hyphens.sh sh tools/verify-version-consistency.sh + sh tools/verify-text-domain.sh sh tools/verify-boomerang-provenance.sh translations: @@ -128,10 +131,10 @@ package: $(COMPOSE) run --rm --no-deps -w /repo $(PHP_SERVICE) sh /tools/build-release.sh /repo/$(PLUGIN_DIR) /repo/release package-verify: - $(COMPOSE) run --rm --no-deps -w /repo $(PHP_SERVICE) sh /tools/verify-release.sh /repo/release/basicrum.zip + $(COMPOSE) run --rm --no-deps -w /repo $(PHP_SERVICE) sh /tools/verify-release.sh /repo/$(RELEASE_ARCHIVE) package-smoke: package - sh tools/smoke-test-release.sh release/basicrum.zip + sh tools/smoke-test-release.sh $(RELEASE_ARCHIVE) clean: $(COMPOSE) down -v diff --git a/README.md b/README.md index b4dbd5c..b141832 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Basicrum is a privacy-first Real User Monitoring integration for WordPress. It loads the bundled Boomerang library, tags WordPress and WooCommerce page types, and sends performance beacons to a configured hosted or self-hosted Basicrum collector. -The installable plugin lives in [`plugins/basicrum/`](plugins/basicrum/). Build release artifacts through the repository tooling instead of zipping the source directory directly. +The plugin source lives in [`plugins/basicrum/`](plugins/basicrum/). Release tooling packages it under the assigned WordPress.org directory slug `basicrum-real-user-monitoring`; do not zip the source directory directly. ## Privacy @@ -18,7 +18,7 @@ The complete webmaster-facing behavior and consent instructions live in the [Wor | Path | Purpose | | --- | --- | -| [`plugins/basicrum/`](plugins/basicrum/) | Installable plugin source | +| [`plugins/basicrum/`](plugins/basicrum/) | Plugin source packaged under the WordPress.org slug | | [`tools/`](tools/) | Setup, test, and release scripts | | [`docker/`](docker/) | Local WordPress and WooCommerce environments | | [`tests/javascript/`](tests/javascript/) | Browser tests for loaders, consent adapters, and settings | @@ -53,7 +53,7 @@ See [AGENTS.md](AGENTS.md) for repository invariants, the complete check suite, ## Releases -`make package` creates `release/basicrum.zip` and its SHA-256 checksum from a temporary production Composer install. `make package-smoke` installs that ZIP into clean WordPress and checks activation, the administration page, frontend loading, and PHP logs. +`make package` creates `release/basicrum-real-user-monitoring.zip` and its SHA-256 checksum from a temporary production Composer install. `make package-smoke` installs that ZIP into clean WordPress and checks activation, the administration page, frontend loading, and PHP logs. The plugin header version, `BASICRUM_VERSION`, WordPress `Stable tag`, top changelog version, and `v` release tag must match. @@ -64,7 +64,7 @@ git tag -a vX.Y.Z -m "Basicrum vX.Y.Z" git push origin vX.Y.Z ``` -The tag workflow verifies the version, runs the release tests, builds and smoke-tests the installable ZIP, and only then creates the GitHub Release with `basicrum.zip` and `basicrum.zip.sha256`. Do not create the GitHub Release or upload the ZIP manually. +The tag workflow verifies the version, runs the release tests, builds and smoke-tests the installable ZIP, and only then creates the GitHub Release with `basicrum-real-user-monitoring.zip` and `basicrum-real-user-monitoring.zip.sha256`. Do not create the GitHub Release or upload the ZIP manually. ## Contributing and security diff --git a/checklist.md b/checklist.md index 079b236..b647cf9 100644 --- a/checklist.md +++ b/checklist.md @@ -148,7 +148,7 @@ Acceptance criteria: - [ ] Record the minifier and its version in a lock file. - [ ] Make CI regenerate the loaders and fail when the committed output differs. - [ ] Document the source and version of the bundled Boomerang asset. -- [x] Add a repeatable command for generating `languages/basicrum.pot`. +- [x] Add a repeatable command for generating `languages/basicrum-real-user-monitoring.pot`. - [x] Keep locale-specific PO and MO files out of the repository and release ZIP. - [x] Keep POT generation as a local maintenance command; the standalone translation CI job was removed by product decision. @@ -164,7 +164,10 @@ Acceptance criteria: tracked source, comments, documentation, and user-facing text. - [x] Add a version consistency check covering the plugin header, `BASICRUM_VERSION`, `Stable tag`, changelog, and release tag. -- [x] Run both checks in pull requests and pushes to the main branch. +- [x] Add a WordPress.org slug and text-domain consistency check covering the + plugin header, source literals, WPCS configuration, POT filename, and release + package identity. +- [x] Run all convention checks in pull requests and pushes to the main branch. - [x] Document the checks in `AGENTS.md` and the contributor documentation. Acceptance criteria: diff --git a/docker-compose.yml b/docker-compose.yml index 1632909..0f78c4c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,7 +33,7 @@ services: - "${WORDPRESS_PORT:-9080}:80" volumes: - wordpress_data:/var/www/html - - ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum + - ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring wpcli: image: wordpress:cli-2.12.0-php8.2 @@ -53,7 +53,7 @@ services: WP_ADMIN_EMAIL: ${WP_ADMIN_EMAIL:-admin@example.test} volumes: - wordpress_data:/var/www/html - - ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum + - ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring - ./tools:/tools:ro php: diff --git a/docker/release-smoke.yml b/docker/release-smoke.yml index c3b1187..d0ae4f4 100644 --- a/docker/release-smoke.yml +++ b/docker/release-smoke.yml @@ -41,7 +41,7 @@ services: WORDPRESS_DB_PASSWORD: wordpress volumes: - wordpress_data:/var/www/html - - "${BASICRUM_RELEASE_ZIP}:/artifacts/basicrum.zip:ro" + - "${BASICRUM_RELEASE_ZIP}:/artifacts/basicrum-real-user-monitoring.zip:ro" volumes: wordpress_data: diff --git a/docker/woocommerce-e2e.yml b/docker/woocommerce-e2e.yml index 2191830..a7c642b 100644 --- a/docker/woocommerce-e2e.yml +++ b/docker/woocommerce-e2e.yml @@ -27,7 +27,7 @@ services: WORDPRESS_DB_PASSWORD: wordpress volumes: - wordpress_data:/var/www/html - - plugin_workspace:/var/www/html/wp-content/plugins/basicrum:ro + - plugin_workspace:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring:ro wpcli: # Reviewed tag: wordpress:cli-2.12.0-php8.2 @@ -49,7 +49,7 @@ services: HTTP_HOST: wordpress volumes: - wordpress_data:/var/www/html - - plugin_workspace:/var/www/html/wp-content/plugins/basicrum:ro + - plugin_workspace:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring:ro - ../tools:/tools:ro plugin: diff --git a/docs/audits/evidence.md b/docs/audits/evidence.md index 40a0203..51afb61 100644 --- a/docs/audits/evidence.md +++ b/docs/audits/evidence.md @@ -71,7 +71,7 @@ to the original privacy report: | COOKIE-07 (privacy 2) | high | consent loader `:222-236`; bundle tail init glue | both | Run `tests/javascript/consent-optout-race.spec.js` from worktree `.claude/worktrees/wf_14de6d93-758-3/` (promise-gated delayed script, no timeouts) | Race reproduced deterministically: spec FAILS against unmodified loaders (late script inits, sets cookie, beacons); passes with the 11-line fix; full 93-test suite green incl. byte-contract and global-surface tests | high | | BR-WP-15 (privacy 3) | medium sev / high conf | `src/Setup.php:57-60`; `src/Compatibility.php:36-54` | static | `grep -rn 'purge\|rocket_clean\|w3tc_flush' plugins/basicrum/src plugins/basicrum/uninstall.php` | No purge call anywhere; deactivate() deletes one transient; the six cache-plugin exclusion filters guarantee the loader survives in cached HTML | high | | DF-08/COOKIE-13/DISC-04 (privacy 4) | low-disclosure | `src/Admin/Privacy.php:48`; readme.txt | both | `grep -n 'first-party cookies' plugins/basicrum/src/Admin/Privacy.php; grep -ni cookie plugins/basicrum/readme.txt`. Runtime: `context.cookies()` after a page view | RT observed: 7.000-day expiry renewed on every view (rolling), SameSite=Strict, path=/, sub-values `z,dm,si,ss,sl,tt,bcn,ld`; `si` = random UUID stable across views, echoed as `rt.si` on every beacon. No public text names RT, its lifetime, or the identifier. BA never created (runtime + zero bundle occurrences) | high | -| DISC-10 (privacy 5, SUPERSEDED) | resolved by product decision | `.github/workflows/ci.yml`; `tools/update-translations.sh`; `.distignore` | static | `find plugins/basicrum/languages -type f`; `rg -n 'translations:' .github/workflows/ci.yml` | Bulgarian PO/MO catalogs and the standalone translation CI job were removed on 2026-07-19. The local generator now maintains only `basicrum.pot`; release packaging excludes and rejects locale-specific PO/MO files. | high | +| DISC-10 (privacy 5, SUPERSEDED) | resolved by product decision | `.github/workflows/ci.yml`; `tools/update-translations.sh`; `.distignore` | static | `find plugins/basicrum/languages -type f`; `rg -n 'translations:' .github/workflows/ci.yml` | Bulgarian PO/MO catalogs and the standalone translation CI job were removed on 2026-07-19. The local generator now maintains only `basicrum-real-user-monitoring.pot`; release packaging excludes and rejects locale-specific PO/MO files. | high | | DISC-08 (privacy 6) | low | `readme.txt:22,70`; `src/PageTypeDetector.php` | static | `sed -n '22p;70p' plugins/basicrum/readme.txt; grep -n "return '" plugins/basicrum/src/PageTypeDetector.php` | Readme lists 7+3 types; detector returns 17 incl. checkout_payment, checkout_success, account, product_category, tag, author, date_archive | high | | DISC-09 (privacy 7) | low | `plugins/basicrum/README.md` | static | `sed -n '4p;14p;51p;86p' plugins/basicrum/README.md` | Stock template stub with placeholder text and fake security-fix changelog; excluded from ZIP by verify-release.sh | high | | BR-WP-14 (privacy 8) | low | `uninstall.php:13-20` | static | `grep -rn is_multisite plugins/basicrum/uninstall.php plugins/basicrum/src; echo exit=$?` | Exit 1 (no match): no multisite iteration; per-site options persist on other subsites | medium | diff --git a/docs/audits/privacy-audit.md b/docs/audits/privacy-audit.md index 02a13d0..a5ab898 100644 --- a/docs/audits/privacy-audit.md +++ b/docs/audits/privacy-audit.md @@ -87,7 +87,7 @@ standalone translation CI job were removed. Keep the POT-only local generator for future gettext changes, and keep locale-specific catalogs out of release ZIPs unless bundled translations are deliberately restored. -- [x] Regenerate and commit `languages/basicrum.pot` when source strings change. +- [x] Regenerate and commit `languages/basicrum-real-user-monitoring.pot` when source strings change. - [x] Exclude and reject locale-specific PO/MO files in release packages. ## 6. Match public page-type lists to the detector (DISC-08) @@ -207,7 +207,8 @@ severity: the residue is operator configuration, not visitor personal data. real WordPress/WooCommerce stack assert `p_type`, `p_gen=wp`, and the configured `brum_site_id`; collector is a reserved `.test` host answered with HTTP 204. -- [x] `make conventions`: ASCII hyphen and version consistency checks pass. +- [x] `make conventions`: ASCII hyphen, version consistency, and WordPress.org + text-domain checks pass. ## 13. Residual test gaps (future work) diff --git a/docs/audits/wporg-submission-checklist.md b/docs/audits/wporg-submission-checklist.md index 9c4d347..b7960f6 100644 --- a/docs/audits/wporg-submission-checklist.md +++ b/docs/audits/wporg-submission-checklist.md @@ -24,7 +24,7 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned. the upstream repository, the exact source commit (the bundle header carries 564759ed70de7801bb64de5e2025fb6ac049ff5f), and the build procedure; ship Boomerang's BSD license text alongside the bundle. (B2) -- [x] RESOLVED 2026-07-20: phpstan.neon.dist added to .distignore and the verify-release dev-file regex; ZIP rebuilt and verified clean. Original finding: dev file leaks into the ZIP: release/basicrum.zip contains +- [x] RESOLVED 2026-07-20: phpstan.neon.dist added to .distignore and the verify-release dev-file regex; ZIP rebuilt and verified clean. Original finding: dev file leaked into the release ZIP. basicrum/phpstan.neon.dist. Add it to plugins/basicrum/.distignore and to the verify-release.sh dev-file regex, rebuild. Plugin Check would flag it. (D2a, B7) @@ -46,7 +46,7 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned. 0.0.x builds and can be misread as shipped-version history. Decide whether 0.0.7/0.0.6 entries stay (internal history) or fold in. (C13, C14) -- [x] RESOLVED 2026-08-21: Plugin Check 2.1.0 completed against the exact +- [x] SUPERSEDED 2026-08-27: Plugin Check 2.1.0 completed against the exact `v0.0.9` ZIP built from tagged commit `f689a3616e897c07a6dd60c51b4985bebeef2988` (SHA-256 `7321a346e3e9e8cc0b4c8cd749a8fa8f209614281da5133cdfcd704f98b42197`). @@ -54,19 +54,16 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned. ignored codes, and Plugin Check's `cli.php` loaded so runtime checks were included. Strict and raw-result runs completed successfully with no result rows. The earlier `outdated_tested_upto_header` finding was resolved by the - WordPress 7.1 compatibility update. (B7) -- [x] RESOLVED 2026-08-20: the permanent directory slug is decided. wp.org - autogenerates the slug from the plugin header Plugin Name at submission and - cannot rename it after approval, so `Basicrum - Real User Monitoring` will be - offered `basicrum-real-user-monitoring`. The display name stays descriptive - and the shorter `basicrum` slug is requested through the documented one-time - correction: the FAQ states "You can update your slug once after submitting - it. Every submission gets an automated email with directions." Both - `basicrum` and `basicrum-real-user-monitoring` were unregistered on - 2026-08-20 (wordpress.org/plugins// redirects to search for each). - `basicrum` is what the generated POT `Report-Msgid-Bugs-To` and the plugin - directory name already assume, so taking it keeps the support URL correct. - This is a user-only action on submission day; see the list below. + WordPress 7.1 compatibility update. This check used the earlier provisional + `basicrum` package identity and is retained only as historical evidence. (B7) +- [x] RESOLVED 2026-08-27: WordPress.org assigned the permanent directory slug + `basicrum-real-user-monitoring`. The plugin header, every gettext call, WPCS + configuration, POT filename and metadata, local and WooCommerce installation + paths, release ZIP name, and release ZIP root now use that identity. Plugin + Check 2.1.0 completed against the rebuilt ZIP under the assigned slug with no + errors. Repository conventions and release verification prevent the text + domain and package root from drifting back to the provisional `basicrum` + identity. - [x] RESOLVED 2026-08-20: External services now links the service privacy information guideline 6 and the common-issues page ask for. The Basicrum Privacy Notice covers only basicrum.com, its contact form, and beta requests, @@ -160,9 +157,3 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned. 5. Confirm the two outside code contributors are content with the GPLv2-or-later relicense. MIT permits the sublicense, so this is a courtesy record, not a blocker. -6. On the submission email, use the one-time slug update to change - `basicrum-real-user-monitoring` to `basicrum` before approval. The slug is - permanent afterwards, and it also sets the SVN path, the installed folder - name, and the support URL the POT already points at. Keep the display name - `Basicrum - Real User Monitoring`; wp.org treats display name and slug - separately, and the display name stays editable after approval. diff --git a/plugins/basicrum/.distignore b/plugins/basicrum/.distignore index 866f129..f0e56ae 100644 --- a/plugins/basicrum/.distignore +++ b/plugins/basicrum/.distignore @@ -22,6 +22,6 @@ playwright*.config.js /languages/*.mo coverage.xml -basicrum.zip +basicrum-real-user-monitoring.zip /release phpstan.neon.dist diff --git a/plugins/basicrum/basicrum.php b/plugins/basicrum/basicrum.php index 6d36603..f3d872e 100644 --- a/plugins/basicrum/basicrum.php +++ b/plugins/basicrum/basicrum.php @@ -8,7 +8,7 @@ * Author URI: https://www.basicrum.com/contact/ * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html - * Text Domain: basicrum + * Text Domain: basicrum-real-user-monitoring * Domain Path: /languages * Requires at least: 6.0 * Requires PHP: 7.4 @@ -36,7 +36,7 @@ printf( '

%s

', - esc_html__( 'Basicrum could not start because its Composer dependencies are missing. Reinstall the plugin from an official release ZIP.', 'basicrum' ) + esc_html__( 'Basicrum could not start because its Composer dependencies are missing. Reinstall the plugin from an official release ZIP.', 'basicrum-real-user-monitoring' ) ); }; diff --git a/plugins/basicrum/composer.json b/plugins/basicrum/composer.json index 603e0cc..83c487a 100644 --- a/plugins/basicrum/composer.json +++ b/plugins/basicrum/composer.json @@ -32,6 +32,9 @@ "Basicrum\\WP\\Tests\\": "tests/" } }, + "extra": { + "installer-name": "basicrum-real-user-monitoring" + }, "scripts": { "analyse": "phpstan analyse --configuration=phpstan.neon.dist --no-progress --memory-limit=1G", "lint": "phpcs --standard=phpcs.ruleset.xml", diff --git a/plugins/basicrum/composer.lock b/plugins/basicrum/composer.lock index 3301411..3282ad6 100644 --- a/plugins/basicrum/composer.lock +++ b/plugins/basicrum/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": "231462705e227a5c542aa20388c60d21", + "content-hash": "a64e44e02f6a7bb10f9d13eb0a79452d", "packages": [ { "name": "composer/installers", diff --git a/plugins/basicrum/languages/basicrum.pot b/plugins/basicrum/languages/basicrum-real-user-monitoring.pot similarity index 80% rename from plugins/basicrum/languages/basicrum.pot rename to plugins/basicrum/languages/basicrum-real-user-monitoring.pot index 7763156..9779451 100644 --- a/plugins/basicrum/languages/basicrum.pot +++ b/plugins/basicrum/languages/basicrum-real-user-monitoring.pot @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Basicrum - Real User Monitoring 0.0.9\n" -"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/basicrum\n" +"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/basicrum-real-user-monitoring\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -12,7 +12,7 @@ msgstr "" "POT-Creation-Date: \n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.12.0\n" -"X-Domain: basicrum\n" +"X-Domain: basicrum-real-user-monitoring\n" #. Plugin Name of the plugin #: basicrum.php @@ -40,7 +40,7 @@ msgstr "" msgid "https://www.basicrum.com/contact/" msgstr "" -#: basicrum.php:37 +#: basicrum.php:39 msgid "Basicrum could not start because its Composer dependencies are missing. Reinstall the plugin from an official release ZIP." msgstr "" @@ -82,609 +82,609 @@ msgstr "" msgid "Monitoring is configured to start immediately on frontend pages, without waiting for a consent signal. Logged-in administrators are excluded unless Track Admin Users is enabled." msgstr "" -#: src/Admin/Settings/Page.php:115 -#: src/Admin/Settings/Page.php:574 +#: src/Admin/Settings/Page.php:114 +#: src/Admin/Settings/Page.php:576 msgid "Basicrum Settings" msgstr "" -#: src/Admin/Settings/Page.php:116 +#: src/Admin/Settings/Page.php:115 msgid "Basicrum" msgstr "" -#: src/Admin/Settings/Page.php:182 +#: src/Admin/Settings/Page.php:183 msgid "General Settings" msgstr "" -#: src/Admin/Settings/Page.php:189 +#: src/Admin/Settings/Page.php:190 msgid "Enable Basicrum" msgstr "" -#: src/Admin/Settings/Page.php:195 +#: src/Admin/Settings/Page.php:196 msgid "Enable real user monitoring on your site." msgstr "" -#: src/Admin/Settings/Page.php:201 +#: src/Admin/Settings/Page.php:202 msgid "Beacon URL" msgstr "" -#: src/Admin/Settings/Page.php:208 +#: src/Admin/Settings/Page.php:209 msgid "URL where Boomerang beacons are sent. Example: https://www.example.com/beacon/catcher. Required when Basicrum is enabled." msgstr "" -#: src/Admin/Settings/Page.php:212 +#: src/Admin/Settings/Page.php:213 msgid "Beacon URL is required when Basicrum is enabled." msgstr "" -#: src/Admin/Settings/Page.php:218 +#: src/Admin/Settings/Page.php:219 msgid "Brum Site ID" msgstr "" -#: src/Admin/Settings/Page.php:225 +#: src/Admin/Settings/Page.php:226 msgid "Copy the Brum Site ID from the Basicrum backoffice. Required when Basicrum is enabled." msgstr "" -#: src/Admin/Settings/Page.php:229 +#: src/Admin/Settings/Page.php:230 msgid "Brum Site ID is required when Basicrum is enabled." msgstr "" -#: src/Admin/Settings/Page.php:235 +#: src/Admin/Settings/Page.php:236 msgid "Track Admin Users" msgstr "" -#: src/Admin/Settings/Page.php:241 +#: src/Admin/Settings/Page.php:242 msgid "Track logged-in administrators (users with manage_options capability)." msgstr "" -#: src/Admin/Settings/Page.php:247 +#: src/Admin/Settings/Page.php:248 msgid "Boomerang Version" msgstr "" -#: src/Admin/Settings/Page.php:333 +#: src/Admin/Settings/Page.php:334 msgid "Visitor Privacy" msgstr "" -#: src/Admin/Settings/Page.php:340 +#: src/Admin/Settings/Page.php:341 msgid "Strip Query Strings" msgstr "" -#: src/Admin/Settings/Page.php:346 +#: src/Admin/Settings/Page.php:347 msgid "When enabled, replace complete query strings in page, navigation, referrer, and resource URLs with ?qs-redacted before sending beacons. URL paths are still collected." msgstr "" -#: src/Admin/Settings/Page.php:352 -#: src/Admin/Settings/Page.php:358 +#: src/Admin/Settings/Page.php:353 +#: src/Admin/Settings/Page.php:359 msgid "Visitor Consent" msgstr "" -#: src/Admin/Settings/Page.php:359 +#: src/Admin/Settings/Page.php:360 msgid "Choose whether Boomerang requires an allow decision before monitoring a visitor." msgstr "" -#: src/Admin/Settings/Page.php:362 +#: src/Admin/Settings/Page.php:363 msgid "Consent Tool Connection hidden." msgstr "" -#: src/Admin/Settings/Page.php:363 +#: src/Admin/Settings/Page.php:364 msgid "Consent Tool Connection shown." msgstr "" -#: src/Admin/Settings/Page.php:367 +#: src/Admin/Settings/Page.php:368 msgid "Monitor without consent" msgstr "" -#: src/Admin/Settings/Page.php:368 +#: src/Admin/Settings/Page.php:369 msgid "Boomerang loads for visitors without a consent check. It may set cookies and send performance data. Use this only when your site is permitted to monitor without prior consent." msgstr "" -#: src/Admin/Settings/Page.php:371 +#: src/Admin/Settings/Page.php:372 msgid "Require consent before monitoring (recommended)" msgstr "" -#: src/Admin/Settings/Page.php:372 +#: src/Admin/Settings/Page.php:373 msgid "Boomerang stays off and no data is sent until your consent or cookie tool reports an allow decision on each page. Visitors who decline are not monitored. Connect your tool below under Consent Tool Connection." msgstr "" -#: src/Admin/Settings/Page.php:387 +#: src/Admin/Settings/Page.php:388 msgid "Consent Tool Connection" msgstr "" -#: src/Admin/Settings/Page.php:389 +#: src/Admin/Settings/Page.php:390 msgid "Choose how your consent tool's decision reaches Basicrum." msgstr "" -#: src/Admin/Settings/Page.php:392 +#: src/Admin/Settings/Page.php:393 msgid "Automatic connection (recommended)" msgstr "" -#: src/Admin/Settings/Page.php:393 +#: src/Admin/Settings/Page.php:394 msgid "Best for most sites. Detect a supported consent tool and load one matching Basicrum adapter." msgstr "" -#: src/Admin/Settings/Page.php:397 +#: src/Admin/Settings/Page.php:398 msgid "Manual callbacks" msgstr "" -#: src/Admin/Settings/Page.php:398 +#: src/Admin/Settings/Page.php:399 msgid "For unsupported or custom tools, or when a webmaster already manages the integration snippet." msgstr "" -#: src/Admin/Settings/Page.php:414 +#: src/Admin/Settings/Page.php:415 msgid "Control URL query-string handling and choose whether monitoring waits for visitor consent. Basicrum does not display a consent popup, determine your legal basis, or make a site compliant by itself." msgstr "" -#: src/Admin/Settings/Page.php:426 +#: src/Admin/Settings/Page.php:427 msgid "Performance" msgstr "" -#: src/Admin/Settings/Page.php:433 +#: src/Admin/Settings/Page.php:434 msgid "Wait After Onload" msgstr "" -#: src/Admin/Settings/Page.php:439 +#: src/Admin/Settings/Page.php:440 msgid "Delay beacon sending until after page load completes." msgstr "" -#: src/Admin/Settings/Page.php:445 +#: src/Admin/Settings/Page.php:446 msgid "Delay (milliseconds)" msgstr "" -#: src/Admin/Settings/Page.php:451 +#: src/Admin/Settings/Page.php:452 msgid "Milliseconds to delay the beacon after onload. Leave 0 to disable the delay." msgstr "" -#: src/Admin/Settings/Page.php:459 -#: src/Admin/Settings/Page.php:465 +#: src/Admin/Settings/Page.php:460 +#: src/Admin/Settings/Page.php:466 msgid "Script Position" msgstr "" -#: src/Admin/Settings/Page.php:466 +#: src/Admin/Settings/Page.php:467 msgid "Where to insert the monitoring script." msgstr "" -#: src/Admin/Settings/Page.php:468 +#: src/Admin/Settings/Page.php:469 msgid "Header (wp_head)" msgstr "" -#: src/Admin/Settings/Page.php:469 +#: src/Admin/Settings/Page.php:470 msgid "Footer (wp_footer)" msgstr "" -#: src/Admin/Settings/Page.php:483 +#: src/Admin/Settings/Page.php:484 msgid "Developer Settings" msgstr "" -#: src/Admin/Settings/Page.php:490 +#: src/Admin/Settings/Page.php:491 msgid "HTTP Strictness" msgstr "" -#: src/Admin/Settings/Page.php:496 +#: src/Admin/Settings/Page.php:497 msgid "Allow HTTP beacon URLs for local testing. Do not enable this on production sites." msgstr "" -#: src/Admin/Settings/Page.php:502 +#: src/Admin/Settings/Page.php:503 msgid "Use Unminified Loaders" msgstr "" -#: src/Admin/Settings/Page.php:508 +#: src/Admin/Settings/Page.php:509 msgid "Load unminified JavaScript loaders for debugging." msgstr "" #. translators: %s: Link to the Basicrum settings page. -#: src/Admin/Settings/Page.php:579 +#: src/Admin/Settings/Page.php:581 #, php-format msgid "Basicrum monitoring is enabled but inactive because the Beacon URL and Brum Site ID are missing. Configure them in %s." msgstr "" #. translators: %s: Link to the Basicrum settings page. -#: src/Admin/Settings/Page.php:582 +#: src/Admin/Settings/Page.php:584 #, php-format msgid "Basicrum monitoring is enabled but inactive because the Beacon URL is missing. Configure it in %s." msgstr "" #. translators: %s: Link to the Basicrum settings page. -#: src/Admin/Settings/Page.php:585 +#: src/Admin/Settings/Page.php:587 #, php-format msgid "Basicrum monitoring is enabled but inactive because the Brum Site ID is missing. Configure it in %s." msgstr "" -#: src/Admin/Settings/Page.php:841 +#: src/Admin/Settings/Page.php:843 msgid "~30 KB gzipped" msgstr "" -#: src/Admin/Settings/Page.php:884 +#: src/Admin/Settings/Page.php:886 msgid "Borlabs Cookie v3" msgstr "" -#: src/Admin/Settings/Page.php:885 +#: src/Admin/Settings/Page.php:887 msgid "The manual adapter supports Borlabs Cookie 3.0.6 or newer. Automatic detection requires 3.2 or newer because it uses the public borlabsCookieApi() marker. Create and enable a Borlabs service with the ID basicrum, normally in the Statistics service group. Add this adapter as unblocked site code that runs on every page." msgstr "" -#: src/Admin/Settings/Page.php:888 +#: src/Admin/Settings/Page.php:890 msgid "Borlabs Cookie adapter" msgstr "" -#: src/Admin/Settings/Page.php:895 -#: src/Admin/Settings/Page.php:1307 +#: src/Admin/Settings/Page.php:897 +#: src/Admin/Settings/Page.php:1309 msgid "WP Consent API" msgstr "" -#: src/Admin/Settings/Page.php:896 +#: src/Admin/Settings/Page.php:898 msgid "Install and activate the standalone WP Consent API plugin, then use this shared adapter with a consent tool such as Complianz or CookieYes that publishes its Statistics decision through the API. Complianz does not include WP Consent API by itself." msgstr "" -#: src/Admin/Settings/Page.php:899 +#: src/Admin/Settings/Page.php:901 msgid "WP Consent API adapter" msgstr "" -#: src/Admin/Settings/Page.php:906 -#: src/Admin/Settings/Page.php:1309 +#: src/Admin/Settings/Page.php:908 +#: src/Admin/Settings/Page.php:1311 msgid "CookieYes" msgstr "" -#: src/Admin/Settings/Page.php:907 +#: src/Admin/Settings/Page.php:909 msgid "Use this direct adapter only for a connected modern CookieYes 3.x installation when WP Consent API is not active. CookieYes legacy mode uses an incompatible browser API and is deliberately not detected. The adapter follows the Analytics category and fails closed when the browser API is unavailable." msgstr "" -#: src/Admin/Settings/Page.php:910 +#: src/Admin/Settings/Page.php:912 msgid "CookieYes adapter" msgstr "" -#: src/Admin/Settings/Page.php:917 +#: src/Admin/Settings/Page.php:919 msgid "Generic" msgstr "" -#: src/Admin/Settings/Page.php:918 +#: src/Admin/Settings/Page.php:920 msgid "Use these separate snippets when your consent tool provides custom callbacks for an allow decision and a deny, expiry, or withdrawal decision." msgstr "" -#: src/Admin/Settings/Page.php:921 +#: src/Admin/Settings/Page.php:923 msgid "Allow or grant callback" msgstr "" -#: src/Admin/Settings/Page.php:926 +#: src/Admin/Settings/Page.php:928 msgid "Deny, expiry, or withdrawal callback" msgstr "" -#: src/Admin/Settings/Page.php:936 +#: src/Admin/Settings/Page.php:938 msgid "Automatic connection details shown." msgstr "" -#: src/Admin/Settings/Page.php:937 +#: src/Admin/Settings/Page.php:939 msgid "Manual connection setup shown. Save Changes to apply this mode." msgstr "" -#: src/Admin/Settings/Page.php:949 +#: src/Admin/Settings/Page.php:951 msgid "Automatic Connection Status" msgstr "" -#: src/Admin/Settings/Page.php:953 +#: src/Admin/Settings/Page.php:955 msgid "Your consent tool remains responsible for collecting and reporting the visitor decision. Automatic connection does not configure consent categories or make the site compliant by itself." msgstr "" -#: src/Admin/Settings/Page.php:964 +#: src/Admin/Settings/Page.php:966 msgid "Manual Connection Setup" msgstr "" -#: src/Admin/Settings/Page.php:965 +#: src/Admin/Settings/Page.php:967 msgid "Manual callbacks are selected. Basicrum will not load a provider adapter automatically." msgstr "" -#: src/Admin/Settings/Page.php:966 +#: src/Admin/Settings/Page.php:968 msgid "Use one matching integration below in your consent or cookie tool. Load it on every page after the Basicrum consent loader." msgstr "" -#: src/Admin/Settings/Page.php:967 +#: src/Admin/Settings/Page.php:969 msgid "Call when the external tool reports that performance monitoring is allowed. This executes the standard Boomerang loader." msgstr "" -#: src/Admin/Settings/Page.php:968 +#: src/Admin/Settings/Page.php:970 msgid "Call when the external tool reports that monitoring is denied or that permission has expired or been withdrawn. Basicrum disables loaded collection and attempts to remove the Boomerang RT and BA cookies, but it cannot retract data already sent." msgstr "" -#: src/Admin/Settings/Page.php:969 +#: src/Admin/Settings/Page.php:971 msgid "The callbacks are registered at the configured Script Position. Load the manual integration after that point; calls made before registration are not replayed." msgstr "" -#: src/Admin/Settings/Page.php:970 +#: src/Admin/Settings/Page.php:972 msgid "Basicrum does not persist consent across page loads or in its own cookie or server-side record, and it does not display a consent popup. Your consent tool remains the source of truth. A region-aware tool may report allowed before visitor interaction in an opt-out region. If consent is withdrawn after Boomerang loading starts, reload the page before granting it again." msgstr "" -#: src/Admin/Settings/Page.php:971 +#: src/Admin/Settings/Page.php:973 msgid "The files below are the same tested adapters included with Basicrum. They do not configure your consent categories or replace legal review." msgstr "" -#: src/Admin/Settings/Page.php:974 +#: src/Admin/Settings/Page.php:976 msgid "Consent tool integrations" msgstr "" -#: src/Admin/Settings/Page.php:1023 -#: src/Admin/Settings/Page.php:1035 +#: src/Admin/Settings/Page.php:1025 +#: src/Admin/Settings/Page.php:1037 msgid "Off" msgstr "" -#: src/Admin/Settings/Page.php:1026 +#: src/Admin/Settings/Page.php:1028 msgid "Automatic connection is not running" msgstr "" -#: src/Admin/Settings/Page.php:1027 +#: src/Admin/Settings/Page.php:1029 msgid "Basicrum monitoring is disabled, so no consent adapter is enqueued." msgstr "" -#: src/Admin/Settings/Page.php:1028 +#: src/Admin/Settings/Page.php:1030 msgid "Enable Basicrum monitoring before checking the consent tool connection." msgstr "" -#: src/Admin/Settings/Page.php:1038 +#: src/Admin/Settings/Page.php:1040 msgid "Consent tool connection is not used" msgstr "" -#: src/Admin/Settings/Page.php:1039 +#: src/Admin/Settings/Page.php:1041 msgid "Visitor Consent is set to Monitor without consent, so Basicrum does not wait for a consent-tool decision." msgstr "" -#: src/Admin/Settings/Page.php:1040 +#: src/Admin/Settings/Page.php:1042 msgid "Select Require consent before monitoring if Basicrum should wait for a reported decision." msgstr "" -#: src/Admin/Settings/Page.php:1047 +#: src/Admin/Settings/Page.php:1049 msgid "Active" msgstr "" -#: src/Admin/Settings/Page.php:1050 +#: src/Admin/Settings/Page.php:1052 msgid "WP Consent API selected" msgstr "" -#: src/Admin/Settings/Page.php:1051 +#: src/Admin/Settings/Page.php:1053 msgid "Basicrum will load its packaged WP Consent API adapter and follow the Statistics decision. This shared API takes priority over direct provider adapters." msgstr "" -#: src/Admin/Settings/Page.php:1052 +#: src/Admin/Settings/Page.php:1054 msgid "Confirm that your consent popup publishes Statistics decisions to WP Consent API, then test both allow and deny in a private window." msgstr "" -#: src/Admin/Settings/Page.php:1059 -#: src/Admin/Settings/Page.php:1080 +#: src/Admin/Settings/Page.php:1061 +#: src/Admin/Settings/Page.php:1082 msgid "Action needed" msgstr "" -#: src/Admin/Settings/Page.php:1062 +#: src/Admin/Settings/Page.php:1064 msgid "Borlabs Cookie selected" msgstr "" -#: src/Admin/Settings/Page.php:1063 +#: src/Admin/Settings/Page.php:1065 msgid "Basicrum detected the public Borlabs Cookie 3.2+ PHP API and will load its packaged adapter." msgstr "" -#: src/Admin/Settings/Page.php:1064 +#: src/Admin/Settings/Page.php:1066 msgid "Create and enable the Borlabs service with the ID basicrum in the Statistics service group, then re-check and test both decisions in a private window." msgstr "" -#: src/Admin/Settings/Page.php:1070 -#: src/Admin/Settings/Page.php:1091 +#: src/Admin/Settings/Page.php:1072 +#: src/Admin/Settings/Page.php:1093 msgid "Packaged Basicrum adapter selected" msgstr "" -#: src/Admin/Settings/Page.php:1074 +#: src/Admin/Settings/Page.php:1076 msgid "Borlabs service basicrum enabled in the Statistics group" msgstr "" -#: src/Admin/Settings/Page.php:1083 +#: src/Admin/Settings/Page.php:1085 msgid "CookieYes selected" msgstr "" -#: src/Admin/Settings/Page.php:1084 +#: src/Admin/Settings/Page.php:1086 msgid "Basicrum detected the modern CookieYes 3.x runtime and will load its packaged direct adapter. The adapter remains blocked if the connected CookieYes browser API is unavailable." msgstr "" -#: src/Admin/Settings/Page.php:1085 +#: src/Admin/Settings/Page.php:1087 msgid "Confirm that CookieYes exposes Analytics consent on the frontend, then re-check and test both decisions in a private window. Prefer WP Consent API when it is available." msgstr "" -#: src/Admin/Settings/Page.php:1095 +#: src/Admin/Settings/Page.php:1097 msgid "CookieYes Analytics consent available through the connected browser API" msgstr "" #. translators: %s: Comma-separated consent provider names. -#: src/Admin/Settings/Page.php:1113 +#: src/Admin/Settings/Page.php:1115 #, php-format msgid "Basicrum detected multiple direct providers: %s. It did not guess which provider controls monitoring, so no adapter is loaded." msgstr "" -#: src/Admin/Settings/Page.php:1116 -#: src/Admin/Settings/Page.php:1129 +#: src/Admin/Settings/Page.php:1118 +#: src/Admin/Settings/Page.php:1131 msgid "Blocked" msgstr "" -#: src/Admin/Settings/Page.php:1119 +#: src/Admin/Settings/Page.php:1121 msgid "Multiple direct providers detected" msgstr "" -#: src/Admin/Settings/Page.php:1121 +#: src/Admin/Settings/Page.php:1123 msgid "Choose Manual callbacks and select the provider that controls Basicrum, or keep only that provider active." msgstr "" -#: src/Admin/Settings/Page.php:1132 +#: src/Admin/Settings/Page.php:1134 msgid "No supported provider detected" msgstr "" -#: src/Admin/Settings/Page.php:1133 +#: src/Admin/Settings/Page.php:1135 msgid "Basicrum did not find WP Consent API, Borlabs Cookie, or CookieYes. No automatic adapter is loaded and monitoring remains blocked." msgstr "" -#: src/Admin/Settings/Page.php:1134 +#: src/Admin/Settings/Page.php:1136 msgid "If you use Complianz, install and activate the standalone WP Consent API plugin. Otherwise use Manual callbacks to connect an unsupported or custom consent tool." msgstr "" -#: src/Admin/Settings/Page.php:1165 +#: src/Admin/Settings/Page.php:1167 msgid "Done" msgstr "" -#: src/Admin/Settings/Page.php:1165 +#: src/Admin/Settings/Page.php:1167 msgid "Verify" msgstr "" -#: src/Admin/Settings/Page.php:1171 +#: src/Admin/Settings/Page.php:1173 msgid "Next:" msgstr "" -#: src/Admin/Settings/Page.php:1178 +#: src/Admin/Settings/Page.php:1180 msgid "Open manual setup" msgstr "" -#: src/Admin/Settings/Page.php:1183 -#: src/Admin/Settings/Page.php:1190 +#: src/Admin/Settings/Page.php:1185 +#: src/Admin/Settings/Page.php:1192 msgid "Re-check detection" msgstr "" -#: src/Admin/Settings/Page.php:1208 +#: src/Admin/Settings/Page.php:1210 msgid "Provider detection" msgstr "" -#: src/Admin/Settings/Page.php:1216 +#: src/Admin/Settings/Page.php:1218 msgid "Selected - priority" msgstr "" -#: src/Admin/Settings/Page.php:1219 +#: src/Admin/Settings/Page.php:1221 msgid "Selected" msgstr "" -#: src/Admin/Settings/Page.php:1222 +#: src/Admin/Settings/Page.php:1224 msgid "Detected" msgstr "" -#: src/Admin/Settings/Page.php:1225 +#: src/Admin/Settings/Page.php:1227 msgid "Not detected" msgstr "" -#: src/Admin/Settings/Page.php:1258 +#: src/Admin/Settings/Page.php:1260 msgid "None" msgstr "" #. translators: %s: Basicrum plugin version. -#: src/Admin/Settings/Page.php:1263 +#: src/Admin/Settings/Page.php:1265 #, php-format msgid "Basicrum version: %s" msgstr "" #. translators: %s: Consent tool connection mode. -#: src/Admin/Settings/Page.php:1265 +#: src/Admin/Settings/Page.php:1267 #, php-format msgid "Connection mode: %s" msgstr "" #. translators: %s: Consent tool connection mode. -#: src/Admin/Settings/Page.php:1265 +#: src/Admin/Settings/Page.php:1267 msgid "Automatic" msgstr "" #. translators: %s: Enabled or disabled. -#: src/Admin/Settings/Page.php:1267 +#: src/Admin/Settings/Page.php:1269 #, php-format msgid "Monitoring: %s" msgstr "" #. translators: %s: Enabled or disabled. -#: src/Admin/Settings/Page.php:1267 +#: src/Admin/Settings/Page.php:1269 msgid "Enabled" msgstr "" #. translators: %s: Enabled or disabled. -#: src/Admin/Settings/Page.php:1267 +#: src/Admin/Settings/Page.php:1269 msgid "Disabled" msgstr "" #. translators: %s: Visitor consent requirement. -#: src/Admin/Settings/Page.php:1269 +#: src/Admin/Settings/Page.php:1271 #, php-format msgid "Visitor consent: %s" msgstr "" #. translators: %s: Visitor consent requirement. -#: src/Admin/Settings/Page.php:1269 +#: src/Admin/Settings/Page.php:1271 msgid "Required before monitoring" msgstr "" #. translators: %s: Visitor consent requirement. -#: src/Admin/Settings/Page.php:1269 +#: src/Admin/Settings/Page.php:1271 msgid "Not required" msgstr "" #. translators: %s: Comma-separated consent provider names. -#: src/Admin/Settings/Page.php:1271 +#: src/Admin/Settings/Page.php:1273 #, php-format msgid "Detected providers: %s" msgstr "" #. translators: %s: Selected consent provider name. -#: src/Admin/Settings/Page.php:1273 +#: src/Admin/Settings/Page.php:1275 #, php-format msgid "Selected provider: %s" msgstr "" #. translators: 1: Status tier. 2: Status verdict. -#: src/Admin/Settings/Page.php:1275 +#: src/Admin/Settings/Page.php:1277 #, php-format msgid "Result: %1$s - %2$s" msgstr "" -#: src/Admin/Settings/Page.php:1280 +#: src/Admin/Settings/Page.php:1282 msgid "Connection diagnostics" msgstr "" -#: src/Admin/Settings/Page.php:1281 +#: src/Admin/Settings/Page.php:1283 msgid "Basicrum consent tool connection diagnostics" msgstr "" -#: src/Admin/Settings/Page.php:1283 +#: src/Admin/Settings/Page.php:1285 msgid "This status contains no Beacon URL or Brum Site ID." msgstr "" -#: src/Admin/Settings/Page.php:1289 -#: src/Admin/Settings/Page.php:1344 +#: src/Admin/Settings/Page.php:1291 +#: src/Admin/Settings/Page.php:1346 msgid "Copied" msgstr "" -#: src/Admin/Settings/Page.php:1290 -#: src/Admin/Settings/Page.php:1345 +#: src/Admin/Settings/Page.php:1292 +#: src/Admin/Settings/Page.php:1347 msgid "Press Ctrl+C or Command+C to copy." msgstr "" -#: src/Admin/Settings/Page.php:1292 +#: src/Admin/Settings/Page.php:1294 msgid "Copy connection status" msgstr "" -#: src/Admin/Settings/Page.php:1308 +#: src/Admin/Settings/Page.php:1310 msgid "Borlabs Cookie" msgstr "" -#: src/Admin/Settings/Page.php:1329 +#: src/Admin/Settings/Page.php:1331 msgid "This integration snippet is unavailable. Reinstall Basicrum from a complete release package." msgstr "" -#: src/Admin/Settings/Page.php:1347 +#: src/Admin/Settings/Page.php:1349 msgid "Copy snippet" msgstr "" -#: src/Admin/Settings/Validate.php:123 +#: src/Admin/Settings/Validate.php:128 msgid "Beacon URL was automatically upgraded to HTTPS." msgstr "" -#: src/Admin/Settings/Validate.php:132 +#: src/Admin/Settings/Validate.php:137 msgid "Invalid Beacon URL. The default URL has been restored." msgstr "" -#: src/Admin/Settings/Validate.php:158 +#: src/Admin/Settings/Validate.php:163 msgid "Invalid Brum Site ID. Copy it from the Basicrum backoffice and try again." msgstr "" -#: src/Admin/Settings/Validate.php:185 +#: src/Admin/Settings/Validate.php:190 msgid "Delay cannot exceed 30000 milliseconds. It has been capped at 30000." msgstr "" -#: src/Admin/Settings/Validate.php:211 +#: src/Admin/Settings/Validate.php:216 msgid "Invalid visitor consent value. Basicrum will require consent before monitoring." msgstr "" -#: src/Admin/Settings/Validate.php:235 +#: src/Admin/Settings/Validate.php:240 msgid "Invalid consent tool connection value. Basicrum will use manual callbacks." msgstr "" diff --git a/plugins/basicrum/phpcs.ruleset.xml b/plugins/basicrum/phpcs.ruleset.xml index 84045c7..ce65ad8 100644 --- a/plugins/basicrum/phpcs.ruleset.xml +++ b/plugins/basicrum/phpcs.ruleset.xml @@ -26,7 +26,7 @@ - + diff --git a/plugins/basicrum/src/Admin/Privacy.php b/plugins/basicrum/src/Admin/Privacy.php index d4fa8b6..1227bc4 100644 --- a/plugins/basicrum/src/Admin/Privacy.php +++ b/plugins/basicrum/src/Admin/Privacy.php @@ -36,29 +36,29 @@ public function add_policy_content() { $is_configured = '1' === $settings['enabled'] && empty( Helpers::get_missing_required_settings( $settings ) ); $content = '

'; - $content .= esc_html__( 'Review and edit this suggested text before publishing it. Confirm the configured collector, purposes, legal basis, recipients, and retention period for your site.', 'basicrum' ); + $content .= esc_html__( 'Review and edit this suggested text before publishing it. Confirm the configured collector, purposes, legal basis, recipients, and retention period for your site.', 'basicrum-real-user-monitoring' ); if ( ! $is_configured ) { $content .= '
'; - $content .= esc_html__( 'Basicrum monitoring is currently inactive. Use the suggested text only if monitoring is enabled and fully configured.', 'basicrum' ); + $content .= esc_html__( 'Basicrum monitoring is currently inactive. Use the suggested text only if monitoring is enabled and fully configured.', 'basicrum-real-user-monitoring' ); $content .= ''; } $content .= '

'; - $content .= '

' . esc_html__( 'Suggested text:', 'basicrum' ) . '

'; + $content .= '

' . esc_html__( 'Suggested text:', 'basicrum-real-user-monitoring' ) . '

'; $content .= '

'; - $content .= esc_html__( 'This site uses Basicrum to measure real-user performance. When monitoring runs, a visitor\'s browser sends page and resource URLs, performance and interaction timing metrics, page type, the configured site identifier, and technical browser, device, and network information to a performance collector. The collector also receives request information such as the IP address and user agent. Boomerang stores measurement state in a first-party cookie named RT, which contains a random session identifier that links page views, uses SameSite=Strict, is marked Secure on HTTPS sites, and expires seven days after the last monitored page view. Opting out removes the RT cookie and any legacy BA cookie.', 'basicrum' ); + $content .= esc_html__( 'This site uses Basicrum to measure real-user performance. When monitoring runs, a visitor\'s browser sends page and resource URLs, performance and interaction timing metrics, page type, the configured site identifier, and technical browser, device, and network information to a performance collector. The collector also receives request information such as the IP address and user agent. Boomerang stores measurement state in a first-party cookie named RT, which contains a random session identifier that links page views, uses SameSite=Strict, is marked Secure on HTTPS sites, and expires seven days after the last monitored page view. Opting out removes the RT cookie and any legacy BA cookie.', 'basicrum-real-user-monitoring' ); $content .= '

'; $content .= '

'; if ( '1' === $settings['strip_query_string'] ) { - $content .= esc_html__( 'Basicrum is configured to replace complete query strings in page, navigation, referrer, and resource URLs with the marker ?qs-redacted before sending beacons. URL paths are still collected.', 'basicrum' ); + $content .= esc_html__( 'Basicrum is configured to replace complete query strings in page, navigation, referrer, and resource URLs with the marker ?qs-redacted before sending beacons. URL paths are still collected.', 'basicrum-real-user-monitoring' ); } else { - $content .= esc_html__( 'Query-string stripping is disabled, so page, navigation, referrer, and resource URLs may include complete query strings. Review whether your URLs can contain personal or sensitive information before using this configuration.', 'basicrum' ); + $content .= esc_html__( 'Query-string stripping is disabled, so page, navigation, referrer, and resource URLs may include complete query strings. Review whether your URLs can contain personal or sensitive information before using this configuration.', 'basicrum-real-user-monitoring' ); } $content .= '

'; if ( $beacon_url ) { $content .= '

'; /* translators: %s: Configured Basicrum beacon URL. */ - $content .= sprintf( esc_html__( 'When monitoring runs, performance data is sent to the collector configured at %s.', 'basicrum' ), '' . esc_html( $beacon_url ) . '' ); + $content .= sprintf( esc_html__( 'When monitoring runs, performance data is sent to the collector configured at %s.', 'basicrum-real-user-monitoring' ), '' . esc_html( $beacon_url ) . '' ); $content .= '

'; } @@ -66,16 +66,16 @@ public function add_policy_content() { $content .= '

'; } if ( $is_configured && '1' === $settings['consent_enabled'] ) { - $content .= esc_html__( 'Monitoring is configured to follow the site\'s consent tool on every page. Basicrum does not persist consent across page loads or in its own cookie or server-side record. The consent tool may report monitoring as allowed before visitor interaction where an opt-out policy applies. Signaling denial, expiry, or withdrawal stops future browser collection but does not retract data already sent.', 'basicrum' ); + $content .= esc_html__( 'Monitoring is configured to follow the site\'s consent tool on every page. Basicrum does not persist consent across page loads or in its own cookie or server-side record. The consent tool may report monitoring as allowed before visitor interaction where an opt-out policy applies. Signaling denial, expiry, or withdrawal stops future browser collection but does not retract data already sent.', 'basicrum-real-user-monitoring' ); } elseif ( $is_configured ) { - $content .= esc_html__( 'Monitoring is configured to start immediately on frontend pages, without waiting for a consent signal. Logged-in administrators are excluded unless Track Admin Users is enabled.', 'basicrum' ); + $content .= esc_html__( 'Monitoring is configured to start immediately on frontend pages, without waiting for a consent signal. Logged-in administrators are excluded unless Track Admin Users is enabled.', 'basicrum-real-user-monitoring' ); } if ( $is_configured ) { $content .= '

'; } wp_add_privacy_policy_content( - esc_html__( 'Basicrum - Real User Monitoring', 'basicrum' ), + esc_html__( 'Basicrum - Real User Monitoring', 'basicrum-real-user-monitoring' ), wp_kses_post( $content ) ); } diff --git a/plugins/basicrum/src/Admin/Settings/Page.php b/plugins/basicrum/src/Admin/Settings/Page.php index e669103..031e8c0 100644 --- a/plugins/basicrum/src/Admin/Settings/Page.php +++ b/plugins/basicrum/src/Admin/Settings/Page.php @@ -111,8 +111,8 @@ private function get_admin_asset_version( $asset ) { */ public function add_menu_page() { add_menu_page( - esc_html__( 'Basicrum Settings', 'basicrum' ), - esc_html__( 'Basicrum', 'basicrum' ), + esc_html__( 'Basicrum Settings', 'basicrum-real-user-monitoring' ), + esc_html__( 'Basicrum', 'basicrum-real-user-monitoring' ), 'manage_options', self::SLUG, array( $this, 'render_settings_page' ), @@ -180,72 +180,72 @@ private function add_general_section() { add_settings_section( 'basicrum_section_general', - esc_html__( 'General Settings', 'basicrum' ), + esc_html__( 'General Settings', 'basicrum-real-user-monitoring' ), '__return_empty_string', self::SLUG ); add_settings_field( 'enabled', - esc_html__( 'Enable Basicrum', 'basicrum' ), + esc_html__( 'Enable Basicrum', 'basicrum-real-user-monitoring' ), array( $this, 'render_checkbox_field' ), self::SLUG, 'basicrum_section_general', array( 'id' => 'enabled', - 'label' => __( 'Enable real user monitoring on your site.', 'basicrum' ), + 'label' => __( 'Enable real user monitoring on your site.', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'beacon_url', - esc_html__( 'Beacon URL', 'basicrum' ), + esc_html__( 'Beacon URL', 'basicrum-real-user-monitoring' ), array( $this, 'render_text_field' ), self::SLUG, 'basicrum_section_general', array( 'id' => 'beacon_url', 'label_for' => 'basicrum_beacon_url', - 'label' => __( 'URL where Boomerang beacons are sent. Example: https://www.example.com/beacon/catcher. Required when Basicrum is enabled.', 'basicrum' ), + 'label' => __( 'URL where Boomerang beacons are sent. Example: https://www.example.com/beacon/catcher. Required when Basicrum is enabled.', 'basicrum-real-user-monitoring' ), 'size' => 60, 'class' => $this->get_required_field_row_class( $settings, 'beacon_url' ), 'required_when_enabled' => true, - 'required_message' => __( 'Beacon URL is required when Basicrum is enabled.', 'basicrum' ), + 'required_message' => __( 'Beacon URL is required when Basicrum is enabled.', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'brum_site_id', - esc_html__( 'Brum Site ID', 'basicrum' ), + esc_html__( 'Brum Site ID', 'basicrum-real-user-monitoring' ), array( $this, 'render_text_field' ), self::SLUG, 'basicrum_section_general', array( 'id' => 'brum_site_id', 'label_for' => 'basicrum_brum_site_id', - 'label' => __( 'Copy the Brum Site ID from the Basicrum backoffice. Required when Basicrum is enabled.', 'basicrum' ), + 'label' => __( 'Copy the Brum Site ID from the Basicrum backoffice. Required when Basicrum is enabled.', 'basicrum-real-user-monitoring' ), 'size' => 40, 'class' => $this->get_required_field_row_class( $settings, 'brum_site_id' ), 'required_when_enabled' => true, - 'required_message' => __( 'Brum Site ID is required when Basicrum is enabled.', 'basicrum' ), + 'required_message' => __( 'Brum Site ID is required when Basicrum is enabled.', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'track_admins', - esc_html__( 'Track Admin Users', 'basicrum' ), + esc_html__( 'Track Admin Users', 'basicrum-real-user-monitoring' ), array( $this, 'render_checkbox_field' ), self::SLUG, 'basicrum_section_general', array( 'id' => 'track_admins', - 'label' => __( 'Track logged-in administrators (users with manage_options capability).', 'basicrum' ), + 'label' => __( 'Track logged-in administrators (users with manage_options capability).', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'boomerang_version', - esc_html__( 'Boomerang Version', 'basicrum' ), + esc_html__( 'Boomerang Version', 'basicrum-real-user-monitoring' ), array( $this, 'render_boomerang_version' ), self::SLUG, 'basicrum_section_general' @@ -331,46 +331,46 @@ private function add_privacy_section() { add_settings_section( 'basicrum_section_privacy', - esc_html__( 'Visitor Privacy', 'basicrum' ), + esc_html__( 'Visitor Privacy', 'basicrum-real-user-monitoring' ), array( $this, 'render_privacy_section_intro' ), self::SLUG ); add_settings_field( 'strip_query_string', - esc_html__( 'Strip Query Strings', 'basicrum' ), + esc_html__( 'Strip Query Strings', 'basicrum-real-user-monitoring' ), array( $this, 'render_checkbox_field' ), self::SLUG, 'basicrum_section_privacy', array( 'id' => 'strip_query_string', - 'label' => __( 'When enabled, replace complete query strings in page, navigation, referrer, and resource URLs with ?qs-redacted before sending beacons. URL paths are still collected.', 'basicrum' ), + 'label' => __( 'When enabled, replace complete query strings in page, navigation, referrer, and resource URLs with ?qs-redacted before sending beacons. URL paths are still collected.', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'consent_enabled', - esc_html__( 'Visitor Consent', 'basicrum' ), + esc_html__( 'Visitor Consent', 'basicrum-real-user-monitoring' ), array( $this, 'render_radio_field' ), self::SLUG, 'basicrum_section_privacy', array( 'id' => 'consent_enabled', - 'legend' => __( 'Visitor Consent', 'basicrum' ), - 'label' => __( 'Choose whether Boomerang requires an allow decision before monitoring a visitor.', 'basicrum' ), + 'legend' => __( 'Visitor Consent', 'basicrum-real-user-monitoring' ), + 'label' => __( 'Choose whether Boomerang requires an allow decision before monitoring a visitor.', 'basicrum-real-user-monitoring' ), 'announcement_class' => 'basicrum-consent-requirement-announcement', 'announcements' => array( - '0' => __( 'Consent Tool Connection hidden.', 'basicrum' ), - '1' => __( 'Consent Tool Connection shown.', 'basicrum' ), + '0' => __( 'Consent Tool Connection hidden.', 'basicrum-real-user-monitoring' ), + '1' => __( 'Consent Tool Connection shown.', 'basicrum-real-user-monitoring' ), ), 'options' => array( '0' => array( - 'label' => __( 'Monitor without consent', 'basicrum' ), - 'description' => __( 'Boomerang loads for visitors without a consent check. It may set cookies and send performance data. Use this only when your site is permitted to monitor without prior consent.', 'basicrum' ), + 'label' => __( 'Monitor without consent', 'basicrum-real-user-monitoring' ), + 'description' => __( 'Boomerang loads for visitors without a consent check. It may set cookies and send performance data. Use this only when your site is permitted to monitor without prior consent.', 'basicrum-real-user-monitoring' ), ), '1' => array( - 'label' => __( 'Require consent before monitoring (recommended)', 'basicrum' ), - 'description' => __( 'Boomerang stays off and no data is sent until your consent or cookie tool reports an allow decision on each page. Visitors who decline are not monitored. Connect your tool below under Consent Tool Connection.', 'basicrum' ), + 'label' => __( 'Require consent before monitoring (recommended)', 'basicrum-real-user-monitoring' ), + 'description' => __( 'Boomerang stays off and no data is sent until your consent or cookie tool reports an allow decision on each page. Visitors who decline are not monitored. Connect your tool below under Consent Tool Connection.', 'basicrum-real-user-monitoring' ), ), ), ) @@ -385,18 +385,18 @@ private function add_privacy_section() { array( 'id' => 'consent_integration', 'class' => $connection_row_class, - 'legend' => __( 'Consent Tool Connection', 'basicrum' ), + 'legend' => __( 'Consent Tool Connection', 'basicrum-real-user-monitoring' ), 'visible_legend' => true, - 'label' => __( 'Choose how your consent tool\'s decision reaches Basicrum.', 'basicrum' ), + 'label' => __( 'Choose how your consent tool\'s decision reaches Basicrum.', 'basicrum-real-user-monitoring' ), 'options' => array( ConsentIntegration::MODE_AUTOMATIC => array( - 'label' => __( 'Automatic connection (recommended)', 'basicrum' ), - 'description' => __( 'Best for most sites. Detect a supported consent tool and load one matching Basicrum adapter.', 'basicrum' ), + 'label' => __( 'Automatic connection (recommended)', 'basicrum-real-user-monitoring' ), + 'description' => __( 'Best for most sites. Detect a supported consent tool and load one matching Basicrum adapter.', 'basicrum-real-user-monitoring' ), 'controls' => 'basicrum-consent-automatic-panel', ), ConsentIntegration::MODE_MANUAL => array( - 'label' => __( 'Manual callbacks', 'basicrum' ), - 'description' => __( 'For unsupported or custom tools, or when a webmaster already manages the integration snippet.', 'basicrum' ), + 'label' => __( 'Manual callbacks', 'basicrum-real-user-monitoring' ), + 'description' => __( 'For unsupported or custom tools, or when a webmaster already manages the integration snippet.', 'basicrum-real-user-monitoring' ), 'controls' => 'basicrum-consent-manual-panel', ), ), @@ -412,7 +412,7 @@ private function add_privacy_section() { public function render_privacy_section_intro() { printf( '

%s

', - esc_html__( 'Control URL query-string handling and choose whether monitoring waits for visitor consent. Basicrum does not display a consent popup, determine your legal basis, or make a site compliant by itself.', 'basicrum' ) + esc_html__( 'Control URL query-string handling and choose whether monitoring waits for visitor consent. Basicrum does not display a consent popup, determine your legal basis, or make a site compliant by itself.', 'basicrum-real-user-monitoring' ) ); } @@ -424,32 +424,32 @@ public function render_privacy_section_intro() { private function add_performance_section() { add_settings_section( 'basicrum_section_performance', - esc_html__( 'Performance', 'basicrum' ), + esc_html__( 'Performance', 'basicrum-real-user-monitoring' ), '__return_empty_string', self::SLUG ); add_settings_field( 'wait_after_onload', - esc_html__( 'Wait After Onload', 'basicrum' ), + esc_html__( 'Wait After Onload', 'basicrum-real-user-monitoring' ), array( $this, 'render_checkbox_field' ), self::SLUG, 'basicrum_section_performance', array( 'id' => 'wait_after_onload', - 'label' => __( 'Delay beacon sending until after page load completes.', 'basicrum' ), + 'label' => __( 'Delay beacon sending until after page load completes.', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'delay_ms', - esc_html__( 'Delay (milliseconds)', 'basicrum' ), + esc_html__( 'Delay (milliseconds)', 'basicrum-real-user-monitoring' ), array( $this, 'render_number_field' ), self::SLUG, 'basicrum_section_performance', array( 'id' => 'delay_ms', - 'label' => __( 'Milliseconds to delay the beacon after onload. Leave 0 to disable the delay.', 'basicrum' ), + 'label' => __( 'Milliseconds to delay the beacon after onload. Leave 0 to disable the delay.', 'basicrum-real-user-monitoring' ), 'min' => 0, 'max' => 30000, ) @@ -457,17 +457,17 @@ private function add_performance_section() { add_settings_field( 'script_position', - esc_html__( 'Script Position', 'basicrum' ), + esc_html__( 'Script Position', 'basicrum-real-user-monitoring' ), array( $this, 'render_radio_field' ), self::SLUG, 'basicrum_section_performance', array( 'id' => 'script_position', - 'legend' => __( 'Script Position', 'basicrum' ), - 'label' => __( 'Where to insert the monitoring script.', 'basicrum' ), + 'legend' => __( 'Script Position', 'basicrum-real-user-monitoring' ), + 'label' => __( 'Where to insert the monitoring script.', 'basicrum-real-user-monitoring' ), 'options' => array( - 'header' => __( 'Header (wp_head)', 'basicrum' ), - 'footer' => __( 'Footer (wp_footer)', 'basicrum' ), + 'header' => __( 'Header (wp_head)', 'basicrum-real-user-monitoring' ), + 'footer' => __( 'Footer (wp_footer)', 'basicrum-real-user-monitoring' ), ), ) ); @@ -481,32 +481,32 @@ private function add_performance_section() { private function add_developer_section() { add_settings_section( 'basicrum_section_developer', - esc_html__( 'Developer Settings', 'basicrum' ), + esc_html__( 'Developer Settings', 'basicrum-real-user-monitoring' ), '__return_empty_string', self::SLUG ); add_settings_field( 'development_mode', - esc_html__( 'HTTP Strictness', 'basicrum' ), + esc_html__( 'HTTP Strictness', 'basicrum-real-user-monitoring' ), array( $this, 'render_checkbox_field' ), self::SLUG, 'basicrum_section_developer', array( 'id' => 'development_mode', - 'label' => __( 'Allow HTTP beacon URLs for local testing. Do not enable this on production sites.', 'basicrum' ), + 'label' => __( 'Allow HTTP beacon URLs for local testing. Do not enable this on production sites.', 'basicrum-real-user-monitoring' ), ) ); add_settings_field( 'use_unminified_loaders', - esc_html__( 'Use Unminified Loaders', 'basicrum' ), + esc_html__( 'Use Unminified Loaders', 'basicrum-real-user-monitoring' ), array( $this, 'render_checkbox_field' ), self::SLUG, 'basicrum_section_developer', array( 'id' => 'use_unminified_loaders', - 'label' => __( 'Load unminified JavaScript loaders for debugging.', 'basicrum' ), + 'label' => __( 'Load unminified JavaScript loaders for debugging.', 'basicrum-real-user-monitoring' ), ) ); } @@ -573,18 +573,18 @@ private function add_required_settings_notice() { $settings_link = sprintf( '%2$s', esc_url( admin_url( 'admin.php?page=' . self::SLUG ) ), - esc_html__( 'Basicrum Settings', 'basicrum' ) + esc_html__( 'Basicrum Settings', 'basicrum-real-user-monitoring' ) ); if ( in_array( 'beacon_url', $missing_settings, true ) && in_array( 'brum_site_id', $missing_settings, true ) ) { /* translators: %s: Link to the Basicrum settings page. */ - $message = sprintf( __( 'Basicrum monitoring is enabled but inactive because the Beacon URL and Brum Site ID are missing. Configure them in %s.', 'basicrum' ), $settings_link ); + $message = sprintf( __( 'Basicrum monitoring is enabled but inactive because the Beacon URL and Brum Site ID are missing. Configure them in %s.', 'basicrum-real-user-monitoring' ), $settings_link ); } elseif ( in_array( 'beacon_url', $missing_settings, true ) ) { /* translators: %s: Link to the Basicrum settings page. */ - $message = sprintf( __( 'Basicrum monitoring is enabled but inactive because the Beacon URL is missing. Configure it in %s.', 'basicrum' ), $settings_link ); + $message = sprintf( __( 'Basicrum monitoring is enabled but inactive because the Beacon URL is missing. Configure it in %s.', 'basicrum-real-user-monitoring' ), $settings_link ); } else { /* translators: %s: Link to the Basicrum settings page. */ - $message = sprintf( __( 'Basicrum monitoring is enabled but inactive because the Brum Site ID is missing. Configure it in %s.', 'basicrum' ), $settings_link ); + $message = sprintf( __( 'Basicrum monitoring is enabled but inactive because the Brum Site ID is missing. Configure it in %s.', 'basicrum-real-user-monitoring' ), $settings_link ); } add_settings_error( @@ -840,7 +840,7 @@ public function render_boomerang_version() { printf( '

v%s (%s)

', esc_html( $version ), - esc_html__( '~30 KB gzipped', 'basicrum' ) + esc_html__( '~30 KB gzipped', 'basicrum-real-user-monitoring' ) ); } @@ -883,49 +883,49 @@ public function render_consent_info() { $integrations = array( 'borlabs-cookie-v3' => array( - 'label' => __( 'Borlabs Cookie v3', 'basicrum' ), - 'description' => __( 'The manual adapter supports Borlabs Cookie 3.0.6 or newer. Automatic detection requires 3.2 or newer because it uses the public borlabsCookieApi() marker. Create and enable a Borlabs service with the ID basicrum, normally in the Statistics service group. Add this adapter as unblocked site code that runs on every page.', 'basicrum' ), + 'label' => __( 'Borlabs Cookie v3', 'basicrum-real-user-monitoring' ), + 'description' => __( 'The manual adapter supports Borlabs Cookie 3.0.6 or newer. Automatic detection requires 3.2 or newer because it uses the public borlabsCookieApi() marker. Create and enable a Borlabs service with the ID basicrum, normally in the Statistics service group. Add this adapter as unblocked site code that runs on every page.', 'basicrum-real-user-monitoring' ), 'snippets' => array( array( - 'label' => __( 'Borlabs Cookie adapter', 'basicrum' ), + 'label' => __( 'Borlabs Cookie adapter', 'basicrum-real-user-monitoring' ), 'path' => 'js/integrations/borlabs-cookie-v3.js', 'rows' => 18, ), ), ), 'wp-consent-api' => array( - 'label' => __( 'WP Consent API', 'basicrum' ), - 'description' => __( 'Install and activate the standalone WP Consent API plugin, then use this shared adapter with a consent tool such as Complianz or CookieYes that publishes its Statistics decision through the API. Complianz does not include WP Consent API by itself.', 'basicrum' ), + 'label' => __( 'WP Consent API', 'basicrum-real-user-monitoring' ), + 'description' => __( 'Install and activate the standalone WP Consent API plugin, then use this shared adapter with a consent tool such as Complianz or CookieYes that publishes its Statistics decision through the API. Complianz does not include WP Consent API by itself.', 'basicrum-real-user-monitoring' ), 'snippets' => array( array( - 'label' => __( 'WP Consent API adapter', 'basicrum' ), + 'label' => __( 'WP Consent API adapter', 'basicrum-real-user-monitoring' ), 'path' => 'js/integrations/wp-consent-api.js', 'rows' => 18, ), ), ), 'cookieyes' => array( - 'label' => __( 'CookieYes', 'basicrum' ), - 'description' => __( 'Use this direct adapter only for a connected modern CookieYes 3.x installation when WP Consent API is not active. CookieYes legacy mode uses an incompatible browser API and is deliberately not detected. The adapter follows the Analytics category and fails closed when the browser API is unavailable.', 'basicrum' ), + 'label' => __( 'CookieYes', 'basicrum-real-user-monitoring' ), + 'description' => __( 'Use this direct adapter only for a connected modern CookieYes 3.x installation when WP Consent API is not active. CookieYes legacy mode uses an incompatible browser API and is deliberately not detected. The adapter follows the Analytics category and fails closed when the browser API is unavailable.', 'basicrum-real-user-monitoring' ), 'snippets' => array( array( - 'label' => __( 'CookieYes adapter', 'basicrum' ), + 'label' => __( 'CookieYes adapter', 'basicrum-real-user-monitoring' ), 'path' => 'js/integrations/cookieyes.js', 'rows' => 18, ), ), ), 'generic' => array( - 'label' => __( 'Generic', 'basicrum' ), - 'description' => __( 'Use these separate snippets when your consent tool provides custom callbacks for an allow decision and a deny, expiry, or withdrawal decision.', 'basicrum' ), + 'label' => __( 'Generic', 'basicrum-real-user-monitoring' ), + 'description' => __( 'Use these separate snippets when your consent tool provides custom callbacks for an allow decision and a deny, expiry, or withdrawal decision.', 'basicrum-real-user-monitoring' ), 'snippets' => array( array( - 'label' => __( 'Allow or grant callback', 'basicrum' ), + 'label' => __( 'Allow or grant callback', 'basicrum-real-user-monitoring' ), 'path' => 'js/integrations/generic-opt-in.js', 'rows' => 9, ), array( - 'label' => __( 'Deny, expiry, or withdrawal callback', 'basicrum' ), + 'label' => __( 'Deny, expiry, or withdrawal callback', 'basicrum-real-user-monitoring' ), 'path' => 'js/integrations/generic-opt-out.js', 'rows' => 9, ), @@ -935,8 +935,8 @@ public function render_consent_info() { ?>