@@ -18,6 +18,20 @@ class Api {
1818 */
1919 private $ inline_scripts = [];
2020
21+ /**
22+ * Determines if caching is enabled for script data.
23+ *
24+ * @var boolean
25+ */
26+ private $ disable_cache = false ;
27+
28+ /**
29+ * Stores loaded script data for the current request
30+ *
31+ * @var array|null
32+ */
33+ private $ script_data = null ;
34+
2135 /**
2236 * Reference to the Package instance
2337 *
@@ -31,7 +45,9 @@ class Api {
3145 * @param Package $package An instance of Package.
3246 */
3347 public function __construct ( Package $ package ) {
34- $ this ->package = $ package ;
48+ $ this ->package = $ package ;
49+ $ this ->disable_cache = ( defined ( 'SCRIPT_DEBUG ' ) && SCRIPT_DEBUG ) || ! $ this ->package ->feature ()->is_production_environment ();
50+ add_action ( 'shutdown ' , array ( $ this , 'update_script_data_cache ' ), 20 );
3551 }
3652
3753 /**
@@ -76,6 +92,44 @@ public function get_block_metadata_path( $block_name, $path = '' ) {
7692 return $ path_to_metadata_from_plugin_root ;
7793 }
7894
95+ /**
96+ * Initialize and load cached script data from the transient cache.
97+ *
98+ * @return array
99+ */
100+ private function get_cached_script_data () {
101+ if ( $ this ->disable_cache ) {
102+ return [];
103+ }
104+
105+ $ transient_value = json_decode ( (string ) get_transient ( 'woocommerce_blocks_asset_api_script_data ' ), true );
106+
107+ if ( empty ( $ transient_value ) || empty ( $ transient_value ['script_data ' ] ) || empty ( $ transient_value ['version ' ] ) || $ transient_value ['version ' ] !== $ this ->package ->get_version () ) {
108+ return [];
109+ }
110+
111+ return (array ) ( $ transient_value ['script_data ' ] ?? [] );
112+ }
113+
114+ /**
115+ * Store all cached script data in the transient cache.
116+ */
117+ public function update_script_data_cache () {
118+ if ( is_null ( $ this ->script_data ) || $ this ->disable_cache ) {
119+ return ;
120+ }
121+ set_transient (
122+ 'woocommerce_blocks_asset_api_script_data ' ,
123+ wp_json_encode (
124+ array (
125+ 'script_data ' => $ this ->script_data ,
126+ 'version ' => $ this ->package ->get_version (),
127+ )
128+ ),
129+ DAY_IN_SECONDS * 30
130+ );
131+ }
132+
79133 /**
80134 * Get src, version and dependencies given a script relative src.
81135 *
@@ -85,31 +139,37 @@ public function get_block_metadata_path( $block_name, $path = '' ) {
85139 * @return array src, version and dependencies of the script.
86140 */
87141 public function get_script_data ( $ relative_src , $ dependencies = [] ) {
88- $ src = '' ;
89- $ version = '1 ' ;
90-
91- if ( $ relative_src ) {
92- $ src = $ this ->get_asset_url ( $ relative_src );
93- $ asset_path = $ this ->package ->get_path (
94- str_replace ( '.js ' , '.asset.php ' , $ relative_src )
142+ if ( ! $ relative_src ) {
143+ return array (
144+ 'src ' => '' ,
145+ 'version ' => '1 ' ,
146+ 'dependencies ' => $ dependencies ,
95147 );
148+ }
96149
97- if ( file_exists ( $ asset_path ) ) {
98- // The following require is safe because we are checking if the file exists and it is not a user input.
99- // nosemgrep audit.php.lang.security.file.inclusion-arg.
100- $ asset = require $ asset_path ;
101- $ dependencies = isset ( $ asset ['dependencies ' ] ) ? array_merge ( $ asset ['dependencies ' ], $ dependencies ) : $ dependencies ;
102- $ version = ! empty ( $ asset ['version ' ] ) ? $ asset ['version ' ] : $ this ->get_file_version ( $ relative_src );
103- } else {
104- $ version = $ this ->get_file_version ( $ relative_src );
105- }
150+ if ( is_null ( $ this ->script_data ) ) {
151+ $ this ->script_data = $ this ->get_cached_script_data ();
106152 }
107153
108- return array (
109- 'src ' => $ src ,
110- 'version ' => $ version ,
111- 'dependencies ' => $ dependencies ,
112- );
154+ if ( empty ( $ this ->script_data [ $ relative_src ] ) ) {
155+ $ asset_path = $ this ->package ->get_path ( str_replace ( '.js ' , '.asset.php ' , $ relative_src ) );
156+ // The following require is safe because we are checking if the file exists and it is not a user input.
157+ // nosemgrep audit.php.lang.security.file.inclusion-arg.
158+ $ asset = file_exists ( $ asset_path ) ? require $ asset_path : [];
159+
160+ $ this ->script_data [ $ relative_src ] = array (
161+ 'src ' => $ this ->get_asset_url ( $ relative_src ),
162+ 'version ' => ! empty ( $ asset ['version ' ] ) ? $ asset ['version ' ] : $ this ->get_file_version ( $ relative_src ),
163+ 'dependencies ' => ! empty ( $ asset ['dependencies ' ] ) ? $ asset ['dependencies ' ] : [],
164+ );
165+ }
166+
167+ // Return asset details as well as the requested dependencies array.
168+ return [
169+ 'src ' => $ this ->script_data [ $ relative_src ]['src ' ],
170+ 'version ' => $ this ->script_data [ $ relative_src ]['version ' ],
171+ 'dependencies ' => array_merge ( $ this ->script_data [ $ relative_src ]['dependencies ' ], $ dependencies ),
172+ ];
113173 }
114174
115175 /**
0 commit comments