From 9c1c6590e89e2ea4ca388c90b79e3018905fac79 Mon Sep 17 00:00:00 2001 From: Mehmood Ahmad <31419912+mehmoodak@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:42:34 +0500 Subject: [PATCH] Adds Tracks Analytics on backend (#155) Adds Tracks Analytics by using the Telemetry library available in MU Plugins which will only work if site is hosted on VIP Platform or if the analytics is enabled via filter. --- composer.json | 3 +- composer.lock | 43 ++- inc/Analytics/EnvironmentConfig.php | 81 +++++ inc/Analytics/TracksAnalytics.php | 170 +++++++++++ inc/Config/DataSource/HttpDataSource.php | 9 +- inc/Editor/BlockManagement/ConfigStore.php | 32 +- inc/REST/DataSourceController.php | 61 +++- psalm.xml | 2 + remote-data-blocks.php | 3 + src/data-sources/hooks/useDataSources.ts | 12 +- tests/inc/Analytics/EnvironmentConfigTest.php | 77 +++++ tests/inc/Analytics/TracksAnalyticsTest.php | 277 ++++++++++++++++++ tests/inc/Config/HttpDataSourceTest.php | 23 ++ tests/inc/Editor/ConfigStoreTest.php | 32 ++ tests/inc/bootstrap.php | 1 + tests/inc/stubs.php | 22 +- tests/inc/test-utils.php | 61 ++++ 17 files changed, 891 insertions(+), 18 deletions(-) create mode 100644 inc/Analytics/EnvironmentConfig.php create mode 100644 inc/Analytics/TracksAnalytics.php create mode 100644 tests/inc/Analytics/EnvironmentConfigTest.php create mode 100644 tests/inc/Analytics/TracksAnalyticsTest.php create mode 100644 tests/inc/Config/HttpDataSourceTest.php create mode 100644 tests/inc/Editor/ConfigStoreTest.php create mode 100644 tests/inc/test-utils.php diff --git a/composer.json b/composer.json index 06279533..65ef6b5f 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,8 @@ "slevomat/coding-standard": "^8.15", "php-stubs/wordpress-stubs": "^6.6", "psalm/phar": "^5.26", - "mockery/mockery": "^1.6" + "mockery/mockery": "^1.6", + "php-stubs/wordpress-globals": "^0.2.0" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 51eb7b72..78bcf23e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "829c7d99f898737644ae2dd3d45313e0", + "content-hash": "5e0d80162087cfd0477746d29ec55e89", "packages": [ { "name": "galbar/jsonpath", @@ -1292,6 +1292,47 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-stubs/wordpress-globals", + "version": "v0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wordpress-globals.git", + "reference": "748a1fb2ae8fda94844bd0545935095dbf404b32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wordpress-globals/zipball/748a1fb2ae8fda94844bd0545935095dbf404b32", + "reference": "748a1fb2ae8fda94844bd0545935095dbf404b32", + "shasum": "" + }, + "require-dev": { + "php": "~7.1" + }, + "suggest": { + "php-stubs/wordpress-stubs": "Up-to-date WordPress function and class declaration stubs", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Global variables and global constants from WordPress core.", + "homepage": "https://github.com/php-stubs/wordpress-globals", + "keywords": [ + "PHPStan", + "constants", + "globals", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/php-stubs/wordpress-globals/issues", + "source": "https://github.com/php-stubs/wordpress-globals/tree/master" + }, + "time": "2020-01-13T06:12:59+00:00" + }, { "name": "php-stubs/wordpress-stubs", "version": "v6.6.2", diff --git a/inc/Analytics/EnvironmentConfig.php b/inc/Analytics/EnvironmentConfig.php new file mode 100644 index 00000000..fe52b93e --- /dev/null +++ b/inc/Analytics/EnvironmentConfig.php @@ -0,0 +1,81 @@ + + */ + private array $tracks_core_props = []; + + public function __construct() { + if ( function_exists( 'Automattic\VIP\Telemetry\Tracks\get_tracks_core_properties' ) ) { + add_action( 'init', function (): void { + /** @psalm-suppress UndefinedFunction */ + $this->tracks_core_props = get_tracks_core_properties(); + } ); + } + } + + public function is_enabled_via_filter(): bool { + return apply_filters( 'remote_data_blocks_enable_tracks_analytics', false ) ?? false; + } + + public function get_tracks_lib_class(): ?string { + if ( ! class_exists( 'Automattic\VIP\Telemetry\Tracks' ) ) { + return null; + } + + return Tracks::class; + } + + public function is_wpvip_site(): bool { + if ( ! isset( $this->tracks_core_props['hosting_provider'] ) ) { + return false; + } + + return 'wpvip' === $this->tracks_core_props['hosting_provider']; + } + + public function is_local_env(): bool { + if ( ! isset( $this->tracks_core_props['vipgo_env'] ) ) { + return false; + } + + return 'local' === $this->tracks_core_props['vipgo_env']; + } + + public function is_remote_data_blocks_plugin( string|null $plugin_path ): bool { + return 'remote-data-blocks/remote-data-blocks.php' === $plugin_path; + } + + public function should_track_post_having_remote_data_blocks( int $post_id ): bool { + // Ensure this is not an auto-save or revision. + if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { + return false; + } + + return true; + } + + /** + * Get the core properties to be sent with each event. + */ + public function get_tracks_core_properties(): array { + return $this->tracks_core_props; + } +} diff --git a/inc/Analytics/TracksAnalytics.php b/inc/Analytics/TracksAnalytics.php new file mode 100644 index 00000000..f6fa05e2 --- /dev/null +++ b/inc/Analytics/TracksAnalytics.php @@ -0,0 +1,170 @@ +is_local_env() ) { + return; + } + + $tracks_class = self::$env_config->get_tracks_lib_class(); + if ( ! $tracks_class ) { + return; + } + + if ( self::$env_config->is_wpvip_site() || self::$env_config->is_enabled_via_filter() ) { + self::$instance = new $tracks_class( '', self::get_global_properties() ); + self::setup_tracking_via_hooks(); + } + } + + /** + * Get `Tracks` global properties to be sent with each event. + */ + public static function get_global_properties(): array { + $rdb_specific_props = [ + 'plugin_version' => defined( 'REMOTE_DATA_BLOCKS__PLUGIN_VERSION' ) ? constant( 'REMOTE_DATA_BLOCKS__PLUGIN_VERSION' ) : '', + ]; + + return array_merge( $rdb_specific_props, self::$env_config->get_tracks_core_properties() ); + } + + private static function setup_tracking_via_hooks(): void { + // WordPress Dashboard Hooks. + add_action( 'activated_plugin', [ __CLASS__, 'track_plugin_activation' ] ); + add_action( 'deactivated_plugin', [ __CLASS__, 'track_plugin_deactivation' ] ); + add_action( 'save_post', [ __CLASS__, 'track_remote_data_blocks_usage' ], 10, 2 ); + } + + /** + * Activation hook. + * + * @param string $plugin_path Path of the plugin that was activated. + */ + public static function track_plugin_activation( string $plugin_path ): void { + if ( ! self::$env_config->is_remote_data_blocks_plugin( $plugin_path ) ) { + return; + } + + self::record_event( 'remotedatablocks_plugin_toggle', [ 'action' => 'activate' ] ); + } + + /** + * Deactivation hook. + * + * @param string $plugin_path Path of the plugin that was deactivated. + */ + public static function track_plugin_deactivation( string $plugin_path ): void { + if ( ! self::$env_config->is_remote_data_blocks_plugin( $plugin_path ) ) { + return; + } + + self::record_event( 'remotedatablocks_plugin_toggle', [ 'action' => 'deactivate' ] ); + } + + /** + * Track usage of Remote Data Blocks. + * + * @param int $post_id Post ID. + * @param \WP_Post $post Post object. + */ + public static function track_remote_data_blocks_usage( int $post_id, object $post ): void { + if ( ! self::$env_config->should_track_post_having_remote_data_blocks( $post_id ) ) { + return; + } + + $post_status = $post->post_status; + if ( 'publish' !== $post_status ) { + return; + } + + // Regular expression to match all remote data blocks present in the post content. + $reg_exp = '/
Our floating shelf is the perfect way to store all your Tonal accessories. Its sleek, versatile design makes this an easy fit with any style room. Available in Coffee Oak (seen here), as well as Matte Black and Light Aged Ash. Made in the U.S.
$272.99
No detail is too small. Tonal’s proprietary T-Locks let you swap out Tonal accessories with a quick push and twist to lock everything in place.
$42.99
Pearl room
Panel