Completed
Push — renovate/automattic-jetpack-bl... ( 92e79a )
by
unknown
16:38 queued 10:00
created

class.jetpack-gutenberg.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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