Completed
Push — update/disconnected-jetpack-da... ( f195d5...ab976f )
by Jeremy
07:42
created

Jetpack_Gutenberg::get_block_availability()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
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 `index.json`
5
 *
6
 * @package Jetpack
7
 */
8
9
/**
10
 * Helper function to register a Jetpack Gutenberg block
11
 *
12
 * @param string $slug Slug of the block
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( $slug, $args = array(), $availability = array( 'available' => true ) ) {
23
	Jetpack_Gutenberg::register( $slug, $args, $availability );
24
}
25
26
/**
27
 * Helper function to register a Jetpack Gutenberg plugin
28
 *
29
 * @param string $slug Slug of the plugin.
30
 * @param array  $avalibility Arguments that tells us what kind of avalibility the plugin 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...
31
 *
32
 * @see register_block_type
33
 *
34
 * @since 6.9.0
35
 *
36
 * @return void
37
 */
38
function jetpack_register_plugin( $slug, $availability = array( 'available' => true ) ) {
39
	Jetpack_Gutenberg::register( $slug, array(), $availability );
40
}
41
42
/**
43
 * General Gutenberg editor specific functionality
44
 */
45
class Jetpack_Gutenberg {
46
47
	// BLOCKS
48
	private static $default_blocks = array(
49
		'map',
50
		'markdown',
51
		'simple-payments',
52
		'related-posts',
53
		'contact-form',
54
		'field-text',
55
		'field-name',
56
		'field-email',
57
		'field-url',
58
		'field-date',
59
		'field-telephone',
60
		'field-textarea',
61
		'field-checkbox',
62
		'field-checkbox-multiple',
63
		'field-radio',
64
		'field-select'
65
	);
66
67
	/**
68
	 * @var array Array of blocks information.
69
	 *
70
	 * For each block we have information about the availability for the current user
71
	 */
72
	private static $blocks = array();
73
74
	private static $availability = array();
75
76
	// PLUGINS
77
	private static $default_plugins = array(
78
		'publicize',
79
	);
80
	/**
81
	 * @var array Array of plugins information.
82
	 *
83
	 * For each block we have information about the availability for the current user
84
	 */
85
	private static $plugins = array();
86
87
	/**
88
	 * @var array Array of extensions we will be registering.
89
	 */
90
	private static $registered = array();
91
92
	/**
93
	 * Add a block to the list of blocks to be registered.
94
	 *
95
	 * @param string $slug Slug of the block.
96
	 * @param array  $args Arguments that are passed into the register_block_type.
97
	 * @param array $availability array containing if a block is available and the reason when it is not.
98
	 */
99
	public static function register( $slug, $args, $availability ) {
100
		$sanitized_slug = sanitize_title_with_dashes( $slug );
101
		self::$registered[ $sanitized_slug ] = array( 'args' => $args, 'availability' => $availability );
102
	}
103
104
	/**
105
	 * Register all Jetpack blocks available.
106
	 *
107
	 * @return void
108
	 */
109
	public static function init() {
110
		if ( ! self::is_gutenberg_available() ) {
111
			return;
112
		}
113
114
		if ( ! self::should_load() ) {
115
			return;
116
		}
117
118
		if ( Jetpack_Constants::is_true( 'REST_API_REQUEST' ) ) {
119
			// We defer the loading of the blocks until we have a better scope in reset requests.
120
121
			add_filter( 'rest_request_before_callbacks', array( __CLASS__, 'load' ) );
122
			return;
123
		}
124
125
		self::load();
126
	}
127
128
	/**
129
	 * @deprecated
130
	 */
131
	static function load_blocks() {
132
		self::init();
133
	}
134
135
	/**
136
	 * Add a block to the list of blocks to be registered.
137
	 *
138
	 * @param string $slug Slug of the block.
0 ignored issues
show
Bug introduced by
There is no parameter named $slug. 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...
139
	 * @param array  $args Arguments that are passed into the register_block_type.
140
	 * @param array $availability array containing if a block is available and the reason when it is not.
141
	 *
142
	 * @deprecated
143
	 */
144
	static function add_block( $type, $args, $availability ) {
145
		self::register( $type, $args, $availability );
146
	}
147
148
	static function load( $request = null ) {
149
		/**
150
		 * Filter the list of block editor blocks that are available through jetpack.
151
		 *
152
		 * This filter is populated by Jetpack_Gutenberg::jetpack_set_available_blocks
153
		 *
154
		 * @since 6.8.0
155
		 *
156
		 * @param array
157
		 */
158
		self::$blocks = apply_filters( 'jetpack_set_available_blocks', self::$default_blocks );
159
160
		/**
161
		 * Filter the list of block editor plugins that are available through jetpack.
162
		 *
163
		 * This filter is populated by Jetpack_Gutenberg::jetpack_set_available_blocks
164
		 *
165
		 * @since 6.9.0
166
		 *
167
		 * @param array
168
		 */
169
		self::$plugins = apply_filters( 'jetpack_set_available_plugins', self::$default_plugins );
170
		self::set_blocks_availability();
171
		self::set_plugins_availability();
172
		self::register_blocks();
173
		return $request;
174
	}
175
176
	static function is_registered( $slug ) {
177
		return isset( self::$registered[ $slug ] );
178
	}
179
180
	static function get_registered_args( $slug ) {
181
		return self::$registered[ $slug ]['args'];
182
	}
183
	static function get_registered_type( $slug ) {
184
		return self::$registered[ $slug ]['type'];
185
	}
186
187
	static function is_available( $slug ) {
188
		if ( ! isset( self::$availability[ $slug ]['available'] ) ) {
189
			return false;
190
		}
191
		return (bool) self::$availability[ $slug ]['available'];
192
	}
193
194
195
	static function get_extension_availability( $slug ) {
196
		if ( ! self::is_registered( $slug ) ) {
197
			return array( 'available' => false, 'unavailable_reason' => 'missing_module' );
198
		}
199
200
		$availability = self::$registered[ $slug ]['availability'];
201
202
		if ( isset( $availability['callback'] ) ) {
203
			$availability = call_user_func( $availability['callback'] );
204
		}
205
206
		$availability['available'] = isset( $availability['available'] )
207
			? (bool) $availability['available']
208
			: true ; // this is the default value
209
210
		if ( ! $availability['available'] ) {
211
			$availability['unavailable_reason'] = isset( $availability['unavailable_reason'] )
212
				? $availability['unavailable_reason']
213
				: 'unknown'; //
214
		}
215
216
		return $availability;
217
	}
218
219
	static function set_blocks_availability() {
220
		foreach ( self::$blocks as $slug ) {
221
			self::$availability[ $slug ] = self::get_extension_availability( $slug );
222
		}
223
	}
224
225
	static function set_plugins_availability() {
226
		foreach ( self::$plugins as $slug ) {
227
			self::$availability[ $slug ] = self::get_extension_availability( $slug );
228
		}
229
	}
230
231
	static function register_blocks() {
232
		foreach ( self::$blocks as $slug ) {
233
			if ( self::is_available( $slug ) ) {
234
				register_block_type( 'jetpack/' . $slug, self::get_registered_args( $slug ) );
235
			}
236
		}
237
	}
238
239
	/**
240
	 * Return the Gutenberg extensions (blocks and plugins) directory
241
	 *
242
	 * @return string The Gutenberg extensions directory
243
	 */
244
	public static function get_blocks_directory() {
245
		/**
246
		 * Filter to select Gutenberg blocks directory
247
		 *
248
		 * @since 6.9
249
		 *
250
		 * @param string default: '_inc/blocks/'
251
		 */
252
		return apply_filters( 'jetpack_blocks_directory', '_inc/blocks/' );
253
	}
254
255
	/**
256
	 * Checks for a given .json file in the blocks folder.
257
	 *
258
	 * @param $preset The name of the .json file to look for.
259
	 *
260
	 * @return bool True if the file is found.
261
	 */
262
	public static function preset_exists( $preset ) {
263
		return file_exists( JETPACK__PLUGIN_DIR . self::get_blocks_directory() . $preset . '.json' );
264
	}
265
266
	/**
267
	 * Decodes JSON loaded from a preset file in the blocks folder
268
	 *
269
	 * @param $preset The name of the .json file to load.
270
	 *
271
	 * @return mixed Returns an object if the file is present, or false if a valid .json file is not present.
272
	 */
273
	public static function get_preset( $preset ) {
274
		return json_decode( file_get_contents(  JETPACK__PLUGIN_DIR .self::get_blocks_directory() . $preset . '.json' ) );
275
	}
276
277
	/**
278
	 * Filters the results of `apply_filter( 'jetpack_set_available_blocks', array() )`
279
	 * using the merged contents of `blocks-manifest.json` ( $preset_blocks )
280
	 * and self::$jetpack_blocks ( $internal_blocks )
281
	 *
282
	 * @param $blocks The default list.
283
	 *
284
	 * @return array A list of blocks: eg [ 'publicize', 'markdown' ]
285
	 */
286
	public static function jetpack_set_available_blocks( $blocks ) {
287
		$preset_blocks_manifest =  self::preset_exists( 'index' ) ? self::get_preset( 'index' ) : (object) array( 'blocks' => $blocks );
288
		// manifest shouldn't remove default blocks...
289
290
		$preset_blocks = isset( $preset_blocks_manifest->production ) ? (array) $preset_blocks_manifest->production : array() ;
291
		$preset_blocks = array_unique( array_merge( $preset_blocks, $blocks ) );
292
293
		if ( Jetpack_Constants::is_true( 'JETPACK_BETA_BLOCKS' ) ) {
294
			$beta_blocks = isset( $preset_blocks_manifest->beta ) ? (array) $preset_blocks_manifest->beta : array();
295
			return array_unique( array_merge( $preset_blocks, $beta_blocks ) );
296
		}
297
298
		return $preset_blocks;
299
	}
300
301
	/**
302
	 * @deprecated
303
	 * @return array A list of block-availability information, eg: [ "publicize" => ["available" => true ], "markdown" => [ "available" => false, "unavailable_reason" => 'missing_module' ] ]
304
	 */
305
	public static function get_block_availability() {
306
		return self::get_availability();
307
	}
308
309
	/**
310
	 * @return array A list of block and plugins and their availablity status
311
	 */
312
	public static function get_availability() {
313
		if ( ! self::should_load() ) {
314
			return array();
315
		}
316
317
		return self::$availability;
318
	}
319
320
	/**
321
	 * Check if Gutenberg editor is available
322
	 *
323
	 * @since 6.7.0
324
	 *
325
	 * @return bool
326
	 */
327
	public static function is_gutenberg_available() {
328
		return function_exists( 'register_block_type' );
329
	}
330
331
	/**
332
	 * Check whether conditions indicate Gutenberg blocks should be loaded
333
	 *
334
	 * Loading blocks is enabled by default and may be disabled via filter:
335
	 *   add_filter( 'jetpack_gutenberg', '__return_false' );
336
	 *
337
	 * @since 6.7.0
338
	 * @deprecated
339
	 * @return bool
340
	 */
341
	public static function should_load_blocks() {
342
		return self::should_load();
343
	}
344
345
	/**
346
	 * Check whether conditions indicate Gutenberg Extensions (blocks and plugins) should be loaded
347
	 *
348
	 * Loading blocks and plugins is enabled by default and may be disabled via filter:
349
	 *   add_filter( 'jetpack_gutenberg', '__return_false' );
350
	 *
351
	 * @since 6.9.0
352
	 *
353
	 * @return bool
354
	 */
355
	public static function should_load() {
356
		if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
357
			return false;
358
		}
359
360
		/**
361
		 * Filter to disable Gutenberg blocks
362
		 *
363
		 * @since 6.5.0
364
		 *
365
		 * @param bool true Whether to load Gutenberg blocks
366
		 */
367
		return (bool) apply_filters( 'jetpack_gutenberg', true );
368
	}
