Completed
Push — branch-6.8 ( b49ff5...fa246c )
by Jeremy
30:02 queued 21:36
created

class.jetpack-gutenberg.php (1 issue)

Labels
Severity

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