Completed
Push — fix/nav-unification-menu-open-... ( d629c6...f468b4 )
by
unknown
17:24 queued 09:08
created

Jetpack_AMP_Support   F

Complexity

Total Complexity 81

Size/Duplication

Total Lines 520
Duplicated Lines 1.35 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 7
loc 520
rs 2
c 0
b 0
f 0
wmc 81
lcom 2
cbo 4

23 Methods

Rating   Name   Duplication   Size   Complexity  
A comment_likes_enabled() 0 3 2
A admin_init() 0 4 1
A is_amp_canonical() 0 3 2
A is_amp_request() 0 12 2
A amp_disable_the_content_filters() 0 10 3
A disable_comment_likes_before_the_content() 0 6 2
B init() 0 54 5
A disable_likes_admin_bar() 0 6 2
A add_stats_pixel() 0 6 2
A amp_post_template_metadata() 0 11 5
A add_site_icon_to_metadata() 0 22 4
B add_image_to_metadata() 0 42 6
A add_fallback_image_to_metadata() 0 13 1
A staticize_subdomain() 0 8 2
B extract_image_dimensions_from_getimagesize() 0 21 7
A amp_post_jetpack_og_tags() 0 9 4
A videopress_enable_freedom_mode() 0 6 2
B render_sharing_html() 0 32 6
A amp_disable_sharedaddy_css() 0 7 2
A amp_enqueue_sharing_css() 0 5 2
A amp_reader_sharing_css() 0 21 3
C filter_photon_post_image_args_for_stories() 7 49 14
A filter_jetpack_options_safelist() 0 6 2

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_AMP_Support 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_AMP_Support, and based on these observations, apply Extract Interface, too.

1
<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3
use Automattic\Jetpack\Assets;
4
use Automattic\Jetpack\Sync\Functions;
5
6
/**
7
 * Manages compatibility with the amp-wp plugin
8
 *
9
 * @see https://github.com/Automattic/amp-wp
10
 */