369
370
	/**
371
	 * Only enqueue block assets when needed.
372
	 *
373
	 * @param string $type slug of the block.
374
	 * @param array $script_dependencies An array of view-side Javascript dependencies to be enqueued.
375
	 *
376
	 * @return void
377
	 */
378
	public static function load_assets_as_required( $type, $script_dependencies = array() ) {
379
		if ( is_admin() ) {
380
			// A block's view assets will not be required in wp-admin.
381
			return;
382
		}
383
384
		$type = sanitize_title_with_dashes( $type );
385
		// Enqueue styles.
386
		$style_relative_path = self::get_blocks_directory() . $type . '/view' . ( is_rtl() ? '.rtl' : '' ) . '.css';
387 View Code Duplication
		if ( self::block_has_asset( $style_relative_path ) ) {
388
			$style_version = self::get_asset_version( $style_relative_path );
389
			$view_style    = plugins_url( $style_relative_path, JETPACK__PLUGIN_FILE );
390
			wp_enqueue_style( 'jetpack-block-' . $type, $view_style, array(), $style_version );
391
		}
392
393
		// Enqueue script.
394
		$script_relative_path = self::get_blocks_directory() . $type . '/view.js';
395 View Code Duplication
		if ( self::block_has_asset( $script_relative_path ) ) {
396
			$script_version = self::get_asset_version( $script_relative_path );
397
			$view_script    = plugins_url( $script_relative_path, JETPACK__PLUGIN_FILE );
398
			wp_enqueue_script( 'jetpack-block-' . $type, $view_script, $script_dependencies, $script_version, false );
399
		}
400
401
		wp_localize_script(
402
			'jetpack-block-' . $type,
403
			'Jetpack_Block_Assets_Base_Url',
404
			plugins_url( self::get_blocks_directory(), JETPACK__PLUGIN_FILE )
405
		);
406
	}
