From f325567cb80781fad0a518103213c82a80d02afc Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 28 Oct 2024 08:31:56 -0600 Subject: [PATCH 1/9] Add a Perflab_Performance_Marks class --- .../class-perflab-performance-marks.php | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php diff --git a/plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php b/plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php new file mode 100644 index 0000000000..99b45c53f1 --- /dev/null +++ b/plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php @@ -0,0 +1,84 @@ +> + */ + private $marks = array(); + + /** + * Add a mark to the list of marks. + * + * @since n.e.x.t + * + * @param string $mark_slug The slug of the mark. + * @param array $args Arguments for the mark. + */ + public function add_mark( string $mark_slug, array $args ): void { + $this->marks[ $mark_slug ] = $args; + } + + /** + * Get a mark by its slug. + * + * @since n.e.x.t + * + * @param string $mark_slug The slug of the mark. + * @return array|null The mark, or null if not found. + */ + public function get_mark( string $mark_slug ): ?array { + return $this->marks[ $mark_slug ] ?? null; + } + + /** + * Get all of the marks. + * + * @since n.e.x.t + * + * @return array> All of the marks. + */ + public function get_all_marks(): array { + return $this->marks; + } + + /** + * Send the marks to the Dev Tools Performance panel. + * + * Outputs inline JavaScript that uses the Dev Tools Performance API to add marks to the timeline. + * + * This function should be called in the footer after all data has been collected. + * + * @since n.e.x.t + */ + public function send_marks(): void { + echo ( '' ); + } +} From d9ee3ef1d8f6fe6cce2d6e4e6c60de125034e007 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 28 Oct 2024 10:25:17 -0600 Subject: [PATCH 2/9] Start adding script performance marks --- .../class-perflab-performance-marks.php | 48 ++++++++++++++++--- .../includes/performance-marks/hooks.php | 18 +++++++ .../includes/performance-marks/load.php | 38 +++++++++++++++ plugins/performance-lab/load.php | 4 ++ 4 files changed, 102 insertions(+), 6 deletions(-) rename plugins/performance-lab/includes/{server-timing => performance-marks}/class-perflab-performance-marks.php (59%) create mode 100644 plugins/performance-lab/includes/performance-marks/hooks.php create mode 100644 plugins/performance-lab/includes/performance-marks/load.php diff --git a/plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php similarity index 59% rename from plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php rename to plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php index 99b45c53f1..260f0bd92f 100644 --- a/plugins/performance-lab/includes/server-timing/class-perflab-performance-marks.php +++ b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php @@ -69,15 +69,51 @@ public function get_all_marks(): array { * @since n.e.x.t */ public function send_marks(): void { + global $wp_scripts; + + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + $all_plugins = get_plugins(); + + // Map TextDomain to Name. This only works when the handle matches the text domain. + $plugin_name_map = array(); + foreach ( $all_plugins as $plugin_slug => $plugin_data ) { + $plugin_name_map[ $plugin_data['TextDomain'] ] = $plugin_data['Name']; + } + + // Save the data to the error log so you can see what the array format is like. + error_log( print_r( $plugin_name_map, true ) ); + + foreach ( $wp_scripts->done as $handle ) { + $name = isset( $plugin_name_map[ $handle ] ) ? $plugin_name_map[ $handle ] : $handle; + $src = $wp_scripts->registered[ $handle ]->src; + perflab_performance_marks()->add_mark( + 'script_enqueue::' . $handle, + array( + 'slug' => $handle, + 'src' => $src, + 'name' => $name, + ) + ); + } + error_log( "send marks!" ); + if ( empty( $this->marks ) ) { + error_log( "no marks!" ); + return; + } echo ( '' ); } diff --git a/plugins/performance-lab/includes/performance-marks/hooks.php b/plugins/performance-lab/includes/performance-marks/hooks.php new file mode 100644 index 0000000000..db72a7a7c9 --- /dev/null +++ b/plugins/performance-lab/includes/performance-marks/hooks.php @@ -0,0 +1,18 @@ + Date: Mon, 28 Oct 2024 15:04:19 -0600 Subject: [PATCH 3/9] Include correct slug and name in data --- .../class-perflab-performance-marks.php | 103 +++++++++++++----- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php index 260f0bd92f..fc095d202b 100644 --- a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php +++ b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php @@ -24,6 +24,29 @@ class Perflab_Performance_Marks { */ private $marks = array(); + /** + * Array of all plugins and their data. + * + * @since n.e.x.t + * + * @var array> + */ + private $plugins_data = array(); + + /** + * Initialize the class including plugin data. + * + * @since n.e.x.t + */ + public function __construct() { + global $wp_scripts; + + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + $this->plugins_data = get_plugins(); + } + /** * Add a mark to the list of marks. * @@ -71,50 +94,78 @@ public function get_all_marks(): array { public function send_marks(): void { global $wp_scripts; - if ( ! function_exists( 'get_plugins' ) ) { - require_once ABSPATH . 'wp-admin/includes/plugin.php'; - } - - $all_plugins = get_plugins(); - - // Map TextDomain to Name. This only works when the handle matches the text domain. - $plugin_name_map = array(); - foreach ( $all_plugins as $plugin_slug => $plugin_data ) { - $plugin_name_map[ $plugin_data['TextDomain'] ] = $plugin_data['Name']; - } - - // Save the data to the error log so you can see what the array format is like. - error_log( print_r( $plugin_name_map, true ) ); - foreach ( $wp_scripts->done as $handle ) { - $name = isset( $plugin_name_map[ $handle ] ) ? $plugin_name_map[ $handle ] : $handle; $src = $wp_scripts->registered[ $handle ]->src; + if ( false === $src ) { + continue; + } + // Gather the plugin slug, name at relative path. + $plugin_data = $this->get_plugin_data_from_src( $src ); perflab_performance_marks()->add_mark( 'script_enqueue::' . $handle, array( - 'slug' => $handle, - 'src' => $src, - 'name' => $name, + 'path' => $plugin_data['path'], + 'slug' => $plugin_data['slug'], + 'name' => $plugin_data['name'], ) ); } - error_log( "send marks!" ); - if ( empty( $this->marks ) ) { - error_log( "no marks!" ); + if ( empty( $this->marks ) ) { return; } echo ( '' ); } + + /** + * Helper function to get the plugin slug and name when passed a script path. + * + * @since n.e.x.t + * + * @param string $src The script path. + * @return array The plugin slug, name and path. + */ + private function get_plugin_data_from_src( string $src ): array { + + // Get just the local path for the src (removing the local domain). + $src = str_replace( get_site_url(), '', $src ); + + if ( str_starts_with( $src, '/wp-includes/' ) ) { + return array( + 'slug' => 'core', + 'name' => 'Core', + 'path' => $src, + ); + } + + // Extract the slug from $src, eg. "/wp-content/plugins/{slug}/path/to/script.js". + $slugs = explode( '/', $src ); + $slug = $slugs[3]; + + foreach ( $this->plugins_data as $plugin_slug => $plugin_data ) { + if ( $slug === $plugin_data['TextDomain'] ) { + return array( + 'slug' => $plugin_data['TextDomain'], + 'name' => $plugin_data['Name'], + 'path' => $src, + ); + } + } + return array( + 'slug' => '', + 'name' => '', + 'path' => $src, + ); + } } From 6bd639617523dfbab6b47ace6a1267ad9c5d6017 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 28 Oct 2024 15:12:19 -0600 Subject: [PATCH 4/9] Fix phpstan errors --- plugins/embed-optimizer/hooks.php | 5 +++-- .../optimization-detective/class-od-html-tag-processor.php | 6 +++--- .../storage/class-od-url-metrics-post-type.php | 4 ++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/embed-optimizer/hooks.php b/plugins/embed-optimizer/hooks.php index 5dffa10f5a..8a4fb0bba2 100644 --- a/plugins/embed-optimizer/hooks.php +++ b/plugins/embed-optimizer/hooks.php @@ -181,8 +181,9 @@ function embed_optimizer_update_markup( WP_HTML_Tag_Processor $html_processor, b 'script' => 'embed_optimizer_script', 'iframe' => 'embed_optimizer_iframe', ); - $trigger_error = static function ( string $message ): void { - wp_trigger_error( __FUNCTION__, esc_html( $message ) ); + $function_name = __FUNCTION__; + $trigger_error = static function ( string $message ) use ( &$function_name ): void { + wp_trigger_error( $function_name, esc_html( $message ) ); }; try { /* diff --git a/plugins/optimization-detective/class-od-html-tag-processor.php b/plugins/optimization-detective/class-od-html-tag-processor.php index 4d9c25137d..51afb4b4e5 100644 --- a/plugins/optimization-detective/class-od-html-tag-processor.php +++ b/plugins/optimization-detective/class-od-html-tag-processor.php @@ -625,10 +625,10 @@ public function get_updated_html(): string { * * @since 0.4.0 * - * @param string $function_name Function name. - * @param string $message Warning message. + * @param callable-string $function_name Function name. + * @param string $message Warning message. */ - private function warn( string $function_name, string $message ): void { + private function warn( callable $function_name, string $message ): void { wp_trigger_error( $function_name, esc_html( $message ) diff --git a/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php b/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php index c59ef9a204..0115524b29 100644 --- a/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php +++ b/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php @@ -119,6 +119,10 @@ public static function get_post( string $slug ): ?WP_Post { public static function get_url_metrics_from_post( WP_Post $post ): array { $this_function = __METHOD__; $trigger_error = static function ( string $message, int $error_level = E_USER_NOTICE ) use ( $this_function ): void { + // Default to E_USER_NOTICE. + if ( ! in_array( $error_level, array( E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR, E_USER_DEPRECATED ), true ) ) { + $error_level = E_USER_NOTICE; + } wp_trigger_error( $this_function, esc_html( $message ), $error_level ); }; From 044d19eec5011b8e9c3a5a427d83c0bd781286e3 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 29 Oct 2024 07:39:00 -0600 Subject: [PATCH 5/9] Update plugins/embed-optimizer/hooks.php Co-authored-by: Weston Ruter --- plugins/embed-optimizer/hooks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/embed-optimizer/hooks.php b/plugins/embed-optimizer/hooks.php index 8a4fb0bba2..a512ac9c63 100644 --- a/plugins/embed-optimizer/hooks.php +++ b/plugins/embed-optimizer/hooks.php @@ -182,7 +182,7 @@ function embed_optimizer_update_markup( WP_HTML_Tag_Processor $html_processor, b 'iframe' => 'embed_optimizer_iframe', ); $function_name = __FUNCTION__; - $trigger_error = static function ( string $message ) use ( &$function_name ): void { + $trigger_error = static function ( string $message ) use ( $function_name ): void { wp_trigger_error( $function_name, esc_html( $message ) ); }; try { From 23159025a1cbc64f7da5178302a478706f74a087 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 29 Oct 2024 13:46:19 -0600 Subject: [PATCH 6/9] Remove unused code --- .../includes/performance-marks/load.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/plugins/performance-lab/includes/performance-marks/load.php b/plugins/performance-lab/includes/performance-marks/load.php index 0a1378895e..c3b392f7c8 100644 --- a/plugins/performance-lab/includes/performance-marks/load.php +++ b/plugins/performance-lab/includes/performance-marks/load.php @@ -12,21 +12,6 @@ require_once __DIR__ . '/hooks.php'; -/** - * Provides access to the performance marks API. - * - * @since n.e.x.t - */ -function perflab_performance_marks(): Perflab_Performance_Marks { - static $performance_marks; - - if ( null === $performance_marks ) { - $performance_marks = new Perflab_Performance_Marks(); - } - - return $performance_marks; -} - /** * Initialize the performance marks API. * From 193b04c23c8b38039e448aeaeb3770c92dc8a6f4 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 29 Oct 2024 14:11:23 -0600 Subject: [PATCH 7/9] Attribution for scripts output in wp_head or wp_footer --- .../class-perflab-performance-marks.php | 137 +++++++++++++++++- .../includes/performance-marks/hooks.php | 2 +- .../includes/performance-marks/load.php | 17 +++ 3 files changed, 152 insertions(+), 4 deletions(-) diff --git a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php index fc095d202b..9ecf6fdbcf 100644 --- a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php +++ b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php @@ -94,6 +94,23 @@ public function get_all_marks(): array { public function send_marks(): void { global $wp_scripts; + // Collect any scripts output directly. + remove_action( 'wp_footer', array( perflab_performance_marks(), 'send_marks' ), 999 ); + $manually_output_scripts = $this->get_manually_output_scripts(); + + // Add the manually output scripts to the marks. + foreach ( $manually_output_scripts as $script ) { + + $this->add_mark( + 'script_output::' . $script['slug'], + array( + 'path' => $script['path'], + 'slug' => $script['slug'], + 'name' => $script['name'], + ) + ); + } + foreach ( $wp_scripts->done as $handle ) { $src = $wp_scripts->registered[ $handle ]->src; if ( false === $src ) { @@ -123,7 +140,7 @@ public function send_marks(): void { wp_json_encode( $mark_args ), esc_attr( (string) $x ) ); - $x = $x + 10; + ++$x; } echo( '' ); } @@ -153,19 +170,133 @@ private function get_plugin_data_from_src( string $src ): array { $slugs = explode( '/', $src ); $slug = $slugs[3]; + $plugin_data = $this->get_plugin_data_by_slug( $slug ); + + return array( + 'slug' => $plugin_data['slug'], + 'name' => $plugin_data['name'], + 'path' => $src, + ); + } + + /** + * Get data for plugin by slug. + * + * @since n.e.x.t + * + * @param string $slug The plugin slug. + * @return array The plugin slug and name. + */ + private function get_plugin_data_by_slug( string $slug ): array { + if ( '' === $slug ) { + return array( + 'slug' => '', + 'name' => '', + ); + } foreach ( $this->plugins_data as $plugin_slug => $plugin_data ) { if ( $slug === $plugin_data['TextDomain'] ) { return array( 'slug' => $plugin_data['TextDomain'], 'name' => $plugin_data['Name'], - 'path' => $src, ); } } return array( 'slug' => '', 'name' => '', - 'path' => $src, ); } + + /** + * Get all of the manually output scripts. + * + * Check all plugins hooked to wp_head or wp_footer to see if they are enqueuing scripts. + * Run all hooks using output buffering, then review content for any script handles that are enqueued. + * Use the HTML API to parse for script handle, then add that to the performance marks. + * + * For each script, return the plugin slug and name and the script path. + * + * @since n.e.x.t + * + * @return array> Array of script handles with plugin slug and name. + */ + private function get_manually_output_scripts(): array { + $scripts = array(); + $hooks = array( + 'wp_head', + 'wp_footer', + ); + foreach ( $hooks as $hook ) { + // Get all callbacks hooked on this hook and invoke them one at a time. + $callbacks = $GLOBALS['wp_filter'][ $hook ]; + foreach ( $callbacks as $priority => $sub_callbacks ) { + foreach ( $sub_callbacks as $callback ) { + // Capture the output HTML. + ob_start(); + call_user_func( $callback['function'], array() ); + $html = ob_get_clean(); + // Parse the HTML for any script handles. + if ( empty( $html ) ) { + continue; + } + $processor = new WP_HTML_Tag_Processor( $html ); + while ( $processor->next_tag() ) { + if ( 'SCRIPT' === $processor->get_tag() ) { + $src = $processor->get_attribute( 'src' ); + $plugin_slug = ''; + if ( ! empty( $src ) ) { + if ( is_array( $callback['function'] ) ) { + $class_name = $callback['function'][0]; // Class. + $method_name = $callback['function'][1]; // Method. + try { + $reflection_method = new ReflectionMethod( $class_name, $method_name ); + $file_path = $reflection_method->getFileName(); + $plugin_slug = $this->get_slug_from_path( $file_path ); + } catch ( ReflectionException $e ) { + continue; + } + } else { + $function_name = $callback['function']; + try { + $reflection_function = new ReflectionFunction( $function_name ); + $file_path = $reflection_function->getFileName(); + $plugin_slug = $this->get_slug_from_path( $file_path ); + } catch ( ReflectionException $e ) { + continue; + } + $plugin_data = $this->get_plugin_data_by_slug( $plugin_slug ); + $scripts[] = array( + 'path' => $src, + 'slug' => empty( $plugin_data['slug'] ) ? 'core' : $plugin_data['slug'], + 'name' => empty( $plugin_data['name'] ) ? 'Core' : $plugin_data['name'], + ); + } + } + } + } + } + } + } + return $scripts; + } + + /** + * Helper to get the plugin slug from a file path. + * + * @since n.e.x.t + * + * @param string|false $file_path The file path. + * @return string The plugin slug. + */ + private function get_slug_from_path( $file_path ): string { + if ( false === $file_path ) { + return ''; + } + $pattern = '#/(?:plugins|themes)/([^/]+)/#'; // Match anything after '/plugins/' or '/themes/' up to the next '/'. + if ( false !== preg_match( $pattern, $file_path, $matches ) ) { + return $matches[1]; + } + return ''; + } } diff --git a/plugins/performance-lab/includes/performance-marks/hooks.php b/plugins/performance-lab/includes/performance-marks/hooks.php index db72a7a7c9..fd623a99e6 100644 --- a/plugins/performance-lab/includes/performance-marks/hooks.php +++ b/plugins/performance-lab/includes/performance-marks/hooks.php @@ -15,4 +15,4 @@ * * @since n.e.x.t */ -add_action( 'wp_footer', array( perflab_performance_marks(), 'send_marks'), 999 ); +add_action( 'wp_footer', array( perflab_performance_marks(), 'send_marks' ), 999 ); diff --git a/plugins/performance-lab/includes/performance-marks/load.php b/plugins/performance-lab/includes/performance-marks/load.php index c3b392f7c8..fe98f53bce 100644 --- a/plugins/performance-lab/includes/performance-marks/load.php +++ b/plugins/performance-lab/includes/performance-marks/load.php @@ -12,6 +12,23 @@ require_once __DIR__ . '/hooks.php'; +/** + * Get the instance of the Perflab_Performance_Marks class. + * + * @since n.e.x.t + * + * @return Perflab_Performance_Marks The instance of the class. + */ +function perflab_performance_marks(): Perflab_Performance_Marks { + static $instance; + + if ( ! $instance ) { + $instance = new Perflab_Performance_Marks(); + } + + return $instance; +} + /** * Initialize the performance marks API. * From a6d4fd913dbf553bdbfa49f04ffae2bd4a2398d2 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 1 Nov 2024 12:40:26 -0600 Subject: [PATCH 8/9] refine attribution marks --- .../performance-marks/class-perflab-performance-marks.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php index 9ecf6fdbcf..8c725525b1 100644 --- a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php +++ b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php @@ -102,7 +102,7 @@ public function send_marks(): void { foreach ( $manually_output_scripts as $script ) { $this->add_mark( - 'script_output::' . $script['slug'], + 'attribution::plugin_output::' . $script['slug'], array( 'path' => $script['path'], 'slug' => $script['slug'], @@ -119,7 +119,7 @@ public function send_marks(): void { // Gather the plugin slug, name at relative path. $plugin_data = $this->get_plugin_data_from_src( $src ); perflab_performance_marks()->add_mark( - 'script_enqueue::' . $handle, + 'attribution::plugin_enqueue::' . $handle, array( 'path' => $plugin_data['path'], 'slug' => $plugin_data['slug'], @@ -161,7 +161,7 @@ private function get_plugin_data_from_src( string $src ): array { if ( str_starts_with( $src, '/wp-includes/' ) ) { return array( 'slug' => 'core', - 'name' => 'Core', + 'name' => 'WordPress Core', 'path' => $src, ); } @@ -269,7 +269,7 @@ private function get_manually_output_scripts(): array { $scripts[] = array( 'path' => $src, 'slug' => empty( $plugin_data['slug'] ) ? 'core' : $plugin_data['slug'], - 'name' => empty( $plugin_data['name'] ) ? 'Core' : $plugin_data['name'], + 'name' => empty( $plugin_data['name'] ) ? 'WordPressCore' : $plugin_data['name'], ); } } From 3e5b038499b3d40df0d616577b41607983b51c09 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 1 Nov 2024 13:09:32 -0600 Subject: [PATCH 9/9] Add theme enqueue support, improve attributions --- .../class-perflab-performance-marks.php | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php index 8c725525b1..e819e423f1 100644 --- a/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php +++ b/plugins/performance-lab/includes/performance-marks/class-perflab-performance-marks.php @@ -116,14 +116,17 @@ public function send_marks(): void { if ( false === $src ) { continue; } - // Gather the plugin slug, name at relative path. - $plugin_data = $this->get_plugin_data_from_src( $src ); + // Gather the slug, name at relative path. + $attribution_data = $this->get_script_data_from_src( $src ); + + // If the slug is core, the is a core:enqueue, otherwise if the src contains 'themes' this is a theme:enqueue, otherwise it is a plugin:enqueue. + $mark_slug = 'attribution::' . ( 'core' === $attribution_data['slug'] ? 'core' : ( str_contains( $src, 'themes' ) ? 'theme' : 'plugin' ) ) . '_enqueue::' . $handle; perflab_performance_marks()->add_mark( - 'attribution::plugin_enqueue::' . $handle, + $mark_slug, array( - 'path' => $plugin_data['path'], - 'slug' => $plugin_data['slug'], - 'name' => $plugin_data['name'], + 'path' => $attribution_data['path'], + 'slug' => $attribution_data['slug'], + 'name' => $attribution_data['name'], ) ); } @@ -153,7 +156,7 @@ public function send_marks(): void { * @param string $src The script path. * @return array The plugin slug, name and path. */ - private function get_plugin_data_from_src( string $src ): array { + private function get_script_data_from_src( string $src ): array { // Get just the local path for the src (removing the local domain). $src = str_replace( get_site_url(), '', $src ); @@ -170,11 +173,19 @@ private function get_plugin_data_from_src( string $src ): array { $slugs = explode( '/', $src ); $slug = $slugs[3]; - $plugin_data = $this->get_plugin_data_by_slug( $slug ); + // If the src contains 'plugins', extract the plugin data. + if ( str_contains( $src, 'themes' ) ) { + return array( + 'slug' => $slug, + 'name' => wp_get_theme()->get( 'Name' ), + 'path' => $src, + ); + } + $script_data = $this->get_plugin_data_by_slug( $slug ); return array( - 'slug' => $plugin_data['slug'], - 'name' => $plugin_data['name'], + 'slug' => $script_data['slug'], + 'name' => $script_data['name'], 'path' => $src, ); }