11
class Jetpack_AMP_Support {
12
13
	/**
14
	 * Apply custom AMP changes on the front-end.
15
	 */
16
	public static function init() {
17
18
		// Add Stats tracking pixel on Jetpack sites when the Stats module is active.
19
		if (
20
			Jetpack::is_module_active( 'stats' )
21
			&& ! ( defined( 'IS_WPCOM' ) && IS_WPCOM )
22
		) {
23
			add_action( 'amp_post_template_footer', array( 'Jetpack_AMP_Support', 'add_stats_pixel' ) );
24
		}
25
26
		/**
27
		 * Remove this during the init hook in case users have enabled it during
28
		 * the after_setup_theme hook, which triggers before init.
29
		 */
30
		remove_theme_support( 'jetpack-devicepx' );
31
32
		// Sharing.
33
		add_filter( 'jetpack_sharing_display_markup', array( 'Jetpack_AMP_Support', 'render_sharing_html' ), 10, 2 );
34
		add_filter( 'sharing_enqueue_scripts', array( 'Jetpack_AMP_Support', 'amp_disable_sharedaddy_css' ) );
35
		add_action( 'wp_enqueue_scripts', array( 'Jetpack_AMP_Support', 'amp_enqueue_sharing_css' ) );
36
37
		// Sharing for Reader mode.
38
		if ( function_exists( 'jetpack_social_menu_include_svg_icons' ) ) {
39
			add_action( 'amp_post_template_footer', 'jetpack_social_menu_include_svg_icons' );
40
		}
41
		add_action( 'amp_post_template_css', array( 'Jetpack_AMP_Support', 'amp_reader_sharing_css' ), 10, 0 );
42
43
		// enforce freedom mode for videopress.
44
		add_filter( 'videopress_shortcode_options', array( 'Jetpack_AMP_Support', 'videopress_enable_freedom_mode' ) );
45
46
		// include Jetpack og tags when rendering native AMP head.
47
		add_action( 'amp_post_template_head', array( 'Jetpack_AMP_Support', 'amp_post_jetpack_og_tags' ) );
48
49
		// Post rendering changes for legacy AMP.
50
		add_action( 'pre_amp_render_post', array( 'Jetpack_AMP_Support', 'amp_disable_the_content_filters' ) );
51
52
		// Disable Comment Likes.
53
		add_filter( 'jetpack_comment_likes_enabled', array( 'Jetpack_AMP_Support', 'comment_likes_enabled' ) );
54
55
		// Transitional mode AMP should not have comment likes.
56
		add_filter( 'the_content', array( 'Jetpack_AMP_Support', 'disable_comment_likes_before_the_content' ) );
57
58
		// Remove the Likes button from the admin bar.
59
		add_filter( 'jetpack_admin_bar_likes_enabled', array( 'Jetpack_AMP_Support', 'disable_likes_admin_bar' ) );
60
61
		// Add post template metadata for legacy AMP.
62
		add_filter( 'amp_post_template_metadata', array( 'Jetpack_AMP_Support', 'amp_post_template_metadata' ), 10, 2 );
63
64
		// Filter photon image args for AMP Stories.
65
		add_filter( 'jetpack_photon_post_image_args', array( 'Jetpack_AMP_Support', 'filter_photon_post_image_args_for_stories' ), 10, 2 );
66
67
		// Sync the amp-options.
68
		add_filter( 'jetpack_options_whitelist', array( 'Jetpack_AMP_Support', 'filter_jetpack_options_safelist' ) );
69
	}
70
71
	/**
72
	 * Disable the Comment Likes feature on AMP views.
73
	 *
74
	 * @param bool $enabled Should comment likes be enabled.
75
	 */
76
	public static function comment_likes_enabled( $enabled ) {
77
		return $enabled && ! self::is_amp_request();
78
	}
79
80
	/**
81
	 * Apply custom AMP changes in wp-admin.
82
	 */
83
	public static function admin_init() {
84
		// disable Likes metabox for post editor if AMP canonical disabled.
85
		add_filter( 'post_flair_disable', array( 'Jetpack_AMP_Support', 'is_amp_canonical' ), 99 );
86
	}
87
88
	/**
89
	 * Is the page in AMP 'canonical mode'.
90
	 * Used when themes register support for AMP with `add_theme_support( 'amp' )`.
91
	 *
92
	 * @return bool is_amp_canonical
93
	 */
94
	public static function is_amp_canonical() {
95
		return function_exists( 'amp_is_canonical' ) && amp_is_canonical();
96
	}
97
98
	/**
99
	 * Does the page return AMP content.
100
	 *
101
	 * @return bool $is_amp_request Are we on am AMP view.
102
	 */
103
	public static function is_amp_request() {
104
		$is_amp_request = ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() );
105
106
		/**
107
		 * Returns true if the current request should return valid AMP content.
108
		 *
109
		 * @since 6.2.0
110
		 *
111
		 * @param boolean $is_amp_request Is this request supposed to return valid AMP content?
112
		 */
113
		return apply_filters( 'jetpack_is_amp_request', $is_amp_request );
114
	}
115
116
	/**
117
	 * Remove content filters added by Jetpack.
118
	 */
119
	public static function amp_disable_the_content_filters() {
120
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
121
			add_filter( 'videopress_show_2015_player', '__return_true' );
122
			add_filter( 'protected_embeds_use_form_post', '__return_false' );
123
			remove_filter( 'the_title', 'widont' );
124
		}
125
126
		remove_filter( 'pre_kses', array( 'Filter_Embedded_HTML_Objects', 'filter' ), 11 );
127
		remove_filter( 'pre_kses', array( 'Filter_Embedded_HTML_Objects', 'maybe_create_links' ), 100 );
128
	}
129
130
	/**
131
	 * Do not add comment likes on AMP requests.
132
	 *
133
	 * @param string $content Post content.
134
	 */
135
	public static function disable_comment_likes_before_the_content( $content ) {
136
		if ( self::is_amp_request() ) {
137
			remove_filter( 'comment_text', 'comment_like_button', 12, 2 );
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 2.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
138
		}
139
		return $content;
140
	}
141
142
	/**
143
	 * Do not display the Likes' Admin bar on AMP requests.
144
	 *
145
	 * @param bool $is_admin_bar_button_visible Should the Like button be visible in the Admin bar. Default to true.
146
	 */
147
	public static function disable_likes_admin_bar( $is_admin_bar_button_visible ) {
148
		if ( self::is_amp_request() ) {
149
			return false;
150
		}
151
		return $is_admin_bar_button_visible;
152
	}
153
154
	/**
155
	 * Add Jetpack stats pixel.
156
	 *
157
	 * @since 6.2.1
158
	 */
159
	public static function add_stats_pixel() {
160
		if ( ! has_action( 'wp_footer', 'stats_footer' ) ) {
161
			return;
162
		}
163
		stats_render_amp_footer( stats_build_view_data() );
164
	}
