Completed
Push — branch-6.8 ( f2133f...d56fa6 )
by Jeremy
42:43 queued 34:44
created

Jetpack_Gutenberg::is_gutenberg_available()   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 `_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
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( $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
		if ( is_admin() ) {
209
			// A block's view assets will not be required in wp-admin.
210
			return;
211
		}
212
213
		$type = sanitize_title_with_dashes( $type );
214
		// Enqueue styles.
215
		$style_relative_path = '_inc/blocks/' . $type . '/view' . ( is_rtl() ? '.rtl' : '' ) . '.css';
216 View Code Duplication
		if ( self::block_has_asset( $style_relative_path ) ) {
217
			$style_version = self::get_asset_version( $style_relative_path );
218
			$view_style    = plugins_url( $style_relative_path, JETPACK__PLUGIN_FILE );
219
			wp_enqueue_style( 'jetpack-block-' . $type, $view_style, array(), $style_version );
220
		}
221
222
		// Enqueue script.
223
		$script_relative_path = '_inc/blocks/' . $type . '/view.js';
224 View Code Duplication
		if ( self::block_has_asset( $script_relative_path ) ) {
225
			$script_version = self::get_asset_version( $script_relative_path );
226
			$view_script    = plugins_url( $script_relative_path, JETPACK__PLUGIN_FILE );
227
			wp_enqueue_script( 'jetpack-block-' . $type, $view_script, $script_dependencies, $script_version, false );
228
		}
229
230
		wp_localize_script(
231
			'jetpack-block-' . $type,
232
			'Jetpack_Block_Assets_Base_Url',
233
			plugins_url( '_inc/blocks/', JETPACK__PLUGIN_FILE )
234
		);
235
	}
236
237
	/**
238
	 * Check if an asset exists for a block.
239
	 *
240
	 * @param string $file Path of the file we are looking for.
241
	 *
242
	 * @return bool $block_has_asset Does the file exist.
243
	 */
244
	public static function block_has_asset( $file ) {
245
		return file_exists( JETPACK__PLUGIN_DIR . $file );
246
	}
247
248
	/**
249
	 * Get the version number to use when loading the file. Allows us to bypass cache when developing.
250
	 *
251
	 * @param string $file Path of the file we are looking for.
252
	 *
253
	 * @return string $script_version Version number.
254
	 */
255
	public static function get_asset_version( $file ) {
256
		return Jetpack::is_development_version() && self::block_has_asset( $file )
257
			? filemtime( JETPACK__PLUGIN_DIR . $file )
258
			: JETPACK__VERSION;
259
	}
260
261
	/**
262
	 * Load Gutenberg editor assets
263
	 *
264
	 * @since 6.7.0
265
	 *
266
	 * @return void
267
	 */
268
	public static function enqueue_block_editor_assets() {
269
		if ( ! self::should_load_blocks() ) {
270
			return;
271
		}
272
273
		$rtl = is_rtl() ? '.rtl' : '';
274
		$beta = Jetpack_Constants::is_true('JETPACK_BETA_BLOCKS' ) ? '-beta' : '';
275
276
		$editor_script = plugins_url( "_inc/blocks/editor{$beta}.js", JETPACK__PLUGIN_FILE );
277
		$editor_style  = plugins_url( "_inc/blocks/editor{$beta}{$rtl}.css", JETPACK__PLUGIN_FILE );
278
279
		$version       = Jetpack::is_development_version() && file_exists( JETPACK__PLUGIN_DIR . '_inc/blocks/editor.js' )
280
			? filemtime( JETPACK__PLUGIN_DIR . '_inc/blocks/editor.js' )
281
			: JETPACK__VERSION;
282
283
		wp_enqueue_script(
284
			'jetpack-blocks-editor',
285
			$editor_script,
286
			array(
287
				'lodash',
288
				'wp-api-fetch',
289
				'wp-blocks',
290
				'wp-components',
291
				'wp-compose',
292
				'wp-data',
293
				'wp-date',
294
				'wp-edit-post',
295
				'wp-editor',
296
				'wp-element',
297
				'wp-hooks',
298
				'wp-i18n',
299
				'wp-keycodes',
300
				'wp-plugins',
301
				'wp-token-list',
302
				'wp-url',
303
			),
304
			$version,
305
			false
306
		);
307
308
		wp_localize_script(
309
			'jetpack-blocks-editor',
310
			'Jetpack_Block_Assets_Base_Url',
311
			plugins_url( '_inc/blocks/', JETPACK__PLUGIN_FILE )
312
		);
313
314
		wp_localize_script(
315
			'jetpack-blocks-editor',
316
			'Jetpack_Editor_Initial_State',
317
			array(
318
				'available_blocks' => self::get_block_availability(),
319
				'jetpack' => array( 'is_active' => Jetpack::is_active() ),
320
			)
321
		);
322
323
		Jetpack::setup_wp_i18n_locale_data();
324
325
		wp_enqueue_style( 'jetpack-blocks-editor', $editor_style, array(), $version );
326
327
		// The social-logos styles are used for Publicize service icons
328
		// TODO: Remove when we ship the icons with the Gutenberg blocks build
329
		wp_enqueue_style( 'social-logos' );
330
	}
331
}
332