407
408
	/**
409
	 * Check if an asset exists for a block.
410
	 *
411
	 * @param string $file Path of the file we are looking for.
412
	 *
413
	 * @return bool $block_has_asset Does the file exist.
414
	 */
415
	public static function block_has_asset( $file ) {
416
		return file_exists( JETPACK__PLUGIN_DIR . $file );
417
	}
418
419
	/**
420
	 * Get the version number to use when loading the file. Allows us to bypass cache when developing.
421
	 *
422
	 * @param string $file Path of the file we are looking for.
423
	 *
424
	 * @return string $script_version Version number.
425
	 */
426
	public static function get_asset_version( $file ) {
427
		return Jetpack::is_development_version() && self::block_has_asset( $file )
428
			? filemtime( JETPACK__PLUGIN_DIR . $file )
429
			: JETPACK__VERSION;
430
	}
431
432
	/**
433
	 * Load Gutenberg editor assets
434
	 *
435
	 * @since 6.7.0
436
	 *
437
	 * @return void
438
	 */
439
	public static function enqueue_block_editor_assets() {
440
		if ( ! self::should_load_blocks() ) {
0 ignored issues
show
Deprecated Code introduced by
The method Jetpack_Gutenberg::should_load_blocks() has been deprecated.

This method has been deprecated.

Loading history...
441
			return;
442
		}
443
444
		$rtl = is_rtl() ? '.rtl' : '';
445
		$beta = Jetpack_Constants::is_true('JETPACK_BETA_BLOCKS' ) ? '-beta' : '';
446
		$blocks_dir = self::get_blocks_directory();
447
448
		$editor_script = plugins_url( "{$blocks_dir}editor{$beta}.js", JETPACK__PLUGIN_FILE );
449
		$editor_style  = plugins_url( "{$blocks_dir}editor{$beta}{$rtl}.css", JETPACK__PLUGIN_FILE );
450
451
		$version       = Jetpack::is_development_version() && file_exists( JETPACK__PLUGIN_DIR . $blocks_dir . 'editor.js' )
452
			? filemtime( JETPACK__PLUGIN_DIR . $blocks_dir . 'editor.js' )
453
			: JETPACK__VERSION;
454
455
		wp_enqueue_script(
456
			'jetpack-blocks-editor',
457
			$editor_script,
458
			array(
459
				'lodash',
460
				'wp-api-fetch',
461
				'wp-blocks',
462
				'wp-components',
463
				'wp-compose',
464
				'wp-data',
465
				'wp-date',
466
				'wp-edit-post',
467
				'wp-editor',
468
				'wp-element',
469
				'wp-hooks',
470
				'wp-i18n',
471
				'wp-keycodes',
472
				'wp-plugins',
473
				'wp-rich-text',
474
				'wp-token-list',
475
				'wp-url',
476
			),
477
			$version,
478
			false
479
		);
480
481
		wp_localize_script(
482
			'jetpack-blocks-editor',
483
			'Jetpack_Block_Assets_Base_Url',
484
			plugins_url( $blocks_dir . '/', JETPACK__PLUGIN_FILE )
485
		);
486
487
		wp_localize_script(
488
			'jetpack-blocks-editor',
489
			'Jetpack_Editor_Initial_State',
490
			array(
491
				'available_blocks' => self::get_block_availability(),
0 ignored issues
show
Deprecated Code introduced by
The method Jetpack_Gutenberg::get_block_availability() has been deprecated.

This method has been deprecated.

Loading history...
492
				'jetpack' => array( 'is_active' => Jetpack::is_active() ),
493
			)
494
		);
495
496
		Jetpack::setup_wp_i18n_locale_data();
497
498
		wp_enqueue_style( 'jetpack-blocks-editor', $editor_style, array(), $version );
499
500
		// The social-logos styles are used for Publicize service icons
501
		// TODO: Remove when we ship the icons with the Gutenberg blocks build
502
		wp_enqueue_style( 'social-logos' );
503
	}
504
}
505