Completed
Push — ignore/lazy-images-linting-pac... ( 3c044f...b5c515 )
by Jeremy
367:06 queued 352:42
created

functions.opengraph.php ➔ jetpack_og_get_image()   F

Complexity

Conditions 27
Paths 1620

Size

Total Lines 96

Duplication

Lines 34
Ratio 35.42 %

Importance

Changes 0
Metric Value
cc 27
nc 1620
nop 3
dl 34
loc 96
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Open Graph Tags
4
 *
5
 * Add Open Graph tags so that Facebook (and any other service that supports them)
6
 * can crawl the site better and we provide a better sharing experience.
7
 *
8
 * @link https://ogp.me/
9
 * @link https://developers.facebook.com/docs/opengraph/
10
 *
11
 * @package Jetpack
12
 */
13
14
add_action( 'wp_head', 'jetpack_og_tags' );
15
add_action( 'web_stories_story_head', 'jetpack_og_tags' );
16
17
/**
18
 * Outputs Open Graph tags generated by Jetpack.
19
 */
20
function jetpack_og_tags() {
21
	global $post;
22
	$data = $post; // so that we don't accidentally explode the global.
23
	/**
24
	 * Allow Jetpack to output Open Graph Meta Tags.
25
	 *
26
	 * @module sharedaddy, publicize
27
	 *
28
	 * @since 2.0.0
29
	 * @deprecated 2.0.3 Duplicative filter. Use `jetpack_enable_open_graph`.
30
	 *
31
	 * @param bool true Should Jetpack's Open Graph Meta Tags be enabled. Default to true.
32
	 */
33
	if ( false === apply_filters( 'jetpack_enable_opengraph', true ) ) {
34
		_deprecated_function( 'jetpack_enable_opengraph', '2.0.3', 'jetpack_enable_open_graph' );
35
		return;
36
	}
37
38
	$is_amp_response = ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() );
39
40
	// Disable the widont filter on WP.com to avoid stray &nbsps.
41
	$disable_widont = remove_filter( 'the_title', 'widont' );
42
43
	$og_output = "\n";
44
	if ( ! $is_amp_response ) { // Because AMP optimizes the order or the nodes in the head.
45
		$og_output .= "<!-- Jetpack Open Graph Tags -->\n";
46
	}
47
	$tags = array();
48
49
	/**
50
	 * Filter the minimum width of the images used in Jetpack Open Graph Meta Tags.
51
	 *
52
	 * @module sharedaddy, publicize
53
	 *
54
	 * @since 2.0.0
55
	 *
56
	 * @param int 200 Minimum image width used in Jetpack Open Graph Meta Tags.
57
	 */
58
	$image_width = absint( apply_filters( 'jetpack_open_graph_image_width', 200 ) );
59
	/**
60
	 * Filter the minimum height of the images used in Jetpack Open Graph Meta Tags.
61
	 *
62
	 * @module sharedaddy, publicize
63
	 *
64
	 * @since 2.0.0
65
	 *
66
	 * @param int 200 Minimum image height used in Jetpack Open Graph Meta Tags.
67
	 */
68
	$image_height       = absint( apply_filters( 'jetpack_open_graph_image_height', 200 ) );
69
	$description_length = 197;
