Api.php
7.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<?php
namespace Automattic\WooCommerce\Blocks\Assets;
use Automattic\WooCommerce\Blocks\Domain\Package;
use Exception;
/**
* The Api class provides an interface to various asset registration helpers.
*
* Contains asset api methods
*
* @since 2.5.0
*/
class Api {
/**
* Stores inline scripts already enqueued.
*
* @var array
*/
private $inline_scripts = [];
/**
* Reference to the Package instance
*
* @var Package
*/
private $package;
/**
* Constructor for class
*
* @param Package $package An instance of Package.
*/
public function __construct( Package $package ) {
$this->package = $package;
}
/**
* Get the file modified time as a cache buster if we're in dev mode.
*
* @param string $file Local path to the file (relative to the plugin
* directory).
* @return string The cache buster value to use for the given file.
*/
protected function get_file_version( $file ) {
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && file_exists( $this->package->get_path() . $file ) ) {
return filemtime( $this->package->get_path( trim( $file, '/' ) ) );
}
return $this->package->get_version();
}
/**
* Retrieve the url to an asset for this plugin.
*
* @param string $relative_path An optional relative path appended to the
* returned url.
*
* @return string
*/
protected function get_asset_url( $relative_path = '' ) {
return $this->package->get_url( $relative_path );
}
/**
* Get the path to a block's metadata
*
* @param string $block_name The block to get metadata for.
* @param string $path Optional. The path to the metadata file inside the 'build' folder.
*
* @return string|boolean False if metadata file is not found for the block.
*/
public function get_block_metadata_path( $block_name, $path = '' ) {
$path_to_metadata_from_plugin_root = $this->package->get_path( 'build/' . $path . $block_name . '/block.json' );
if ( ! file_exists( $path_to_metadata_from_plugin_root ) ) {
return false;
}
return $path_to_metadata_from_plugin_root;
}
/**
* Get src, version and dependencies given a script relative src.
*
* @param string $relative_src Relative src to the script.
* @param array $dependencies Optional. An array of registered script handles this script depends on. Default empty array.
*
* @return array src, version and dependencies of the script.
*/
public function get_script_data( $relative_src, $dependencies = [] ) {
$src = '';
$version = '1';
if ( $relative_src ) {
$src = $this->get_asset_url( $relative_src );
$asset_path = $this->package->get_path(
str_replace( '.js', '.asset.php', $relative_src )
);
if ( file_exists( $asset_path ) ) {
$asset = require $asset_path;
$dependencies = isset( $asset['dependencies'] ) ? array_merge( $asset['dependencies'], $dependencies ) : $dependencies;
$version = ! empty( $asset['version'] ) ? $asset['version'] : $this->get_file_version( $relative_src );
} else {
$version = $this->get_file_version( $relative_src );
}
}
return array(
'src' => $src,
'version' => $version,
'dependencies' => $dependencies,
);
}
/**
* Registers a script according to `wp_register_script`, adding the correct prefix, and additionally loading translations.
*
* When creating script assets, the following rules should be followed:
* 1. All asset handles should have a `wc-` prefix.
* 2. If the asset handle is for a Block (in editor context) use the `-block` suffix.
* 3. If the asset handle is for a Block (in frontend context) use the `-block-frontend` suffix.
* 4. If the asset is for any other script being consumed or enqueued by the blocks plugin, use the `wc-blocks-` prefix.
*
* @since 2.5.0
* @throws Exception If the registered script has a dependency on itself.
*
* @param string $handle Unique name of the script.
* @param string $relative_src Relative url for the script to the path from plugin root.
* @param array $dependencies Optional. An array of registered script handles this script depends on. Default empty array.
* @param bool $has_i18n Optional. Whether to add a script translation call to this file. Default: true.
*/
public function register_script( $handle, $relative_src, $dependencies = [], $has_i18n = true ) {
$script_data = $this->get_script_data( $relative_src, $dependencies );
if ( in_array( $handle, $script_data['dependencies'], true ) ) {
if ( $this->package->feature()->is_development_environment() ) {
$dependencies = array_diff( $script_data['dependencies'], [ $handle ] );
add_action(
'admin_notices',
function() use ( $handle ) {
echo '<div class="error"><p>';
/* translators: %s file handle name. */
printf( esc_html__( 'Script with handle %s had a dependency on itself which has been removed. This is an indicator that your JS code has a circular dependency that can cause bugs.', 'woocommerce' ), esc_html( $handle ) );
echo '</p></div>';
}
);
} else {
throw new Exception( sprintf( 'Script with handle %s had a dependency on itself. This is an indicator that your JS code has a circular dependency that can cause bugs.', $handle ) );
}
}
/**
* Filters the list of script dependencies.
*
* @param array $dependencies The list of script dependencies.
* @param string $handle The script's handle.
* @return array
*/
$script_dependencies = apply_filters( 'woocommerce_blocks_register_script_dependencies', $script_data['dependencies'], $handle );
wp_register_script( $handle, $script_data['src'], $script_dependencies, $script_data['version'], true );
if ( $has_i18n && function_exists( 'wp_set_script_translations' ) ) {
wp_set_script_translations( $handle, 'woocommerce', $this->package->get_path( 'languages' ) );
}
}
/**
* Registers a style according to `wp_register_style`.
*
* @since 2.5.0
* @since 2.6.0 Change src to be relative source.
*
* @param string $handle Name of the stylesheet. Should be unique.
* @param string $relative_src Relative source of the stylesheet to the plugin path.
* @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.
* @param string $media Optional. The media for which this stylesheet has been defined. Default 'all'. Accepts media types like
* 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
*/
public function register_style( $handle, $relative_src, $deps = [], $media = 'all' ) {
$filename = str_replace( plugins_url( '/', __DIR__ ), '', $relative_src );
$src = $this->get_asset_url( $relative_src );
$ver = $this->get_file_version( $filename );
wp_register_style( $handle, $src, $deps, $ver, $media );
}
/**
* Returns the appropriate asset path for loading either legacy builds or
* current builds.
*
* @param string $filename Filename for asset path (without extension).
* @param string $type File type (.css or .js).
*
* @return string The generated path.
*/
public function get_block_asset_build_path( $filename, $type = 'js' ) {
global $wp_version;
$suffix = version_compare( $wp_version, '5.3', '>=' )
? ''
: '-legacy';
return "build/$filename$suffix.$type";
}
/**
* Adds an inline script, once.
*
* @param string $handle Script handle.
* @param string $script Script contents.
*/
public function add_inline_script( $handle, $script ) {
if ( ! empty( $this->inline_scripts[ $handle ] ) && in_array( $script, $this->inline_scripts[ $handle ], true ) ) {
return;
}
wp_add_inline_script( $handle, $script );
if ( isset( $this->inline_scripts[ $handle ] ) ) {
$this->inline_scripts[ $handle ][] = $script;
} else {
$this->inline_scripts[ $handle ] = array( $script );
}
}
}