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