70
71
	if ( is_home() || is_front_page() ) {
72
		$site_type              = Jetpack_Options::get_option_and_ensure_autoload( 'open_graph_protocol_site_type', '' );
73
		$tags['og:type']        = ! empty( $site_type ) ? $site_type : 'website';
74
		$tags['og:title']       = get_bloginfo( 'name' );
75
		$tags['og:description'] = get_bloginfo( 'description' );
76
77
		$front_page_id = get_option( 'page_for_posts' );
78
		if ( 'page' === get_option( 'show_on_front' ) && $front_page_id && is_home() ) {
79
			$tags['og:url'] = get_permalink( $front_page_id );
80
		} else {
81
			$tags['og:url'] = home_url( '/' );
82
		}
83
84
		// Associate a blog's root path with one or more Facebook accounts.
85
		$facebook_admins = Jetpack_Options::get_option_and_ensure_autoload( 'facebook_admins', array() );
86
		if ( ! empty( $facebook_admins ) ) {
87
			$tags['fb:admins'] = $facebook_admins;
88
		}
89
	} elseif ( is_author() ) {
90
		$tags['og:type'] = 'profile';
91
92
		$author = get_queried_object();
93
94
		if ( is_a( $author, 'WP_User' ) ) {
95
			$tags['og:title'] = $author->display_name;
96
			if ( ! empty( $author->user_url ) ) {
97
				$tags['og:url'] = $author->user_url;
98
			} else {
99
				$tags['og:url'] = get_author_posts_url( $author->ID );
100
			}
101
			$tags['og:description']     = $author->description;
102
			$tags['profile:first_name'] = get_the_author_meta( 'first_name', $author->ID );
103
			$tags['profile:last_name']  = get_the_author_meta( 'last_name', $author->ID );
104
		}
105
	} elseif ( is_archive() ) {
106
		$tags['og:type']  = 'website';
107
		$tags['og:title'] = wp_get_document_title();
108
109
		$archive = get_queried_object();
110
		if ( ! empty( $archive ) ) {
111
			if ( is_category() || is_tag() || is_tax() ) {
112
				$tags['og:url']         = get_term_link( $archive->term_id, $archive->taxonomy );
113
				$tags['og:description'] = $archive->description;
114
			} elseif ( is_post_type_archive() ) {
115
				$tags['og:url']         = get_post_type_archive_link( $archive->name );
116
				$tags['og:description'] = $archive->description;
117
			}
118
		}
119
	} elseif ( is_singular() && is_a( $data, 'WP_Post' ) ) {
120
		$tags['og:type'] = 'article';
121
		if ( empty( $data->post_title ) ) {
122
			$tags['og:title'] = ' ';
123
		} else {
124
			/** This filter is documented in core/src/wp-includes/post-template.php */
125
			$tags['og:title'] = wp_kses( apply_filters( 'the_title', $data->post_title, $data->ID ), array() );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $data->ID.

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...
126
		}
127
128
		$tags['og:url'] = get_permalink( $data->ID );
129
		if ( ! post_password_required() ) {
130
			/*
131
			 * If the post author set an excerpt, use that.
132
			 * Otherwise, pick the post content that comes before the More tag if there is one.
133
			 */
134
			$excerpt = ! empty( $data->post_excerpt )
135
				? $data->post_excerpt
136
				: explode( '<!--more-->', $data->post_content )[0];
137
138
			$tags['og:description'] = jetpack_og_get_description( $excerpt );
139
		}
140
141
		$tags['article:published_time'] = gmdate( 'c', strtotime( $data->post_date_gmt ) );
142
		$tags['article:modified_time']  = gmdate( 'c', strtotime( $data->post_modified_gmt ) );
143
		if ( post_type_supports( get_post_type( $data ), 'author' ) && isset( $data->post_author ) ) {
144
			$publicize_facebook_user = get_post_meta( $data->ID, '_publicize_facebook_user', true );
145
			if ( ! empty( $publicize_facebook_user ) ) {
146
				$tags['article:author'] = esc_url( $publicize_facebook_user );
147
			}
148
		}
149
	} elseif ( is_search() ) {
150
		if ( '' !== get_query_var( 's', '' ) ) {
151
			$tags['og:title'] = wp_get_document_title();
152
		}
153
	}
154
	/**
155
	 * Allow plugins to inject additional template-specific Open Graph tags.
156
	 *
157
	 * @module sharedaddy, publicize
158
	 *
159
	 * @since 3.0.0
160
	 *
161
	 * @param array $tags Array of Open Graph Meta tags.
162
	 * @param array $args Array of image size parameters.
163
	 */
164
	$tags = apply_filters( 'jetpack_open_graph_base_tags', $tags, compact( 'image_width', 'image_height' ) );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with compact('image_width', 'image_height').

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...
165
166
	// Re-enable widont if we had disabled it.
167
	if ( $disable_widont ) {
168
		add_filter( 'the_title', 'widont' );
169
	}
170
171
	/**
172
	 * Do not return any Open Graph Meta tags if we don't have any info about a post.
173
	 *
174
	 * @module sharedaddy, publicize
175
	 *
176
	 * @since 3.0.0
177
	 *
178
	 * @param bool true Do not return any Open Graph Meta tags if we don't have any info about a post.
179
	 */
180
	if ( empty( $tags ) && apply_filters( 'jetpack_open_graph_return_if_empty', true ) ) {
181
		return;
182
	}
183
184
	$tags['og:site_name'] = get_bloginfo( 'name' );