165
166
	/**
167
	 * Add publisher and image metadata to legacy AMP post.
168
	 *
169
	 * @since 6.2.0
170
	 *
171
	 * @param array   $metadata Metadata array.
172
	 * @param WP_Post $post     Post.
173
	 * @return array Modified metadata array.
174
	 */
175
	public static function amp_post_template_metadata( $metadata, $post ) {
176
		if ( isset( $metadata['publisher'] ) && ! isset( $metadata['publisher']['logo'] ) ) {
177
			$metadata = self::add_site_icon_to_metadata( $metadata );
178
		}
179
180
		if ( ! isset( $metadata['image'] ) && ! empty( $post ) ) {
181
			$metadata = self::add_image_to_metadata( $metadata, $post );
182
		}
183
184
		return $metadata;
185
	}
186
187
	/**
188
	 * Add blavatar to legacy AMP post metadata.
189
	 *
190
	 * @since 6.2.0
191
	 *
192
	 * @param array $metadata Metadata.
193
	 *
194
	 * @return array Metadata.
195
	 */
196
	private static function add_site_icon_to_metadata( $metadata ) {
197
		$size          = 60;
198
		$site_icon_url = class_exists( 'Automattic\\Jetpack\\Sync\\Functions' ) ? Functions::site_icon_url( $size ) : '';
199
200
		if ( function_exists( 'blavatar_domain' ) ) {
201
			$metadata['publisher']['logo'] = array(
202
				'@type'  => 'ImageObject',
203
				'url'    => blavatar_url( blavatar_domain( site_url() ), 'img', $size, self::staticize_subdomain( 'https://wordpress.com/i/favicons/apple-touch-icon-60x60.png' ) ),
204
				'width'  => $size,
205
				'height' => $size,
206
			);
207
		} elseif ( $site_icon_url ) {
208
			$metadata['publisher']['logo'] = array(
209
				'@type'  => 'ImageObject',
210
				'url'    => $site_icon_url,
211
				'width'  => $size,
212
				'height' => $size,
213
			);
214
		}
215
216
		return $metadata;
217
	}
218
219
	/**
220
	 * Add image to legacy AMP post metadata.
221
	 *
222
	 * @since 6.2.0
223
	 *
224
	 * @param array   $metadata Metadata.
225
	 * @param WP_Post $post     Post.
226
	 * @return array Metadata.
227
	 */
228
	private static function add_image_to_metadata( $metadata, $post ) {
229
		$image = Jetpack_PostImages::get_image(
230
			$post->ID,
231
			array(
232
				'fallback_to_avatars' => true,
233
				'avatar_size'         => 200,
234
				// AMP already attempts these.
235
				'from_thumbnail'      => false,
236
				'from_attachment'     => false,
237
			)
238
		);
239
240
		if ( empty( $image ) ) {
241
			return self::add_fallback_image_to_metadata( $metadata );
242
		}
243
244
		if ( ! isset( $image['src_width'] ) ) {
245
			$dimensions = self::extract_image_dimensions_from_getimagesize(
246
				array(
247
					$image['src'] => false,
248
				)
249
			);
250
251
			if ( false !== $dimensions[ $image['src'] ] ) {
252
				$image['src_width']  = $dimensions['width'];
253
				$image['src_height'] = $dimensions['height'];
254
			}
255
		}
256
257
		$metadata['image'] = array(
258
			'@type' => 'ImageObject',
259
			'url'   => $image['src'],
260
		);
261
		if ( isset( $image['src_width'] ) ) {
262
			$metadata['image']['width'] = $image['src_width'];
263
		}
264
		if ( isset( $image['src_width'] ) ) {
265
			$metadata['image']['height'] = $image['src_height'];
266
		}
267
268
		return $metadata;
269
	}
270
271
	/**
272
	 * Add fallback image to legacy AMP post metadata.
273
	 *
274
	 * @since 6.2.0
275
	 *
276
	 * @param array $metadata Metadata.
277
	 * @return array Metadata.
278
	 */
279
	private static function add_fallback_image_to_metadata( $metadata ) {
280
		/** This filter is documented in functions.opengraph.php */
281
		$default_image = apply_filters( 'jetpack_open_graph_image_default', 'https://wordpress.com/i/blank.jpg' );
282
283
		$metadata['image'] = array(
284
			'@type'  => 'ImageObject',
285
			'url'    => self::staticize_subdomain( $default_image ),
286
			'width'  => 200,
287
			'height' => 200,
288
		);
289
290
		return $metadata;
291
	}
