Completed
Push — branch-6.8-built ( ab1229...17d608 )
by Jeremy
15:49 queued 07:50
created

Jetpack_Gutenberg::get_asset_version()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Handles server-side registration and use of all blocks available in Jetpack for the block editor, aka Gutenberg.
4
 * Works in tandem with client-side block registration via `_inc/blocks/block-manifest.json`
5
 *
6
 * @package Jetpack
7
 */
8
9
/**
10
 * Helper function to register a Jetpack Gutenberg block
11
 *
12
 * @param string $type Slug of the block. Will be prefixed with jetpack/.
13
 * @param array  $args Arguments that are passed into the register_block_type.
14
 * @param array  $avalibility Arguments that tells us what kind of avalibility the block has
0 ignored issues
show
Bug introduced by
There is no parameter named $avalibility. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
15
 *
16
 * @see register_block_type
17
 *
18
 * @since 6.7.0
19
 *
20
 * @return void
21
 */
22
function jetpack_register_block( $type, $args = array(), $availability = array( 'available' => true ) ) {
23
	$type = sanitize_title_with_dashes( $type );
24
	Jetpack_Gutenberg::add_block( $type, $args, $availability );
25
}
26
27
/**
28
 * General Gutenberg editor specific functionality
29
 */
30
class Jetpack_Gutenberg {
31
32
	/**
33
	 * Array of blocks we will be registering.
34
	 *
35
	 * @var array $blocks Array of blocks we will be registering.
36
	 */
37
	private static $jetpack_blocks = array();
38
	private static $blocks_index = array();
39
	/**
40
	 * Add a block to the list of blocks to be registered.
41
	 *
42
	 * @param string $type Slug of the block.
43
	 * @param array  $args Arguments that are passed into the register_block_type.
44
	 */
45
	public static function add_block( $type, $args, $availability ) {
46
		self::$jetpack_blocks[ $type ] = array( 'args' => $args, 'availability' => $availability );
47
	}
48
49
	/**
50
	 * Register all Jetpack blocks available.
51
	 *
52
	 * @return void|WP_Block_Type|false The registered block type on success, or false on failure.
53
	 */
54
	public static function load_blocks() {
55
		if ( ! self::is_gutenberg_available() ) {
56
			return;
57
		}
58
59
		if ( ! self::should_load_blocks() ) {
60
			return;
61
		}
62
63
		/**
64
		 * Filter the list of blocks that are available through jetpack.
65
		 *
66
		 * This filter is populated by Jetpack_Gutenberg::jetpack_set_available_blocks
67
		 *
68
		 * @since 6.8.0
69
		 *
70
		 * @param array
71
		 */
72
		self::$blocks_index = apply_filters( 'jetpack_set_available_blocks', array() );
73
74
		foreach ( self::$jetpack_blocks as $type => $args ) {
75
			if ( 'publicize' === $type ) {
76
				// publicize is not actually a block, it's a gutenberg plugin.
77
				// We will handle it's registration on the client-side.
78
				continue;
79
			}
80
			if ( isset( $args['availability']['available'] ) && $args['availability']['available'] && in_array( $type, self::$blocks_index ) ) {
81
				register_block_type( 'jetpack/' . $type, $args['args'] );
82
			}
83
		}
84
	}
85
86
	/**
87
	 * Checks for a given .json file in the `_inc/blocks` folder.
88
	 *
89
	 * @param $preset The name of the .json file to look for.
90
	 *
91
	 * @return bool True if the file is found.
92
	 */
93
	public static function preset_exists( $preset ) {
94
		return file_exists( JETPACK__PLUGIN_DIR . '/_inc/blocks/' . $preset . '.json' );
95
	}
96
97
	/**
98
	 * Decodes JSON loaded from a preset file in `_inc/blocks`
99
	 *
100
	 * @param $preset The name of the .json file to load.
101
	 *
102
	 * @return mixed Returns an object if the file is present, or false if a valid .json file is not present.
103
	 */
104
	public static function get_preset( $preset ) {
105
		return json_decode( file_get_contents(  JETPACK__PLUGIN_DIR . '/_inc/blocks/' . $preset . '.json' ) );
106
	}
107
108
	/**
109
	 * Filters the results of `apply_filter( 'jetpack_set_available_blocks', array() )`
110
	 * using the merged contents of `_inc/blocks/blocks-manifest.json` ( $preset_blocks )
111
	 * and self::$jetpack_blocks ( $internal_blocks )
112
	 *
113
	 * @param $blocks The default list.
114
	 *
115
	 * @return array A list of blocks: eg [ 'publicize', 'markdown' ]
116
	 */
117
	public static function jetpack_set_available_blocks( $blocks ) {
118
		$preset_blocks_manifest =  self::preset_exists( 'block-manifest' ) ? self::get_preset( 'block-manifest' ) : (object) array( 'blocks' => $blocks );
119
		$preset_blocks = isset( $preset_blocks_manifest->blocks ) ? (array) $preset_blocks_manifest->blocks : array() ;
120
		$internal_blocks = array_keys( self::$jetpack_blocks );
121
122
		if ( Jetpack_Constants::is_true( 'JETPACK_BETA_BLOCKS' ) ) {
123
			$beta_blocks = isset( $preset_blocks_manifest->betaBlocks ) ? (array) $preset_blocks_manifest->betaBlocks : array();
124
			return array_unique( array_merge( $preset_blocks, $beta_blocks, $internal_blocks ) );
125
		}
126
127
		return array_unique( array_merge( $preset_blocks, $internal_blocks ) );
128
	}
129
130
	/**
131
	 * @return array A list of block-availability information, eg: [ "publicize" => ["available" => true ], "markdown" => [ "available" => false, "unavailable_reason" => 'missing_module' ] ]
132
	 */
133
	public static function get_block_availability() {
134
135
		if ( ! self::should_load_blocks() ) {
136
			return array();
137
		}
138
139
		$blocks_availability = array(); // default
140
141
		foreach ( self::$jetpack_blocks as $type => $args ) {
142
			if ( ! in_array( $type,  self::$blocks_index ) ) {
143
				// Jetpack shouldn't expose blocks that are not in the manifest.
144
				continue;
145
			}
146
			$availability = $args['availability'];
147
			$available = array(
148
				'available' => ( isset( $availability['available'] ) ? (bool) $availability['available'] : true ),
149
			);
150
			$unavailability_reason = array();
151
			if ( ! $available['available'] ) {
152
				$unavailability_reason = array(
153
					'unavailable_reason' => ( isset( $availability['unavailable_reason'] ) ? $availability['unavailable_reason'] : 'unknown' )
154
				);
155
			}
156
			$blocks_availability[ $type ] = array_merge( $available, $unavailability_reason );
157
		}
158
159
		foreach ( self::$blocks_index as $block ) {
160
			if ( ! isset( $blocks_availability[ $block ] ) ) {
161
				$blocks_availability[ $block ] = array( 'available' => false, 'unavailable_reason' => 'missing_module' );
162
			}
163
		}
164
165
		return $blocks_availability;
166
	}
167
168
	/**
169
	 * Check if Gutenberg editor is available
170
	 *
171
	 * @since 6.7.0
172
	 *
173
	 * @return bool
174
	 */
175
	public static function is_gutenberg_available() {
176
		return function_exists( 'register_block_type' );
177
	}
178
179
	/**
180
	 * Check whether conditions indicate Gutenberg blocks should be loaded
181
	 *
182
	 * Loading blocks is enabled by default and may be disabled via filter:
183
	 *   add_filter( 'jetpack_gutenberg', '__return_false' );
184
	 *
185
	 * @since 6.7.0
186
	 *
187
	 * @return bool
188
	 */
189
	public static function should_load_blocks() {
190
		if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
191
			return false;
192
		}
193
194
		/**
195
		 * Filter to disable Gutenberg blocks
196
		 *
197
		 * @since 6.5.0
198
		 *
199
		 * @param bool true Whether to load Gutenberg blocks
200
		 */
201
		return (bool) apply_filters( 'jetpack_gutenberg', true );
202
	}
203
204
	/**
205
	 * Only enqueue block assets when needed.
206
	 *
207
	 * @param string $type slug of the block.
208
	 * @param array $script_dependencies An array of view-side Javascript dependencies to be enqueued.
209
	 *
210
	 * @return void
211
	 */
212
	public static function load_assets_as_required( $type, $script_dependencies = array() ) {
213
		if ( is_admin() ) {
214
			// A block's view assets will not be required in wp-admin.
215
			return;
216
		}
217
218
		$type = sanitize_title_with_dashes( $type );
219
		// Enqueue styles.
220
		$style_relative_path = '_inc/blocks/' . $type . '/view' . ( is_rtl() ? '.rtl' : '' ) . '.css';
221 View Code Duplication
		if ( self::block_has_asset( $style_relative_path ) ) {
222
			$style_version = self::get_asset_version( $style_relative_path );
223
			$view_style    = plugins_url( $style_relative_path, JETPACK__PLUGIN_FILE );
224
			wp_enqueue_style( 'jetpack-block-' . $type, $view_style, array(), $style_version );
225
		}
226
227
		// Enqueue script.
228
		$script_relative_path = '_inc/blocks/' . $type . '/view.js';
229 View Code Duplication
		if ( self::block_has_asset( $script_relative_path ) ) {
230
			$script_version = self::get_asset_version( $script_relative_path );
231
			$view_script    = plugins_url( $script_relative_path, JETPACK__PLUGIN_FILE );
232
			wp_enqueue_script( 'jetpack-block-' . $type, $view_script, $script_dependencies, $script_version, false );
233
		}
234
235
		wp_localize_script(
236
			'jetpack-block-' . $type,
237
			'Jetpack_Block_Assets_Base_Url',
238
			plugins_url( '_inc/blocks/', JETPACK__PLUGIN_FILE )
239
		);
240
	}
241
242
	/**
243
	 * Check if an asset exists for a block.
244
	 *
245
	 * @param string $file Path of the file we are looking for.
246
	 *
247
	 * @return bool $block_has_asset Does the file exist.
248
	 */
249
	public static function block_has_asset( $file ) {
250
		return file_exists( JETPACK__PLUGIN_DIR . $file );
251
	}
252
253
	/**
254
	 * Get the version number to use when loading the file. Allows us to bypass cache when developing.
255
	 *
256
	 * @param string $file Path of the file we are looking for.
257
	 *
258
	 * @return string $script_version Version number.
259
	 */
260
	public static function get_asset_version( $file ) {
261
		return Jetpack::is_development_version() && self::block_has_asset( $file )
262
			? filemtime( JETPACK__PLUGIN_DIR . $file )
263
			: JETPACK__VERSION;
264
	}
265
266
	/**
267
	 * Load Gutenberg editor assets
268
	 *
269
	 * @since 6.7.0
270
	 *
271
	 * @return void
272
	 */
273
	public static function enqueue_block_editor_assets() {
274
		if ( ! self::should_load_blocks() ) {
275
			return;
276
		}
277
278
		$rtl = is_rtl() ? '.rtl' : '';
279
		$beta = Jetpack_Constants::is_true('JETPACK_BETA_BLOCKS' ) ? '-beta' : '';
280
281
		$editor_script = plugins_url( "_inc/blocks/editor{$beta}.js", JETPACK__PLUGIN_FILE );
282
		$editor_style  = plugins_url( "_inc/blocks/editor{$beta}{$rtl}.css", JETPACK__PLUGIN_FILE );
283
284
		$version       = Jetpack::is_development_version() && file_exists( JETPACK__PLUGIN_DIR . '_inc/blocks/editor.js' )
285
			? filemtime( JETPACK__PLUGIN_DIR . '_inc/blocks/editor.js' )
286
			: JETPACK__VERSION;
287
288
		wp_enqueue_script(
289
			'jetpack-blocks-editor',
290
			$editor_script,
291
			array(
292
				'lodash',
293
				'wp-api-fetch',
294
				'wp-blocks',
295
				'wp-components',
296
				'wp-compose',
297
				'wp-data',
298
				'wp-date',
299
				'wp-edit-post',
300
				'wp-editor',
301
				'wp-element',
302
				'wp-hooks',
303
				'wp-i18n',
304
				'wp-keycodes',
305
				'wp-plugins',
306
				'wp-token-list',
307
				'wp-url',
308
			),
309
			$version,
310
			false
311
		);
312
313
		wp_localize_script(
314
			'jetpack-blocks-editor',
315
			'Jetpack_Block_Assets_Base_Url',
316
			plugins_url( '_inc/blocks/', JETPACK__PLUGIN_FILE )
317
		);
318
319
		wp_localize_script(
320
			'jetpack-blocks-editor',
321
			'Jetpack_Editor_Initial_State',
322
			array(
323
				'available_blocks' => self::get_block_availability(),
324
				'jetpack' => array( 'is_active' => Jetpack::is_active() ),
325
			)
326
		);
327
328
		Jetpack::setup_wp_i18n_locale_data();
329
330
		wp_enqueue_style( 'jetpack-blocks-editor', $editor_style, array(), $version );
331
332
		// The social-logos styles are used for Publicize service icons
333
		// TODO: Remove when we ship the icons with the Gutenberg blocks build
334
		wp_enqueue_style( 'social-logos' );
335
	}
336
}
337