diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..28066be
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.php eol=lf
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6d20bf2..0cdd05f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -53,8 +53,8 @@ docker compose --profile test run --rm test
# Build plugin zip
docker compose --profile build run --rm build
-# Run WordPress.org Plugin Check
-docker compose up -d && docker compose --profile plugin-check run --rm plugin-check
+# Run WordPress.org Plugin Check (package first, then check)
+./package.sh && docker compose --profile plugin-check run --rm plugin-check
# Clean up everything (including volumes)
docker compose down -v
@@ -86,15 +86,11 @@ docker compose --profile test run --rm test vendor/bin/phpunit --verbose
## Plugin Check (WordPress.org Validation)
-Run the official [WordPress Plugin Check](https://wordpress.org/plugins/plugin-check/) tool to validate the plugin against WordPress.org submission requirements and best practices.
+Run the official [WordPress Plugin Check](https://wordpress.org/plugins/plugin-check/) tool to validate the plugin against WordPress.org submission requirements and best practices. The check runs against the packaged zip to match exactly what WordPress.org reviewers see.
```bash
-# Run all checks (comprehensive - for development)
-docker compose up -d && docker compose --profile plugin-check run --rm plugin-check
-
-# Run only plugin_repo category (required checks for WordPress.org submission)
-docker compose up -d && docker compose --profile plugin-check run --rm plugin-check \
- wp plugin check betterlytics --categories=plugin_repo --format=table
+# Package the plugin and run all checks
+./package.sh && docker compose --profile plugin-check run --rm plugin-check
```
### Check Categories
diff --git a/docker-compose.yml b/docker-compose.yml
index bd40a10..f57b5e9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -89,7 +89,7 @@ services:
volumes:
- .:/app
working_dir: /app
- command: sh -c "composer install && vendor/bin/phpcs"
+ command: sh -c "git config --global --add safe.directory /app && composer install && vendor/bin/phpcs -v"
profiles:
- lint
@@ -98,7 +98,7 @@ services:
volumes:
- .:/app
working_dir: /app
- command: sh -c "composer install && vendor/bin/phpcbf"
+ command: sh -c "git config --global --add safe.directory /app && composer install && vendor/bin/phpcbf"
profiles:
- lint-fix
@@ -161,7 +161,7 @@ services:
WORDPRESS_DB_NAME: ${MYSQL_DATABASE:-wordpress}
volumes:
- wordpress_data:/var/www/html
- - .:/var/www/html/wp-content/plugins/betterlytics
+ - ./betterlytics.zip:/tmp/betterlytics.zip:ro
depends_on:
wordpress:
condition: service_healthy
@@ -173,7 +173,8 @@ services:
- plugin-check
command: >
sh -c '
- echo "Installing Plugin Check..." &&
+ echo "Installing plugin from betterlytics.zip..." &&
+ wp plugin install /tmp/betterlytics.zip --force --activate &&
wp plugin install plugin-check --activate &&
echo "" &&
echo "Running Plugin Check on betterlytics..." &&
diff --git a/public/class-betterlytics-public.php b/public/class-betterlytics-public.php
index 0a1ea02..1614c68 100644
--- a/public/class-betterlytics-public.php
+++ b/public/class-betterlytics-public.php
@@ -50,15 +50,6 @@ public function __construct( $plugin_name, $version ) {
public function inject_tracking_script() {
$options = Betterlytics_Options::get_options();
- // Debug: Log tracking check.
- if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
- $tracking_status = Betterlytics_Options::is_tracking_enabled() ? 'ENABLED' : 'DISABLED';
- // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug only.
- error_log( '[Betterlytics] Tracking status: ' . $tracking_status );
- // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug only.
- error_log( '[Betterlytics] Options: ' . wp_json_encode( $options ) );
- }
-
if ( ! Betterlytics_Options::is_tracking_enabled() ) {
return;
}
@@ -83,8 +74,8 @@ public function inject_tracking_script() {
]
);
- // Add filter for data-* attributes.
- add_filter( 'script_loader_tag', [ $this, 'add_tracker_script_attributes' ], 10, 2 );
+ // Add data-* attributes via wp_script_attributes filter.
+ add_filter( 'wp_script_attributes', [ $this, 'add_tracker_script_attributes' ] );
// Build inline script for event queue buffer.
$inline_script = 'window.betterlytics = window.betterlytics || { event: function() { (window.betterlytics.q = window.betterlytics.q || []).push(arguments); } };';
@@ -107,30 +98,22 @@ public function inject_tracking_script() {
* Add data attributes to the tracking script tag.
*
* @since 1.0.0
- * @param string $tag The script tag HTML.
- * @param string $handle The script handle.
- * @return string Modified script tag.
+ * @param array $attr Script tag attributes.
+ * @return array Modified attributes.
*/
- public function add_tracker_script_attributes( $tag, $handle ) {
- if ( 'betterlytics-tracker' !== $handle ) {
- return $tag;
+ public function add_tracker_script_attributes( $attr ) {
+ if ( ! isset( $attr['id'] ) || 'betterlytics-tracker-js' !== $attr['id'] ) {
+ return $attr;
}
$options = Betterlytics_Options::get_options();
- // Build data attributes string.
- $data_attrs = sprintf(
- ' data-site-id="%s" data-server-url="%s" data-outbound-links="%s" data-web-vitals="%s"',
- esc_attr( $options['site_id'] ),
- esc_url( $options['server_url'] ),
- esc_attr( $options['track_outbound']['mode'] ),
- ! empty( $options['track_web_vitals'] ) ? 'true' : 'false'
- );
-
- // Insert data attributes before the closing >.
- $tag = str_replace( '>', $data_attrs . '>', $tag );
+ $attr['data-site-id'] = esc_attr( $options['site_id'] );
+ $attr['data-server-url'] = esc_url( $options['server_url'] );
+ $attr['data-outbound-links'] = esc_attr( $options['track_outbound']['mode'] );
+ $attr['data-web-vitals'] = ! empty( $options['track_web_vitals'] ) ? 'true' : 'false';
- return $tag;
+ return $attr;
}
/**
diff --git a/tests/class-betterlytics-test-case.php b/tests/class-betterlytics-test-case.php
index ff1ebff..2cbb3f3 100644
--- a/tests/class-betterlytics-test-case.php
+++ b/tests/class-betterlytics-test-case.php
@@ -8,7 +8,7 @@
/**
* Base test case class.
*/
-class Betterlytics_Test_Case extends WP_UnitTestCase {
+abstract class Betterlytics_Test_Case extends WP_UnitTestCase {
/**
* Set up test fixtures.
diff --git a/tests/test-public.php b/tests/test-public.php
index 21c10f3..5905c93 100644
--- a/tests/test-public.php
+++ b/tests/test-public.php
@@ -225,13 +225,13 @@ public function test_web_vitals_enabled() {
)
);
- $this->public->inject_tracking_script();
-
- // Check the data attributes via the filter method.
- $test_tag = '';
- $result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
+ $attr = array(
+ 'id' => 'betterlytics-tracker-js',
+ 'src' => 'https://analytics.example.com/script.js',
+ );
+ $result = $this->public->add_tracker_script_attributes( $attr );
- $this->assertStringContainsString( 'data-web-vitals="true"', $result );
+ $this->assertEquals( 'true', $result['data-web-vitals'] );
}
/**
@@ -246,13 +246,13 @@ public function test_web_vitals_disabled() {
)
);
- $this->public->inject_tracking_script();
-
- // Check the data attributes via the filter method.
- $test_tag = '';
- $result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
+ $attr = array(
+ 'id' => 'betterlytics-tracker-js',
+ 'src' => 'https://analytics.example.com/script.js',
+ );
+ $result = $this->public->add_tracker_script_attributes( $attr );
- $this->assertStringContainsString( 'data-web-vitals="false"', $result );
+ $this->assertEquals( 'false', $result['data-web-vitals'] );
}
/**
@@ -267,13 +267,13 @@ public function test_outbound_links_domain_mode() {
)
);
- $this->public->inject_tracking_script();
-
- // Check the data attributes via the filter method.
- $test_tag = '';
- $result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
+ $attr = array(
+ 'id' => 'betterlytics-tracker-js',
+ 'src' => 'https://analytics.example.com/script.js',
+ );
+ $result = $this->public->add_tracker_script_attributes( $attr );
- $this->assertStringContainsString( 'data-outbound-links="domain"', $result );
+ $this->assertEquals( 'domain', $result['data-outbound-links'] );
}
/**
@@ -288,13 +288,13 @@ public function test_outbound_links_full_mode() {
)
);
- $this->public->inject_tracking_script();
-
- // Check the data attributes via the filter method.
- $test_tag = '';
- $result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
+ $attr = array(
+ 'id' => 'betterlytics-tracker-js',
+ 'src' => 'https://analytics.example.com/script.js',
+ );
+ $result = $this->public->add_tracker_script_attributes( $attr );
- $this->assertStringContainsString( 'data-outbound-links="full"', $result );
+ $this->assertEquals( 'full', $result['data-outbound-links'] );
}
/**
@@ -309,13 +309,13 @@ public function test_outbound_links_off_mode() {
)
);
- $this->public->inject_tracking_script();
-
- // Check the data attributes via the filter method.
- $test_tag = '';
- $result = $this->public->add_tracker_script_attributes( $test_tag, 'betterlytics-tracker' );
+ $attr = array(
+ 'id' => 'betterlytics-tracker-js',
+ 'src' => 'https://analytics.example.com/script.js',
+ );
+ $result = $this->public->add_tracker_script_attributes( $attr );
- $this->assertStringContainsString( 'data-outbound-links="off"', $result );
+ $this->assertEquals( 'off', $result['data-outbound-links'] );
}
/**
@@ -329,10 +329,14 @@ public function test_filter_ignores_other_handles() {
)
);
- $test_tag = '';
- $result = $this->public->add_tracker_script_attributes( $test_tag, 'other-script' );
+ $attr = array(
+ 'id' => 'other-script-js',
+ 'src' => 'https://example.com/other.js',
+ );
+ $result = $this->public->add_tracker_script_attributes( $attr );
- // Should return unchanged.
- $this->assertEquals( $test_tag, $result );
+ // Should return unchanged — no data-* keys added.
+ $this->assertArrayNotHasKey( 'data-site-id', $result );
+ $this->assertEquals( $attr, $result );
}
}