PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 All 507 releases
jetpack / jetpack_vendor / automattic / jetpack-stats-admin / src / class-odyssey-assets.php

class-odyssey-assets.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-beta, at jetpack_vendor/automattic/jetpack-stats-admin/src/class-odyssey-assets.php

156 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Stats Assets
4 *
5 * @package automattic/jetpack-stats-admin
6 */
7
8 namespace Automattic\Jetpack\Stats_Admin;
9
10 use Automattic\Jetpack\Assets;
11
12 /**
13 * Class Odyssey_Config_Data
14 *
15 * @package automattic/jetpack-stats-admin
16 */
17 class Odyssey_Assets {
18 // This is a fixed list @see https://github.com/Automattic/wp-calypso/pull/71442/
19 const JS_DEPENDENCIES = array( 'lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-primitives', 'wp-url', 'wp-warning', 'moment' );
20 /**
21 * Odyssey's UI is built on @wordpress/components and runs against the page's own
22 * `wp.components` (externalized, see JS_DEPENDENCIES above), so it needs that package's
23 * matching stylesheet. Declare it rather than relying on some other admin feature loading it
24 * as a side effect — WP 7.0's command palette happens to enqueue it globally today, but that's
25 * an implementation detail of the palette, not a contract. Declaring it also fixes cascade
26 * order: WP emits dependencies first, so Odyssey's own overrides of these classes reliably win.
27 */
28 const CSS_DEPENDENCIES = array( 'wp-components' );
29 // Sometimes custom scripts would strip the `ver` query params, so we need to make sure it doesn't by adding a custom version param `osv` here.
30 const ODYSSEY_CDN_URL = 'https://widgets.wp.com/odyssey-stats/%s/%s?minify=false&osv=%s';
31
32 /**
33 * We bump the asset version when the Jetpack back end is not compatible anymore.
34 */
35 const ODYSSEY_STATS_VERSION = 'v1';
36 const ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY = 'odyssey_stats_admin_asset_cache_buster';
37
38 /**
39 * Load the admin scripts.
40 *
41 * @param string $asset_handle The handle of the asset.
42 * @param string $asset_name The name of the asset.
43 * @param array $options The options.
44 */
45 public function load_admin_scripts( $asset_handle, $asset_name, $options = array() ) {
46 $default_options = array(
47 'config_data' => ( new Odyssey_Config_Data() )->get_data(),
48 'config_variable_name' => 'configData',
49 'enqueue_css' => true,
50 );
51 $options = wp_parse_args( $options, $default_options );
52 if ( file_exists( __DIR__ . "/../dist/{$asset_name}.js" ) ) {
53 // Load local assets for the convinience of development.
54 Assets::register_script(
55 $asset_handle,
56 "../dist/{$asset_name}.js",
57 __FILE__,
58 array(
59 'in_footer' => true,
60 'textdomain' => 'jetpack-stats-admin',
61 'css_dependencies' => self::CSS_DEPENDENCIES,
62 )
63 );
64 Assets::enqueue_script( $asset_handle );
65 } else {
66 // In production, we load the assets from our CDN.
67 wp_register_script(
68 $asset_handle,
69 sprintf( self::ODYSSEY_CDN_URL, self::ODYSSEY_STATS_VERSION, "{$asset_name}.js", $this->get_cdn_asset_cache_buster() ),
70 self::JS_DEPENDENCIES,
71 $this->get_cdn_asset_cache_buster(),
72 true
73 );
74 wp_enqueue_script( $asset_handle );
75
76 // Enqueue CSS if needed.
77 if ( $options['enqueue_css'] ) {
78 $css_url = $asset_name . ( is_rtl() ? '.rtl' : '' ) . '.css';
79 $css_handle = $asset_handle . '-style';
80 wp_register_style(
81 $css_handle,
82 sprintf( self::ODYSSEY_CDN_URL, self::ODYSSEY_STATS_VERSION, $css_url, $this->get_cdn_asset_cache_buster() ),
83 self::CSS_DEPENDENCIES,
84 $this->get_cdn_asset_cache_buster()
85 );
86 wp_enqueue_style( $css_handle );
87 }
88 }
89
90 wp_add_inline_script(
91 $asset_handle,
92 ( new Odyssey_Config_Data() )->get_js_config_data( $options['config_variable_name'], $options['config_data'] ),
93 'before'
94 );
95 }
96
97 /**
98 * Returns cache buster string for assets.
99 * Development mode doesn't need this, as it's handled by `Assets` class.
100 *
101 * @return string
102 */
103 protected function get_cdn_asset_cache_buster() {
104 $now_in_ms = floor( microtime( true ) * 1000 );
105 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
106 if ( isset( $_GET['force_refresh'] ) ) {
107 update_option( self::ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY, $this->get_cache_buster_option_value( $now_in_ms ), false );
108 }
109
110 // Use cached cache buster in production.
111 $remote_asset_version = get_option( self::ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY );
112
113 if ( ! empty( $remote_asset_version ) ) {
114 $remote_asset_version = json_decode( $remote_asset_version, true );
115 // If cache buster is cached and not expired (valid in 15 min), return it.
116 if ( ! empty( $remote_asset_version['cache_buster'] ) && $remote_asset_version['cached_at'] > $now_in_ms - MINUTE_IN_SECONDS * 1000 * 15 ) {
117 return $remote_asset_version['cache_buster'];
118 }
119 }
120
121 // If no cached cache buster, we fetch it from CDN and set to transient.
122 $response = wp_remote_get( sprintf( self::ODYSSEY_CDN_URL, self::ODYSSEY_STATS_VERSION, 'build_meta.json', $now_in_ms ), array( 'timeout' => 5 ) );
123
124 if ( is_wp_error( $response ) ) {
125 // fallback to current timestamp.
126 return (string) $now_in_ms;
127 }
128
129 $build_meta = json_decode( wp_remote_retrieve_body( $response ), true );
130 if ( ! empty( $build_meta['cache_buster'] ) ) {
131 // Cache the cache buster for 15 mins.
132 update_option( self::ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY, $this->get_cache_buster_option_value( $build_meta['cache_buster'] ), false );
133 return $build_meta['cache_buster'];
134 }
135
136 // fallback to current timestamp.
137 return (string) $now_in_ms;
138 }
139
140 /**
141 * Get the cache buster option value.
142 *
143 * @param string|int|float $cache_buster The cache buster.
144 * @return string|false
145 */
146 protected function get_cache_buster_option_value( $cache_buster ) {
147 return wp_json_encode(
148 array(
149 'cache_buster' => (string) $cache_buster,
150 'cached_at' => floor( microtime( true ) * 1000 ), // milliseconds.
151 ),
152 JSON_UNESCAPED_SLASHES
153 );
154 }
155 }
156