185
186
	// Get image info and build tags.
187
	if ( ! post_password_required() ) {
188
		$image_info       = jetpack_og_get_image( $image_width, $image_height );
189
		$tags['og:image'] = $image_info['src'];
190
191
		if ( ! empty( $image_info['width'] ) ) {
192
			$tags['og:image:width'] = (int) $image_info['width'];
193
		}
194
		if ( ! empty( $image_info['height'] ) ) {
195
			$tags['og:image:height'] = (int) $image_info['height'];
196
		}
197
		if ( ! empty( $image_info['alt_text'] ) ) {
198
			$tags['og:image:alt'] = esc_attr( $image_info['alt_text'] );
199
		}
200
	}
201
202
	// Facebook whines if you give it an empty title.
203
	if ( empty( $tags['og:title'] ) ) {
204
		$tags['og:title'] = __( '(no title)', 'jetpack' );
205
	}
206
207
	// Shorten the description if it's too long.
208
	if ( isset( $tags['og:description'] ) ) {
209
		$tags['og:description'] = strlen( $tags['og:description'] ) > $description_length ? mb_substr( $tags['og:description'], 0, $description_length ) . '…' : $tags['og:description'];
210
	}
211
212
	// Try to add OG locale tag if the WP->FB data mapping exists.
213
	if ( defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) && file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
214
		require_once JETPACK__GLOTPRESS_LOCALES_PATH;
215
		$_locale = get_locale();
216
217
		// We have to account for w.org vs WP.com locale divergence.
218
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
219
			$gp_locale = GP_Locales::by_field( 'slug', $_locale );
220
		} else {
221
			$gp_locale = GP_Locales::by_field( 'wp_locale', $_locale );
222
		}
223
	}
224
225
	if ( isset( $gp_locale->facebook_locale ) && ! empty( $gp_locale->facebook_locale ) ) {
226
		$tags['og:locale'] = $gp_locale->facebook_locale;
0 ignored issues
show
Bug introduced by
The variable $gp_locale does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
227
	}
228
229
	/**
230
	 * Allow the addition of additional Open Graph Meta tags, or modify the existing tags.
231
	 *
232
	 * @module sharedaddy, publicize
233
	 *
234
	 * @since 2.0.0
235
	 *
236
	 * @param array $tags Array of Open Graph Meta tags.
237
	 * @param array $args Array of image size parameters.
238
	 */
239
	$tags = apply_filters( 'jetpack_open_graph_tags', $tags, compact( 'image_width', 'image_height' ) );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with compact('image_width', 'image_height').

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...
240
241
	// secure_urls need to go right after each og:image to work properly so we will abstract them here.
242
	$tags['og:image:secure_url'] = ( empty( $tags['og:image:secure_url'] ) ) ? '' : $tags['og:image:secure_url'];
243
	$secure                      = $tags['og:image:secure_url'];
244
	unset( $tags['og:image:secure_url'] );
245
	$secure_image_num = 0;
246
247
	foreach ( (array) $tags as $tag_property => $tag_content ) {
248
		// to accommodate multiple images.
249
		$tag_content = (array) $tag_content;
250
		$tag_content = array_unique( $tag_content );
251
252
		foreach ( $tag_content as $tag_content_single ) {
253
			if ( empty( $tag_content_single ) ) {
254
				continue; // Don't ever output empty tags.
255
			}
256
			$og_tag = sprintf( '<meta property="%s" content="%s" />', esc_attr( $tag_property ), esc_attr( $tag_content_single ) );
257
			/**
258
			 * Filter the HTML Output of each Open Graph Meta tag.
259
			 *
260
			 * @module sharedaddy, publicize
261
			 *
262
			 * @since 2.0.0
263
			 *
264
			 * @param string $og_tag HTML HTML Output of each Open Graph Meta tag.
265
			 */
266
			$og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
267
			$og_output .= "\n";
268
269
			if ( 'og:image' === $tag_property ) {
270
				if ( is_array( $secure ) && ! empty( $secure[ $secure_image_num ] ) ) {
271
					$og_tag = sprintf( '<meta property="og:image:secure_url" content="%s" />', esc_url( $secure[ $secure_image_num ] ) );
272
					/** This filter is documented in functions.opengraph.php */
273
					$og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
274
					$og_output .= "\n";
275
				} elseif ( ! is_array( $secure ) && ! empty( $secure ) ) {
276
					$og_tag = sprintf( '<meta property="og:image:secure_url" content="%s" />', esc_url( $secure ) );
277
					/** This filter is documented in functions.opengraph.php */
278
					$og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
279
					$og_output .= "\n";
280
				}
281
				$secure_image_num++;
282
			}
283
		}
284
	}
