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 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 //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName |
||
65 | class Jetpack_Gutenberg { |
||
66 | |||
67 | /** |
||
68 | * Only these extensions can be registered. Used to control availability of beta blocks. |
||
69 | * |
||
70 | * @var array Extensions allowed list. |
||
71 | */ |
||
72 | public static $extensions = array(); |
||
73 | |||
74 | /** |
||
75 | * Keeps track of the reasons why a given extension is unavailable. |
||
76 | * |
||
77 | * @var array Extensions availability information |
||
78 | */ |
||
79 | private static $availability = array(); |
||
80 | |||
81 | /** |
||
82 | * Check to see if a minimum version of Gutenberg is available. Because a Gutenberg version is not available in |
||
83 | * php if the Gutenberg plugin is not installed, if we know which minimum WP release has the required version we can |
||
84 | * optionally fall back to that. |
||
85 | * |
||
86 | * @param array $version_requirements An array containing the required Gutenberg version and, if known, the WordPress version that was released with this minimum version. |
||
87 | * @param string $slug The slug of the block or plugin that has the gutenberg version requirement. |
||
88 | * |
||
89 | * @since 8.3.0 |
||
90 | * |
||
91 | * @return boolean True if the version of gutenberg required by the block or plugin is available. |
||
92 | */ |
||
93 | public static function is_gutenberg_version_available( $version_requirements, $slug ) { |
||
133 | |||
134 | /** |
||
135 | * Remove the 'jetpack/' or jetpack-' prefix from an extension name |
||
136 | * |
||
137 | * @param string $extension_name The extension name. |
||
138 | * |
||
139 | * @return string The unprefixed extension name. |
||
140 | */ |
||
141 | public static function remove_extension_prefix( $extension_name ) { |
||
147 | |||
148 | /** |
||
149 | * Whether two arrays share at least one item |
||
150 | * |
||
151 | * @param array $a An array. |
||
152 | * @param array $b Another array. |
||
153 | * |
||
154 | * @return boolean True if $a and $b share at least one item |
||
155 | */ |
||
156 | protected static function share_items( $a, $b ) { |
||
159 | |||
160 | /** |
||
161 | * Set a (non-block) extension as available |
||
162 | * |
||
163 | * @param string $slug Slug of the extension. |
||
164 | */ |
||
165 | public static function set_extension_available( $slug ) { |
||
168 | |||
169 | /** |
||
170 | * Set the reason why an extension (block or plugin) is unavailable |
||
171 | * |
||
172 | * @param string $slug Slug of the extension. |
||
173 | * @param string $reason A string representation of why the extension is unavailable. |
||
174 | * @param array $details A free-form array containing more information on why the extension is unavailable. |
||
175 | */ |
||
176 | public static function set_extension_unavailable( $slug, $reason, $details = array() ) { |
||
207 | |||
208 | /** |
||
209 | * Set up a list of allowed block editor extensions |
||
210 | * |
||
211 | * @return void |
||
212 | */ |
||
213 | public static function init() { |
||
259 | |||
260 | /** |
||
261 | * Resets the class to its original state |
||
262 | * |
||
263 | * Used in unit tests |
||
264 | * |
||
265 | * @return void |
||
266 | */ |
||
267 | public static function reset() { |
||
271 | |||
272 | /** |
||
273 | * Return the Gutenberg extensions (blocks and plugins) directory |
||
274 | * |
||
275 | * @return string The Gutenberg extensions directory |
||
276 | */ |
||
277 | public static function get_extension_path( $type ) { |
||
278 | $default_extension_path = self::get_blocks_directory() . $type; |
||
279 | return apply_filters( 'jetpack_get_extension_path', $default_extension_path, $type ); |
||
280 | } |
||
281 | |||
282 | public static function get_blocks_directory() { |
||
283 | /** |
||
284 | * Filter to select Gutenberg blocks directory |
||
285 | * |
||
286 | * @since 6.9.0 |
||
287 | * |
||
288 | * @param string default: false |
||
289 | */ |
||
290 | return apply_filters( 'jetpack_blocks_directory', false ); |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * Returns a list of Jetpack Gutenberg extensions (blocks and plugins) |
||
295 | * |
||
296 | * @return array A list of blocks: eg [ 'publicize', 'markdown' ] |
||
297 | */ |
||
298 | public static function get_jetpack_gutenberg_extensions_allowed_list() { |
||
299 | $preset_extensions_manifest = (object) array(); |
||
300 | $blocks_variation = self::blocks_variation(); |
||
301 | |||
302 | return self::get_extensions_preset_for_variation( $preset_extensions_manifest, $blocks_variation ); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Returns a list of Jetpack Gutenberg extensions (blocks and plugins) |
||
307 | * |
||
308 | * @deprecated 8.7.0 Use get_jetpack_gutenberg_extensions_allowed_list() |
||
309 | * |
||
310 | * @return array A list of blocks: eg [ 'publicize', 'markdown' ] |
||
311 | */ |
||
312 | public static function get_jetpack_gutenberg_extensions_whitelist() { |
||
313 | _deprecated_function( __FUNCTION__, 'jetpack-8.7.0', 'Jetpack_Gutenberg::get_jetpack_gutenberg_extensions_allowed_list' ); |
||
314 | return self::get_jetpack_gutenberg_extensions_allowed_list(); |
||
315 | } |
||
316 | |||
317 | /** |
||
318 | * Return true if the extension has been registered and there's nothing in the availablilty array. |
||
319 | * |
||
320 | * @param string $extension The name of the extension. |
||
321 | * |
||
322 | * @return bool whether the extension has been registered and there's nothing in the availablilty array. |
||
323 | */ |
||
324 | public static function is_registered_and_no_entry_in_availability( $extension ) { |
||
325 | return self::is_registered( 'jetpack/' . $extension ) && ! isset( self::$availability[ $extension ] ); |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Return true if the extension has a true entry in the availablilty array. |
||
330 | * |
||
331 | * @param string $extension The name of the extension. |
||
332 | * |
||
333 | * @return bool whether the extension has a true entry in the availablilty array. |
||
334 | */ |
||
335 | public static function is_available( $extension ) { |
||
336 | return isset( self::$availability[ $extension ] ) && true === self::$availability[ $extension ]; |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Get availability of each block / plugin. |
||
341 | * |
||
342 | * @return array A list of block and plugins and their availablity status |
||
343 | */ |
||
344 | public static function get_availability() { |
||
345 | /** |
||
346 | * Fires before Gutenberg extensions availability is computed. |
||
347 | * |
||
348 | * In the function call you supply, use `jetpack_register_block()` to set a block as available. |
||
349 | * Alternatively, use `Jetpack_Gutenberg::set_extension_available()` (for a non-block plugin), and |
||
350 | * `Jetpack_Gutenberg::set_extension_unavailable()` (if the block or plugin should not be registered |
||
351 | * but marked as unavailable). |
||
352 | * |
||
353 | * @since 7.0.0 |
||
354 | */ |
||
355 | do_action( 'jetpack_register_gutenberg_extensions' ); |
||
356 | |||
357 | $available_extensions = array(); |
||
358 | |||
359 | foreach ( self::$extensions as $extension ) { |
||
360 | $is_available = self::is_registered_and_no_entry_in_availability( $extension ) || self::is_available( $extension ); |
||
361 | $available_extensions[ $extension ] = array( |
||
362 | 'available' => $is_available, |
||
363 | ); |
||
364 | |||
365 | if ( ! $is_available ) { |
||
366 | $reason = isset( self::$availability[ $extension ] ) ? self::$availability[ $extension ]['reason'] : 'missing_module'; |
||
367 | $details = isset( self::$availability[ $extension ] ) ? self::$availability[ $extension ]['details'] : array(); |
||
368 | $available_extensions[ $extension ]['unavailable_reason'] = $reason; |
||
369 | $available_extensions[ $extension ]['details'] = $details; |
||
370 | } |
||
371 | } |
||
372 | |||
373 | return $available_extensions; |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Check if an extension/block is already registered |
||
378 | * |
||
379 | * @since 7.2 |
||
380 | * |
||
381 | * @param string $slug Name of extension/block to check. |
||
382 | * |
||
383 | * @return bool |
||
384 | */ |
||
385 | public static function is_registered( $slug ) { |
||
386 | return WP_Block_Type_Registry::get_instance()->is_registered( $slug ); |
||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Check if Gutenberg editor is available |
||
391 | * |
||
392 | * @since 6.7.0 |
||
393 | * |
||
394 | * @return bool |
||
395 | */ |
||
396 | public static function is_gutenberg_available() { |
||
397 | return true; |
||
398 | } |
||
399 | |||
400 | /** |
||
401 | * Check whether conditions indicate Gutenberg Extensions (blocks and plugins) should be loaded |
||
402 | * |
||
403 | * Loading blocks and plugins is enabled by default and may be disabled via filter: |
||
404 | * add_filter( 'jetpack_gutenberg', '__return_false' ); |
||
405 | * |
||
406 | * @since 6.9.0 |
||
407 | * |
||
408 | * @return bool |
||
409 | */ |
||
410 | public static function should_load() { |
||
411 | /** |
||
412 | * Filter to disable Gutenberg blocks |
||
413 | * |
||
414 | * @since 6.5.0 |
||
415 | * |
||
416 | * @param bool true Whether to load Gutenberg blocks |
||
417 | */ |
||
418 | return (bool) apply_filters( 'jetpack_gutenberg', true ); |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Only enqueue block assets when needed. |
||
423 | * |
||
424 | * @param string $type Slug of the block. |
||
425 | * @param array $script_dependencies Script dependencies. Will be merged with automatically |
||
426 | * detected script dependencies from the webpack build. |
||
427 | * |
||
428 | * @return void |
||
429 | */ |
||
430 | public static function load_assets_as_required( $type, $script_dependencies = array() ) { |
||
440 | |||
441 | /** |
||
442 | * Only enqueue block sytles when needed. |
||
443 | * |
||
444 | * @param string $type Slug of the block. |
||
445 | * |
||
446 | * @since 7.2.0 |
||
447 | * |
||
448 | * @return void |
||
449 | */ |
||
450 | public static function load_styles_as_required( $type ) { |
||
464 | |||
465 | /** |
||
466 | * Only enqueue block scripts when needed. |
||
467 | * |
||
468 | * @param string $type Slug of the block. |
||
469 | * @param array $script_dependencies Script dependencies. Will be merged with automatically |
||
470 | * detected script dependencies from the webpack build. |
||
471 | * |
||
472 | * @since 7.2.0 |
||
473 | * |
||
474 | * @return void |
||
475 | */ |
||
476 | public static function load_scripts_as_required( $type, $script_dependencies = array() ) { |
||
498 | |||
499 | /** |
||
500 | * Get the version number to use when loading the file. Allows us to bypass cache when developing. |
||
501 | * |
||
502 | * @param string $file Path of the file we are looking for. |
||
503 | * |
||
504 | * @return string $script_version Version number. |
||
505 | */ |
||
506 | public static function get_asset_version( $file ) { |
||
507 | // @todo - remove this reference to JETPACK__VERSION |
||
508 | return Jetpack::is_development_version() && file_exists( $file ) |
||
512 | |||
513 | /** |
||
514 | * Get CSS classes for a block. |
||
515 | * |
||
516 | * @since 7.7.0 |
||
517 | * |
||
518 | * @param string $slug Block slug. |
||
519 | * @param array $attr Block attributes. |
||
520 | * @param array $extra Potential extra classes you may want to provide. |
||
521 | * |
||
522 | * @return string $classes List of CSS classes for a block. |
||
523 | */ |
||
524 | public static function block_classes( $slug = '', $attr, $extra = array() ) { |
||
554 | |||
555 | /** |
||
556 | * Determine whether a site should use the default set of blocks, or a custom set. |
||
557 | * Possible variations are currently beta, experimental, and production. |
||
558 | * |
||
559 | * @since 8.1.0 |
||
560 | * |
||
561 | * @return string $block_varation production|beta|experimental |
||
562 | */ |
||
563 | public static function blocks_variation() { |
||
587 | |||
588 | /** |
||
589 | * Get a list of extensions available for the variation you chose. |
||
590 | * |
||
591 | * @since 8.1.0 |
||
592 | * |
||
593 | * @param obj $preset_extensions_manifest List of extensions available in Jetpack. |
||
594 | * @param string $blocks_variation Subset of blocks. production|beta|experimental. |
||
595 | * |
||
596 | * @return array $preset_extensions Array of extensions for that variation |
||
597 | */ |
||
598 | public static function get_extensions_preset_for_variation( $preset_extensions_manifest, $blocks_variation ) { |
||
636 | |||
637 | /** |
||
638 | * Validate a URL used in a SSR block. |
||
639 | * |
||
640 | * @since 8.3.0 |
||
641 | * |
||
642 | * @param string $url URL saved as an attribute in block. |
||
643 | * @param array $allowed Array of allowed hosts for that block, or regexes to check against. |
||
644 | * @param bool $is_regex Array of regexes matching the URL that could be used in block. |
||
645 | * |
||
646 | * @return bool|string |
||
647 | */ |
||
648 | public static function validate_block_embed_url( $url, $allowed = array(), $is_regex = false ) { |
||
702 | |||
703 | /** |
||
704 | * Output an UpgradeNudge Component on the frontend of a site. |
||
705 | * |
||
706 | * @since 8.4.0 |
||
707 | * |
||
708 | * @param string $plan The plan that users need to purchase to make the block work. |
||
709 | * |
||
710 | * @return string |
||
711 | */ |
||
712 | public static function upgrade_nudge( $plan ) { |
||
731 | |||
732 | /** |
||
733 | * Output a notice within a block. |
||
734 | * |
||
735 | * @since 8.6.0 |
||
736 | * |
||
737 | * @param string $message Notice we want to output. |
||
738 | * @param string $status Status of the notice. Can be one of success, info, warning, error. info by default. |
||
739 | * @param string $classes List of CSS classes. |
||
740 | * |
||
741 | * @return string |
||
742 | */ |
||
743 | public static function notice( $message, $status = 'info', $classes = '' ) { |
||
782 | |||
783 | /** |
||
784 | * Set the availability of the block as the editor |
||
785 | * is loaded. |
||
786 | * |
||
787 | * @param string $slug Slug of the block. |
||
788 | */ |
||
789 | public static function set_availability_for_plan( $slug ) { |
||
824 | |||
825 | /** |
||
826 | * Wraps the suplied render_callback in a function to check |
||
827 | * the availability of the block before rendering it. |
||
828 | * |
||
829 | * @param string $slug The block slug, used to check for availability. |
||
830 | * @param callable $render_callback The render_callback that will be called if the block is available. |
||
831 | */ |
||
832 | public static function get_render_callback_with_availability_check( $slug, $render_callback ) { |
||
845 | } |
||
846 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: