Completed
Push — branch-6.7 ( 747d70...b1cc7a )
by Jeremy
26:03 queued 17:04
created

Jetpack_Gutenberg   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 283
Duplicated Lines 3.53 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 42
lcom 1
cbo 2
dl 10
loc 283
rs 9.0399
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A add_block() 0 3 1
B load_blocks() 0 26 7
A preset_exists() 0 3 1
A get_preset() 0 3 1
A jetpack_set_available_blocks() 0 10 5
B get_block_availability() 0 34 9
A is_gutenberg_available() 0 3 1
A should_load_blocks() 0 14 3
A load_assets_as_required() 10 18 4
A block_has_asset() 0 3 1
A get_asset_version() 0 5 3
B enqueue_block_editor_assets() 0 59 6

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Jetpack_Gutenberg often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Jetpack_Gutenberg, and based on these observations, apply Extract Interface, too.

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