Completed
Push — update/load-beta-blocks-proxie... ( 844819...854020 )
by Marin
191:27 queued 184:04
created

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