285
286
	if ( ! $is_amp_response ) { // Because AMP optimizes the order or the nodes in the head.
287
		$og_output .= "\n<!-- End Jetpack Open Graph Tags -->";
288
	}
289
	$og_output .= "\n";
290
	// This is trusted output or added by a filter.
291
	echo $og_output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
292
}
293
294
/**
295
 * Returns an image used in social shares.
296
 *
297
 * @since 2.0.0
298
 *
299
 * @param int  $width Minimum width for the image. Default is 200 based on Facebook's requirement.
300
 * @param int  $height Minimum height for the image. Default is 200 based on Facebook's requirement.
301
 * @param null $deprecated Deprecated.
302
 *
303
 * @return array The source ('src'), 'width', and 'height' of the image.
304
 */
305
function jetpack_og_get_image( $width = 200, $height = 200, $deprecated = null ) {
306
	if ( ! empty( $deprecated ) ) {
307
		_deprecated_argument( __FUNCTION__, '6.6.0' );
308
	}
309
	$image = array();
310
311
	if ( is_singular() && ! is_home() ) {
312
		// Grab obvious image if post is an attachment page for an image.
313
		if ( is_attachment( get_the_ID() ) && 'image' === substr( get_post_mime_type(), 0, 5 ) ) {
314
			$image['src'] = wp_get_attachment_url( get_the_ID() );
315
		}
316
317
		// Attempt to find something good for this post using our generalized PostImages code.
318
		if ( empty( $image ) && class_exists( 'Jetpack_PostImages' ) ) {
319
			$post_image = Jetpack_PostImages::get_image(
320
				get_the_ID(),
321
				array(
322
					'width'  => $width,
323
					'height' => $height,
324
				)
325
			);
326 View Code Duplication
			if ( ! empty( $post_image ) && is_array( $post_image ) ) {
327
				$image['src'] = $post_image['src'];
328
				if ( isset( $post_image['src_width'], $post_image['src_height'] ) ) {
329
					$image['width']  = $post_image['src_width'];
330
					$image['height'] = $post_image['src_height'];
331
				}
332
				if ( ! empty( $post_image['alt_text'] ) ) {
333
					$image['alt_text'] = $post_image['alt_text'];
334
				}
335
			}
336
		}
337
	} elseif ( is_author() ) {
338
		$author = get_queried_object();
339
		if ( is_a( $author, 'WP_User' ) ) {
340
			$image['src'] = get_avatar_url(
341
				$author->user_email,
342
				array(
343
					'size' => $width,
344
				)
345
			);
346
		}
347
	}
348
349
	// First fall back, blavatar.
350
	if ( empty( $image ) && function_exists( 'blavatar_domain' ) ) {
351
		$blavatar_domain = blavatar_domain( site_url() );
352
		if ( blavatar_exists( $blavatar_domain ) ) {
353
			$image['src']    = blavatar_url( $blavatar_domain, 'img', $width, false, true );
354
			$image['width']  = $width;
355
			$image['height'] = $height;
356
		}
357
	}
358
359
	// Second fall back, Site Logo.
360 View Code Duplication
	if ( empty( $image ) && ( function_exists( 'jetpack_has_site_logo' ) && jetpack_has_site_logo() ) ) {
361
		$image_id = jetpack_get_site_logo( 'id' );
362
		$logo     = wp_get_attachment_image_src( $image_id, 'full' );
363
		if (
364
			isset( $logo[0], $logo[1], $logo[2] )
365
			&& ( _jetpack_og_get_image_validate_size( $logo[1], $logo[2], $width, $height ) )
366
		) {
367
			$image['src']    = $logo[0];
368
			$image['width']  = $logo[1];
369
			$image['height'] = $logo[2];
370
		}
371
	}
372
373
	// Third fall back, Core Site Icon, if valid in size.
374 View Code Duplication
	if ( empty( $image ) && has_site_icon() ) {
375
		$image_id = get_option( 'site_icon' );
376
		$icon     = wp_get_attachment_image_src( $image_id, 'full' );
377
		if (
378
			isset( $icon[0], $icon[1], $icon[2] )
379
			&& ( _jetpack_og_get_image_validate_size( $icon[1], $icon[2], $width, $height ) )
380
		) {
381
			$image['src']    = $icon[0];
382
			$image['width']  = $icon[1];
383
			$image['height'] = $icon[2];
384
		}
385
	}
386
387
	// Final fall back, blank image.
388
	if ( empty( $image ) ) {
389
		/**
390
		 * Filter the default Open Graph Image tag, used when no Image can be found in a post.
391
		 *
392
		 * @since 3.0.0
393
		 *
394
		 * @param string $str Default Image URL.
395
		 */
396
		$image['src'] = apply_filters( 'jetpack_open_graph_image_default', 'https://s0.wp.com/i/blank.jpg' );
397
	}
398
399
	return $image;
400
}
401
402
/**
403
 * Validate the width and height against required width and height
404
 *
405
 * @param int $width      Width of the image.
406
 * @param int $height     Height of the image.
407
 * @param int $req_width  Required width to pass validation.
408
 * @param int $req_height Required height to pass validation.
409
 *
410
 * @return bool - True if the image passed the required size validation
411
 */