292
293
	/**
294
	 * Return static WordPress.com domain to use to load resources from WordPress.com.
295
	 *
296
	 * @param string $domain Asset URL.
297
	 */
298
	private static function staticize_subdomain( $domain ) {
299
		// deal with WPCOM vs Jetpack.
300
		if ( function_exists( 'staticize_subdomain' ) ) {
301
			return staticize_subdomain( $domain );
302
		} else {
303
			return Assets::staticize_subdomain( $domain );
304
		}
305
	}
306
307
	/**
308
	 * Extract image dimensions via wpcom/imagesize, only on WPCOM
309
	 *
310
	 * @since 6.2.0
311
	 *
312
	 * @param array $dimensions Dimensions.
313
	 * @return array Dimensions.
314
	 */
315
	private static function extract_image_dimensions_from_getimagesize( $dimensions ) {
316
		if ( ! ( defined( 'IS_WPCOM' ) && IS_WPCOM && function_exists( 'jetpack_require_lib' ) ) ) {
317
			return $dimensions;
318
		}
319
		jetpack_require_lib( 'wpcom/imagesize' );
320
321
		foreach ( $dimensions as $url => $value ) {
322
			if ( is_array( $value ) ) {
323
				continue;
324
			}
325
			$result = wpcom_getimagesize( $url );
326
			if ( is_array( $result ) ) {
327
				$dimensions[ $url ] = array(
328
					'width'  => $result[0],
329
					'height' => $result[1],
330
				);
331
			}
332
		}
333
334
		return $dimensions;
335
	}
336
337
	/**
338
	 * Display Open Graph Meta tags in AMP views.
339
	 */
340
	public static function amp_post_jetpack_og_tags() {
341
		if ( ! ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
342
			Jetpack::init()->check_open_graph();
343
		}
344
345
		if ( function_exists( 'jetpack_og_tags' ) ) {
346
			jetpack_og_tags();
347
		}
348
	}
349
350
	/**
351
	 * Force Freedom mode in VideoPress.
352
	 *
353
	 * @param array $options Array of VideoPress shortcode options.
354
	 */
355
	public static function videopress_enable_freedom_mode( $options ) {
356
		if ( self::is_amp_request() ) {
357
			$options['freedom'] = true;
358
		}
359
		return $options;
360
	}
361
362
	/**
363
	 * Display custom markup for the sharing buttons when in an AMP view.
364
	 *
365
	 * @param string $markup          Content markup of the Jetpack sharing links.
366
	 * @param array  $sharing_enabled Array of Sharing Services currently enabled.
367
	 */
368
	public static function render_sharing_html( $markup, $sharing_enabled ) {
369
		global $post;
370
371
		if ( empty( $post ) ) {
372
			return '';
373
		}
374
375
		if ( ! self::is_amp_request() ) {
376
			return $markup;
377
		}
378
379
		remove_action( 'wp_footer', 'sharing_add_footer' );
380
		if ( empty( $sharing_enabled ) ) {
381
			return $markup;
382
		}
383
384
		$sharing_links = array();
385
		foreach ( $sharing_enabled['visible'] as $service ) {
386
			$sharing_link = $service->get_amp_display( $post );
387
			if ( ! empty( $sharing_link ) ) {
388
				$sharing_links[] = $sharing_link;
389
			}
390
		}
391
392
		// Replace the existing unordered list with AMP sharing buttons.
393
		$markup = preg_replace( '#<ul>(.+)</ul>#', implode( '', $sharing_links ), $markup );
394
395
		// Remove any lingering share-end list items.
396
		$markup = str_replace( '<li class="share-end"></li>', '', $markup );
397
398
		return $markup;
399
	}
400
401
	/**
402
	 * Tells Jetpack not to enqueue CSS for share buttons.
403
	 *
404
	 * @param  bool $enqueue Whether or not to enqueue.
405
	 * @return bool          Whether or not to enqueue.
406
	 */
407
	public static function amp_disable_sharedaddy_css( $enqueue ) {
408
		if ( self::is_amp_request() ) {
409
			$enqueue = false;
410
		}
411
412
		return $enqueue;
413
	}
414
415
	/**
416
	 * Enqueues the AMP specific sharing styles for the sharing icons.
417
	 */
418
	public static function amp_enqueue_sharing_css() {
419
		if ( self::is_amp_request() ) {
420
			wp_enqueue_style( 'sharedaddy-amp', plugin_dir_url( __DIR__ ) . 'modules/sharedaddy/amp-sharing.css', array( 'social-logos' ), JETPACK__VERSION );
421
		}
422
	}
