Completed
Push — update/load-beta-blocks-proxie... ( 943b87 )
by Marin
29:05 queued 21:23
created

Jetpack_Gutenberg::set_plugins_availability()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
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 `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
		'shortlinks',
80
	);
81
	/**
82
	 * @var array Array of plugins information.
83
	 *
84
	 * For each block we have information about the availability for the current user
85
	 */
86
	private static $plugins = array();
87
88
	/**
89
	 * @var array Array of extensions we will be registering.
90
	 */
91
	private static $registered = array();
92
93
	/**
94
	 * Add a block to the list of blocks to be registered.
95
	 *
96
	 * @param string $slug Slug of the block.
97
	 * @param array  $args Arguments that are passed into the register_block_type.
98
	 * @param array $availability array containing if a block is available and the reason when it is not.
99
	 */
100
	public static function register( $slug, $args, $availability ) {
101
		$sanitized_slug = sanitize_title_with_dashes( $slug );
102
		self::$registered[ $sanitized_slug ] = array( 'args' => $args, 'availability' => $availability );
103
	}
104
105
	/**
106
	 * Register all Jetpack blocks available.
107
	 *
108
	 * @return void
109
	 */
110
	public static function init() {
111
		if ( ! self::is_gutenberg_available() ) {
112
			return;
113
		}
114
115
		if ( ! self::should_load() ) {
116
			return;
117
		}
118
119
		if ( Jetpack_Constants::is_true( 'REST_API_REQUEST' ) ) {
120
			// We defer the loading of the blocks until we have a better scope in reset requests.
121
122
			add_filter( 'rest_request_before_callbacks', array( __CLASS__, 'load' ) );
123
			return;
124
		}
125
126
		self::load();
127
	}
128
129
	/**
130
	 * @deprecated
131
	 */
132
	static function load_blocks() {
133
		self::init();
134
	}
135
136
	/**
137
	 * Add a block to the list of blocks to be registered.
138
	 *
139
	 * @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...
140
	 * @param array  $args Arguments that are passed into the register_block_type.
141
	 * @param array $availability array containing if a block is available and the reason when it is not.
142
	 *
143
	 * @deprecated
144
	 */
145
	static function add_block( $type, $args, $availability ) {
146
		self::register( $type, $args, $availability );
147
	}
148
149
	static function load( $request = null ) {
150
		// We display beta blocks in available Gutenberg extensions endpoint requests
151
		$is_availability_endpoint_beta = ! is_null( $request ) && $request->get_param( 'beta' ) && wp_endswith( $request->get_route(), 'gutenberg/available-extensions' );
152
		// We display beta blocks in proxied requests
153
		$is_proxied = function_exists( 'wpcom_is_proxied_request' ) ? wpcom_is_proxied_request() : false;
154
155
		if ( $is_availability_endpoint_beta || $is_proxied ) {
156
			Jetpack_Constants::set_constant( 'JETPACK_BETA_BLOCKS', true );
157
		}
158
159
		/**
160
		 * Filter the list of block editor blocks that are available through jetpack.
161
		 *
162
		 * This filter is populated by Jetpack_Gutenberg::jetpack_set_available_blocks
163
		 *
164
		 * @since 6.8.0
165
		 *
166
		 * @param array
167
		 */
168
		self::$blocks = apply_filters( 'jetpack_set_available_blocks', self::$default_blocks );
169
170
		/**
171
		 * Filter the list of block editor plugins that are available through jetpack.
172
		 *
173
		 * This filter is populated by Jetpack_Gutenberg::jetpack_set_available_blocks
174
		 *
175
		 * @since 6.9.0
176
		 *
177
		 * @param array
178
		 */
179
		self::$plugins = apply_filters( 'jetpack_set_available_plugins', self::$default_plugins );
180
		self::set_blocks_availability();
181
		self::set_plugins_availability();
182
		self::register_blocks();
183
		return $request;
184
	}
185
186
	static function is_registered( $slug ) {
187
		return isset( self::$registered[ $slug ] );
188
	}
189
190
	static function get_registered_args( $slug ) {
191
		return self::$registered[ $slug ]['args'];
192
	}
193
	static function get_registered_type( $slug ) {
194
		return self::$registered[ $slug ]['type'];
195
	}
196
197
	static function is_available( $slug ) {
198
		if ( ! isset( self::$availability[ $slug ]['available'] ) ) {
199
			return false;
200
		}
201
		return (bool) self::$availability[ $slug ]['available'];
202
	}
203
204
205
	static function get_extension_availability( $slug ) {
206
		if ( ! self::is_registered( $slug ) ) {
207
			return array( 'available' => false, 'unavailable_reason' => 'missing_module' );
208
		}
209
210
		$availability = self::$registered[ $slug ]['availability'];
211
212
		if ( isset( $availability['callback'] ) ) {
213
			$availability = call_user_func( $availability['callback'] );
214
		}
215
216
		$availability['available'] = isset( $availability['available'] )
217
			? (bool) $availability['available']
218
			: true ; // this is the default value
219
220
		if ( ! $availability['available'] ) {
221
			$availability['unavailable_reason'] = isset( $availability['unavailable_reason'] )
222
				? $availability['unavailable_reason']
223
				: 'unknown'; //
224
		}
225
226
		return $availability;
227
	}
228
229
	static function set_blocks_availability() {
230
		foreach ( self::$blocks as $slug ) {
231
			self::$availability[ $slug ] = self::get_extension_availability( $slug );
232
		}
233
	}
234
235
	static function set_plugins_availability() {
236
		foreach ( self::$plugins as $slug ) {
237
			self::$availability[ $slug ] = self::get_extension_availability( $slug );
238
		}
239
	}
240
241
	static function register_blocks() {
242
		foreach ( self::$blocks as $slug ) {
243
			if ( self::is_available( $slug ) ) {
244
				register_block_type( 'jetpack/' . $slug, self::get_registered_args( $slug ) );
245
			}
246
		}
247
	}
248
249
	/**
250
	 * Return the Gutenberg extensions (blocks and plugins) directory
251
	 *
252
	 * @return string The Gutenberg extensions directory
253
	 */
254
	public static function get_blocks_directory() {
255
		/**
256
		 * Filter to select Gutenberg blocks directory
257
		 *
258
		 * @since 6.9
259
		 *
260
		 * @param string default: '_inc/blocks/'
261
		 */
262
		return apply_filters( 'jetpack_blocks_directory', '_inc/blocks/' );
263
	}
264
265
	/**
266
	 * Checks for a given .json file in the blocks folder.
267
	 *
268
	 * @param $preset The name of the .json file to look for.
269
	 *
270
	 * @return bool True if the file is found.
271
	 */
272
	public static function preset_exists( $preset ) {
273
		return file_exists( JETPACK__PLUGIN_DIR . self::get_blocks_directory() . $preset . '.json' );
274
	}
275
276
	/**
277
	 * Decodes JSON loaded from a preset file in the blocks folder
278
	 *
279
	 * @param $preset The name of the .json file to load.
280
	 *
281
	 * @return mixed Returns an object if the file is present, or false if a valid .json file is not present.
282
	 */
283
	public static function get_preset( $preset ) {
284
		return json_decode( file_get_contents(  JETPACK__PLUGIN_DIR .self::get_blocks_directory() . $preset . '.json' ) );
285
	}
286
287
	/**
288
	 * Filters the results of `apply_filter( 'jetpack_set_available_blocks', array() )`
289
	 * using the merged contents of `blocks-manifest.json` ( $preset_blocks )
290
	 * and self::$jetpack_blocks ( $internal_blocks )
291
	 *
292
	 * @param $blocks The default list.
293
	 *
294
	 * @return array A list of blocks: eg [ 'publicize', 'markdown' ]
295
	 */
296
	public static function jetpack_set_available_blocks( $blocks ) {
297
		$preset_blocks_manifest =  self::preset_exists( 'index' ) ? self::get_preset( 'index' ) : (object) array( 'blocks' => $blocks );
298
		// manifest shouldn't remove default blocks...
299
300
		$preset_blocks = isset( $preset_blocks_manifest->production ) ? (array) $preset_blocks_manifest->production : array() ;
301
		$preset_blocks = array_unique( array_merge( $preset_blocks, $blocks ) );
302
303
		if ( Jetpack_Constants::is_true( 'JETPACK_BETA_BLOCKS' ) ) {
304
			$beta_blocks = isset( $preset_blocks_manifest->beta ) ? (array) $preset_blocks_manifest->beta : array();
305
			return array_unique( array_merge( $preset_blocks, $beta_blocks ) );
306
		}
307
308
		return $preset_blocks;
309
	}
310
311
	/**
312
	 * @deprecated
313
	 * @return array A list of block-availability information, eg: [ "publicize" => ["available" => true ], "markdown" => [ "available" => false, "unavailable_reason" => 'missing_module' ] ]
314
	 */
315
	public static function get_block_availability() {
316
		return self::get_availability();
317
	}
318
319
	/**
320
	 * @return array A list of block and plugins and their availablity status
321
	 */
322
	public static function get_availability() {
323
		if ( ! self::should_load() ) {
324
			return array();
325
		}
326
327
		return self::$availability;
328
	}
329
330
	/**
331
	 * Check if Gutenberg editor is available
332
	 *
333
	 * @since 6.7.0
334
	 *
335
	 * @return bool
336
	 */
337
	public static function is_gutenberg_available() {
338
		return function_exists( 'register_block_type' );
339
	}
340
341
	/**
342
	 * Check whether conditions indicate Gutenberg blocks should be loaded
343
	 *
344
	 * Loading blocks is enabled by default and may be disabled via filter:
345
	 *   add_filter( 'jetpack_gutenberg', '__return_false' );
346
	 *
347
	 * @since 6.7.0
348
	 * @deprecated
349
	 * @return bool
350
	 */
351
	public static function should_load_blocks() {
352
		return self::should_load();
353
	}
354
355
	/**
356
	 * Check whether conditions indicate Gutenberg Extensions (blocks and plugins) should be loaded
357
	 *
358
	 * Loading blocks and plugins is enabled by default and may be disabled via filter:
359
	 *   add_filter( 'jetpack_gutenberg', '__return_false' );
360
	 *
361
	 * @since 6.9.0
362
	 *
363
	 * @return bool
364
	 */
365
	public static function should_load() {
366
		if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
367
			return false;
368
		}
369
370
		/**
371
		 * Filter to disable Gutenberg blocks
372
		 *
373
		 * @since 6.5.0
374
		 *
375
		 * @param bool true Whether to load Gutenberg blocks
376
		 */
377
		return (bool) apply_filters( 'jetpack_gutenberg', true );
378
	}
379
380
	/**
381
	 * Only enqueue block assets when needed.
382
	 *
383
	 * @param string $type slug of the block.
384
	 * @param array $script_dependencies An array of view-side Javascript dependencies to be enqueued.
385
	 *
386
	 * @return void
387
	 */
388
	public static function load_assets_as_required( $type, $script_dependencies = array() ) {
389
		if ( is_admin() ) {
390
			// A block's view assets will not be required in wp-admin.
391
			return;
392
		}
393
394
		$type = sanitize_title_with_dashes( $type );
395
		// Enqueue styles.
396
		$style_relative_path = self::get_blocks_directory() . $type . '/view' . ( is_rtl() ? '.rtl' : '' ) . '.css';
397 View Code Duplication
		if ( self::block_has_asset( $style_relative_path ) ) {
398
			$style_version = self::get_asset_version( $style_relative_path );
399
			$view_style    = plugins_url( $style_relative_path, JETPACK__PLUGIN_FILE );
400
			wp_enqueue_style( 'jetpack-block-' . $type, $view_style, array(), $style_version );
401
		}
402
403
		// Enqueue script.
404
		$script_relative_path = self::get_blocks_directory() . $type . '/view.js';
405 View Code Duplication
		if ( self::block_has_asset( $script_relative_path ) ) {
406
			$script_version = self::get_asset_version( $script_relative_path );
407
			$view_script    = plugins_url( $script_relative_path, JETPACK__PLUGIN_FILE );
408
			wp_enqueue_script( 'jetpack-block-' . $type, $view_script, $script_dependencies, $script_version, false );
409
		}
410
411
		wp_localize_script(
412
			'jetpack-block-' . $type,
413
			'Jetpack_Block_Assets_Base_Url',
414
			plugins_url( self::get_blocks_directory(), JETPACK__PLUGIN_FILE )
415
		);
416
	}
417
418
	/**
419
	 * Check if an asset exists for a block.
420
	 *
421
	 * @param string $file Path of the file we are looking for.
422
	 *
423
	 * @return bool $block_has_asset Does the file exist.
424
	 */
425
	public static function block_has_asset( $file ) {
426
		return file_exists( JETPACK__PLUGIN_DIR . $file );
427
	}
428
429
	/**
430
	 * Get the version number to use when loading the file. Allows us to bypass cache when developing.
431
	 *
432
	 * @param string $file Path of the file we are looking for.
433
	 *
434
	 * @return string $script_version Version number.
435
	 */
436
	public static function get_asset_version( $file ) {
437
		return Jetpack::is_development_version() && self::block_has_asset( $file )
438
			? filemtime( JETPACK__PLUGIN_DIR . $file )
439
			: JETPACK__VERSION;
440
	}
441
442
	/**
443
	 * Load Gutenberg editor assets
444
	 *
445
	 * @since 6.7.0
446
	 *
447
	 * @return void
448
	 */
449
	public static function enqueue_block_editor_assets() {
450
		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...
451
			return;
452
		}
453
454
		$rtl = is_rtl() ? '.rtl' : '';
455
		$beta = Jetpack_Constants::is_true('JETPACK_BETA_BLOCKS' ) ? '-beta' : '';
456
		$blocks_dir = self::get_blocks_directory();
457
458
		$editor_script = plugins_url( "{$blocks_dir}editor{$beta}.js", JETPACK__PLUGIN_FILE );
459
		$editor_style  = plugins_url( "{$blocks_dir}editor{$beta}{$rtl}.css", JETPACK__PLUGIN_FILE );
460
461
		$version       = Jetpack::is_development_version() && file_exists( JETPACK__PLUGIN_DIR . $blocks_dir . 'editor.js' )
462
			? filemtime( JETPACK__PLUGIN_DIR . $blocks_dir . 'editor.js' )
463
			: JETPACK__VERSION;
464
465
		wp_enqueue_script(
466
			'jetpack-blocks-editor',
467
			$editor_script,
468
			array(
469
				'lodash',
470
				'wp-api-fetch',
471
				'wp-blocks',
472
				'wp-components',
473
				'wp-compose',
474
				'wp-data',
475
				'wp-date',
476
				'wp-edit-post',
477
				'wp-editor',
478
				'wp-element',
479
				'wp-hooks',
480
				'wp-i18n',
481
				'wp-keycodes',
482
				'wp-plugins',
483
				'wp-rich-text',
484
				'wp-token-list',
485
				'wp-url',
486
			),
487
			$version,
488
			false
489
		);
490
491
		wp_localize_script(
492
			'jetpack-blocks-editor',
493
			'Jetpack_Block_Assets_Base_Url',
494
			plugins_url( $blocks_dir . '/', JETPACK__PLUGIN_FILE )
495
		);
496
497
		wp_localize_script(
498
			'jetpack-blocks-editor',
499
			'Jetpack_Editor_Initial_State',
500
			array(
501
				'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...
502
				'jetpack' => array( 'is_active' => Jetpack::is_active() ),
503
			)
504
		);
505
506
		Jetpack::setup_wp_i18n_locale_data();
507
508
		wp_enqueue_style( 'jetpack-blocks-editor', $editor_style, array(), $version );
509
510
		// The social-logos styles are used for Publicize service icons
511
		// TODO: Remove when we ship the icons with the Gutenberg blocks build
512
		wp_enqueue_style( 'social-logos' );
513
	}
514
}
515