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