423
424
	/**
425
	 * For the AMP Reader mode template, include styles that we need.
426
	 */
427
	public static function amp_reader_sharing_css() {
428
		// If sharing is not enabled, we should not proceed to render the CSS.
429
		if ( ! defined( 'JETPACK_SOCIAL_LOGOS_DIR' ) || ! defined( 'WP_SHARING_PLUGIN_DIR' ) ) {
430
			return;
431
		}
432
433
		/*
434
		 * We'll need to output the full contents of the 2 files
435
		 * in the head on AMP views. We can't rely on regular enqueues here.
436
		 *
437
		 * phpcs:disable WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
438
		 * phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
439
		 */
440
		echo file_get_contents( JETPACK_SOCIAL_LOGOS_DIR . 'social-logos.css' );
441
		echo file_get_contents( WP_SHARING_PLUGIN_DIR . 'amp-sharing.css' );
442
443
		/*
444
		 * phpcs:enable WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
445
		 * phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
446
		 */
447
	}
448
449
	/**
450
	 * Ensure proper Photon image dimensions for AMP Stories.
451
	 *
452
	 * @param array $args Array of Photon Arguments.
453
	 * @param array $details {
454
	 *     Array of image details.
455
	 *
456
	 *     @type string    $tag            Image tag (Image HTML output).
457
	 *     @type string    $src            Image URL.
458
	 *     @type string    $src_orig       Original Image URL.
459
	 *     @type int|false $width          Image width.
460
	 *     @type int|false $height         Image height.
461
	 *     @type int|false $width_orig     Original image width before constrained by content_width.
462
	 *     @type int|false $height_orig    Original Image height before constrained by content_width.
463
	 *     @type string    $transform_orig Original transform before constrained by content_width.
464
	 * }
465
	 * @return array Args.
466
	 */
467
	public static function filter_photon_post_image_args_for_stories( $args, $details ) {
468
		if ( ! is_singular( 'amp_story' ) ) {
469
			return $args;
470
		}
471
472
		// Percentage-based dimensions are not allowed in AMP, so this shouldn't happen, but short-circuit just in case.
473
		if ( false !== strpos( $details['width_orig'], '%' ) || false !== strpos( $details['height_orig'], '%' ) ) {
474
			return $args;
475
		}
476
477
		$max_height = 1280; // See image size with the slug \AMP_Story_Post_Type::MAX_IMAGE_SIZE_SLUG.
478
		$transform  = $details['transform_orig'];
479
		$width      = $details['width_orig'];
480
		$height     = $details['height_orig'];
481
482
		// If height is available, constrain to $max_height.
483
		if ( false !== $height ) {
484
			if ( $height > $max_height && false !== $height ) {
485
				$width  = ( $max_height * $width ) / $height;
486
				$height = $max_height;
487
			} elseif ( $height > $max_height ) {
488
				$height = $max_height;
489
			}
490
		}
491
492
		/*
493
		 * Set a height if none is found.
494
		 * If height is set in this manner and height is available, use `fit` instead of `resize` to prevent skewing.
495
		 */
496
		if ( false === $height ) {
497
			$height = $max_height;
498
			if ( false !== $width ) {
499
				$transform = 'fit';
500
			}
501
		}
502
503
		// Build array of Photon args and expose to filter before passing to Photon URL function.
504
		$args = array();
505
506 View Code Duplication
		if ( false !== $width && false !== $height ) {
507
			$args[ $transform ] = $width . ',' . $height;
508
		} elseif ( false !== $width ) {
509
			$args['w'] = $width;
510
		} elseif ( false !== $height ) {
511
			$args['h'] = $height;
512
		}
513
514
		return $args;
515
	}
516
517
	/**
518
	 *  Adds amp-options to the list of options to sync, if AMP is available
519
	 *
520
	 * @param array $options_safelist Safelist of options to sync.
521
	 *
522
	 * @return array Updated options safelist
523
	 */
524
	public static function filter_jetpack_options_safelist( $options_safelist ) {
525
		if ( function_exists( 'is_amp_endpoint' ) ) {
526
			$options_safelist[] = 'amp-options';
527
		}
528
		return $options_safelist;
529
	}
530
}
531
532
add_action( 'init', array( 'Jetpack_AMP_Support', 'init' ), 1 );
533
534
add_action( 'admin_init', array( 'Jetpack_AMP_Support', 'admin_init' ), 1 );
535