412
function _jetpack_og_get_image_validate_size( $width, $height, $req_width, $req_height ) {
413
	if ( ! $width || ! $height ) {
414
		return false;
415
	}
416
417
	$valid_width         = ( $width >= $req_width );
418
	$valid_height        = ( $height >= $req_height );
419
	$is_image_acceptable = $valid_width && $valid_height;
420
421
	return $is_image_acceptable;
422
}
423
424
/**
425
 * Gets a gravatar URL of the specified size.
426
 *
427
 * @param string $email E-mail address to get gravatar for.
428
 * @param int    $width Size of returned gravatar.
429
 * @return array|bool|mixed|string
430
 */
431
function jetpack_og_get_image_gravatar( $email, $width ) {
432
	return get_avatar_url(
433
		$email,
434
		array(
435
			'size' => $width,
436
		)
437
	);
438
}
439
440
/**
441
 * Clean up text meant to be used as Description Open Graph tag.
442
 *
443
 * There should be:
444
 * - no links
445
 * - no shortcodes
446
 * - no html tags or their contents
447
 * - not too many words.
448
 *
449
 * @param string       $description Text coming from WordPress (autogenerated or manually generated by author).
450
 * @param WP_Post|null $data        Information about our post.
451
 *
452
 * @return string $description Cleaned up description string.
453
 */
454
function jetpack_og_get_description( $description = '', $data = null ) {
455
	// Remove tags such as <style or <script.
456
	$description = wp_strip_all_tags( $description );
457
458
	/*
459
	 * Clean up any plain text entities left into formatted entities.
460
	 * Intentionally not using a filter to prevent pollution.
461
	 * @see https://github.com/Automattic/jetpack/pull/2899#issuecomment-151957382
462
	 */
463
	$description = wp_kses(
464
		trim(
465
			convert_chars(
466
				wptexturize( $description )
467
			)
468
		),
469
		array()
470
	);
471
472
	// Remove shortcodes.
473
	$description = strip_shortcodes( $description );
474
475
	// Remove links.
476
	$description = preg_replace(
477
		'@https?://[\S]+@',
478
		'',
479
		$description
480
	);
481
482
	/*
483
	 * Limit things to a small text blurb.
484
	 * There isn't a hard limit set by Facebook, so let's rely on WP's own limit.
485
	 * (55 words or the localized equivalent).
486
	 * This limit can be customized with the wp_trim_words filter.
487
	 */
488
	$description = wp_trim_words( $description );
489
490
	// Let's set a default if we have no text by now.
491
	if ( empty( $description ) ) {
492
		/**
493
		 * Filter the fallback `og:description` used when no excerpt information is provided.
494
		 *
495
		 * @module sharedaddy, publicize
496
		 *
497
		 * @since 3.9.0
498
		 *
499
		 * @param string $var  Fallback og:description. Default is translated `Visit the post for more'.
500
		 * @param object $data Post object for the current post.
501
		 */
502
		$description = apply_filters(
503
			'jetpack_open_graph_fallback_description',
504
			__( 'Visit the post for more.', 'jetpack' ),
505
			$data
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $data.

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...
506
		);
507
	}
508
509
	return $description;
510
}
511