Completed
Push — add/double-encode-message ( 8b6530...2d4e84 )
by
unknown
14:26 queued 05:57
created

functions.opengraph.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
 * 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 http://ogp.me/
9
 * @link http://developers.facebook.com/docs/opengraph/
10
 */
11
add_action( 'wp_head', 'jetpack_og_tags' );
12
13
function jetpack_og_tags() {
14
	/**
15
	 * Allow Jetpack to output Open Graph Meta Tags.
16
	 *
17
	 * @module sharedaddy, publicize
18
	 *
19
	 * @since 2.0.0
20
	 * @deprecated 2.0.3 Duplicative filter. Use `jetpack_enable_open_graph`.
21
	 *
22
	 * @param bool true Should Jetpack's Open Graph Meta Tags be enabled. Default to true.
23
	 */
24
	if ( false === apply_filters( 'jetpack_enable_opengraph', true ) ) {
25
		_deprecated_function( 'jetpack_enable_opengraph', '2.0.3', 'jetpack_enable_open_graph' );
26
		return;
27
	}
28
29
	// Disable the widont filter on WP.com to avoid stray &nbsps
30
	$disable_widont = remove_filter( 'the_title', 'widont' );
31
32
	$og_output = "\n<!-- Jetpack Open Graph Tags -->\n";
33
	$tags = array();
34
35
	/**
36
	 * Filter the minimum width of the images used in Jetpack Open Graph Meta Tags.
37
	 *
38
	 * @module sharedaddy, publicize
39
	 *
40
	 * @since 2.0.0
41
	 *
42
	 * @param int 200 Minimum image width used in Jetpack Open Graph Meta Tags.
43
	 */
44
	$image_width        = absint( apply_filters( 'jetpack_open_graph_image_width', 200 ) );
45
	/**
46
	 * Filter the minimum height of the images used in Jetpack Open Graph Meta Tags.
47
	 *
48
	 * @module sharedaddy, publicize
49
	 *
50
	 * @since 2.0.0
51
	 *
52
	 * @param int 200 Minimum image height used in Jetpack Open Graph Meta Tags.
53
	 */
54
	$image_height       = absint( apply_filters( 'jetpack_open_graph_image_height', 200 ) );
55
	$description_length = 197;
56
57
	if ( is_home() || is_front_page() ) {
58
		$site_type              = Jetpack_Options::get_option_and_ensure_autoload( 'open_graph_protocol_site_type', '' );
59
		$tags['og:type']        = ! empty( $site_type ) ? $site_type : 'website';
60
		$tags['og:title']       = get_bloginfo( 'name' );
61
		$tags['og:description'] = get_bloginfo( 'description' );
62
63
		$front_page_id = get_option( 'page_for_posts' );
64
		if ( 'page' == get_option( 'show_on_front' ) && $front_page_id && is_home() )
65
			$tags['og:url'] = get_permalink( $front_page_id );
66
		else
67
			$tags['og:url'] = home_url( '/' );
68
69
		// Associate a blog's root path with one or more Facebook accounts
70
		$facebook_admins = Jetpack_Options::get_option_and_ensure_autoload( 'facebook_admins', array() );
71
		if ( ! empty( $facebook_admins ) )
72
			$tags['fb:admins'] = $facebook_admins;
73
74
	} else if ( is_author() ) {
75
		$tags['og:type'] = 'profile';
76
77
		$author = get_queried_object();
78
79
		$tags['og:title']           = $author->display_name;
80
		if ( ! empty( $author->user_url ) ) {
81
			$tags['og:url']     = $author->user_url;
82
		} else {
83
			$tags['og:url']     = get_author_posts_url( $author->ID );
84
		}
85
		$tags['og:description']     = $author->description;
86
		$tags['profile:first_name'] = get_the_author_meta( 'first_name', $author->ID );
87
		$tags['profile:last_name']  = get_the_author_meta( 'last_name', $author->ID );
88
89
	} else if ( is_singular() ) {
90
		global $post;
91
		$data = $post; // so that we don't accidentally explode the global
92
93
		$tags['og:type'] = 'article';
94
		if ( empty( $data->post_title ) ) {
95
			$tags['og:title'] = ' ';
96
		} else {
97
			/** This filter is documented in core/src/wp-includes/post-template.php */
98
			$tags['og:title'] = wp_kses( apply_filters( 'the_title', $data->post_title, $data->ID ), array() );
99
		}
100
101
		$tags['og:url']         = get_permalink( $data->ID );
102
		if ( ! post_password_required() ) {
103
			if ( ! empty( $data->post_excerpt ) ) {
104
				$tags['og:description'] = preg_replace( '@https?://[\S]+@', '', strip_shortcodes( wp_kses( $data->post_excerpt, array() ) ) );
105
			} else {
106
				$exploded_content_on_more_tag = explode( '<!--more-->', $data->post_content );
107
				$tags['og:description'] = wp_trim_words( preg_replace( '@https?://[\S]+@', '', strip_shortcodes( wp_kses( $exploded_content_on_more_tag[0], array() ) ) ) );
108
			}
109
		}
110
		if ( empty( $tags['og:description'] ) ) {
111
				/**
112
				 * Filter the fallback `og:description` used when no excerpt information is provided.
113
				 *
114
				 * @module sharedaddy, publicize
115
				 *
116
				 * @since 3.9.0
117
				 *
118
				 * @param string $var  Fallback og:description. Default is translated `Visit the post for more'.
119
				 * @param object $data Post object for the current post.
120
				 */
121
			$tags['og:description'] = apply_filters( 'jetpack_open_graph_fallback_description', __( 'Visit the post for more.', 'jetpack' ), $data );
122
		} else {
123
			// Intentionally not using a filter to prevent pollution. @see https://github.com/Automattic/jetpack/pull/2899#issuecomment-151957382
124
			$tags['og:description'] = wp_kses( trim( convert_chars( wptexturize( $tags['og:description'] ) ) ), array() );
125
		}
126
127
		$tags['article:published_time'] = date( 'c', strtotime( $data->post_date_gmt ) );
128
		$tags['article:modified_time'] = date( 'c', strtotime( $data->post_modified_gmt ) );
129
		if ( post_type_supports( get_post_type( $data ), 'author' ) && isset( $data->post_author ) ) {
130
			$publicize_facebook_user = get_post_meta( $data->ID, '_publicize_facebook_user', true );
131
			if ( ! empty( $publicize_facebook_user ) ) {
132
				$tags['article:author'] = esc_url( $publicize_facebook_user );
133
			}
134
		}
135
	}
136
137
	/**
138
	 * Allow plugins to inject additional template-specific Open Graph tags.
139
	 *
140
	 * @module sharedaddy, publicize
141
	 *
142
	 * @since 3.0.0
143
	 *
144
	 * @param array $tags Array of Open Graph Meta tags.
145
	 * @param array $args Array of image size parameters.
146
	 */
147
	$tags = apply_filters( 'jetpack_open_graph_base_tags', $tags, compact( 'image_width', 'image_height' ) );
148
149
	// Re-enable widont if we had disabled it
150
	if ( $disable_widont )
151
		add_filter( 'the_title', 'widont' );
152
153
	/**
154
	 * Do not return any Open Graph Meta tags if we don't have any info about a post.
155
	 *
156
	 * @module sharedaddy, publicize
157
	 *
158
	 * @since 3.0.0
159
	 *
160
	 * @param bool true Do not return any Open Graph Meta tags if we don't have any info about a post.
161
	 */
162
	if ( empty( $tags ) && apply_filters( 'jetpack_open_graph_return_if_empty', true ) )
163
		return;
164
165
	$tags['og:site_name'] = get_bloginfo( 'name' );
166
167
	// Get image info and build tags
168
	if ( ! post_password_required() ) {
169
		$image_info       = jetpack_og_get_image( $image_width, $image_height );
170
		$tags['og:image'] = $image_info['src'];
171
172
		if ( ! empty( $image_info['width'] ) ) {
173
			$tags['og:image:width'] = (int) $image_info['width'];
174
		}
175
		if ( ! empty( $image_info['height'] ) ) {
176
			$tags['og:image:height'] = (int) $image_info['height'];
177
		}
178
		if ( ! empty( $image_info['alt_text'] ) ) {
179
			$tags['og:image:alt'] = esc_attr( $image_info['alt_text'] );
180
		}
181
	}
182
183
	// Facebook whines if you give it an empty title
184
	if ( empty( $tags['og:title'] ) )
185
		$tags['og:title'] = __( '(no title)', 'jetpack' );
186
187
	// Shorten the description if it's too long
188
	if ( isset( $tags['og:description'] ) ) {
189
		$tags['og:description'] = strlen( $tags['og:description'] ) > $description_length ? mb_substr( $tags['og:description'], 0, $description_length ) . '…' : $tags['og:description'];
190
	}
191
192
	// Try to add OG locale tag if the WP->FB data mapping exists
193
	if ( defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) && file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
194
		require_once JETPACK__GLOTPRESS_LOCALES_PATH;
195
		$_locale = get_locale();
196
197
		// We have to account for w.org vs WP.com locale divergence
198
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
199
			$gp_locale = GP_Locales::by_field( 'slug', $_locale );
200
		} else {
201
			$gp_locale = GP_Locales::by_field( 'wp_locale', $_locale );
202
		}
203
	}
204
205
	if ( isset( $gp_locale->facebook_locale ) && ! empty( $gp_locale->facebook_locale ) ) {
206
		$tags['og:locale'] = $gp_locale->facebook_locale;
0 ignored issues
show
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...
207
	}
208
209
	/**
210
	 * Allow the addition of additional Open Graph Meta tags, or modify the existing tags.
211
	 *
212
	 * @module sharedaddy, publicize
213
	 *
214
	 * @since 2.0.0
215
	 *
216
	 * @param array $tags Array of Open Graph Meta tags.
217
	 * @param array $args Array of image size parameters.
218
	 */
219
	$tags = apply_filters( 'jetpack_open_graph_tags', $tags, compact( 'image_width', 'image_height' ) );
220
221
	// secure_urls need to go right after each og:image to work properly so we will abstract them here
222
	$secure = $tags['og:image:secure_url'] = ( empty( $tags['og:image:secure_url'] ) ) ? '' : $tags['og:image:secure_url'];
223
	unset( $tags['og:image:secure_url'] );
224
	$secure_image_num = 0;
225
226
	foreach ( (array) $tags as $tag_property => $tag_content ) {
227
		// to accommodate multiple images
228
		$tag_content = (array) $tag_content;
229
		$tag_content = array_unique( $tag_content );
230
231
		foreach ( $tag_content as $tag_content_single ) {
232
			if ( empty( $tag_content_single ) )
233
				continue; // Don't ever output empty tags
234
			$og_tag = sprintf( '<meta property="%s" content="%s" />', esc_attr( $tag_property ), esc_attr( $tag_content_single ) );
235
			/**
236
			 * Filter the HTML Output of each Open Graph Meta tag.
237
			 *
238
			 * @module sharedaddy, publicize
239
			 *
240
			 * @since 2.0.0
241
			 *
242
			 * @param string $og_tag HTML HTML Output of each Open Graph Meta tag.
243
			 */
244
			$og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
245
			$og_output .= "\n";
246
247
			if ( 'og:image' == $tag_property ) {
248
				if ( is_array( $secure ) && !empty( $secure[$secure_image_num] ) ) {
249
					$og_tag = sprintf( '<meta property="og:image:secure_url" content="%s" />', esc_url( $secure[ $secure_image_num ] ) );
250
					/** This filter is documented in functions.opengraph.php */
251
					$og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
252
					$og_output .= "\n";
253
				} else if ( !is_array( $secure ) && !empty( $secure ) ) {
254
					$og_tag = sprintf( '<meta property="og:image:secure_url" content="%s" />', esc_url( $secure ) );
255
					/** This filter is documented in functions.opengraph.php */
256
					$og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
257
					$og_output .= "\n";
258
				}
259
				$secure_image_num++;
260
			}
261
		}
262
	}
263
	$og_output .= "\n<!-- End Jetpack Open Graph Tags -->\n";
264
	echo $og_output;
265
}
266
267
/**
268
 * Returns an image used in social shares.
269
 *
270
 * @since 2.0.0
271
 *
272
 * @param int  $width Minimum width for the image. Default is 200 based on Facebook's requirement.
273
 * @param int  $height Minimum height for the image. Default is 200 based on Facebook's requirement.
274
 * @param null $deprecated Deprecated.
275
 *
276
 * @return array The source ('src'), 'width', and 'height' of the image.
277
 */
278
function jetpack_og_get_image( $width = 200, $height = 200, $deprecated = null ) {
279
	if ( ! empty( $deprecated ) ) {
280
		_deprecated_argument( __FUNCTION__, '6.6.0' );
281
	}
282
	$image = array();
283
284
	if ( is_singular() && ! is_home() ) {
285
		// Grab obvious image if post is an attachment page for an image
286
		if ( is_attachment( get_the_ID() ) && 'image' === substr( get_post_mime_type(), 0, 5 ) ) {
287
			$image['src'] = wp_get_attachment_url( get_the_ID() );
288
		}
289
290
		// Attempt to find something good for this post using our generalized PostImages code
291
		if ( empty( $image ) && class_exists( 'Jetpack_PostImages' ) ) {
292
			$post_images = Jetpack_PostImages::get_images( get_the_ID(), array( 'width' => $width, 'height' => $height ) );
293
			if ( $post_images && ! is_wp_error( $post_images ) ) {
294
				foreach ( (array) $post_images as $post_image ) {
295
					$image['src'] = $post_image['src'];
296 View Code Duplication
					if ( isset( $post_image['src_width'], $post_image['src_height'] ) ) {
297
						$image['width']  = $post_image['src_width'];
298
						$image['height'] = $post_image['src_height'];
299
					}
300
					if ( ! empty( $post_image['alt_text'] ) ) {
301
						$image['alt_text'] = $post_image['alt_text'];
302
					}
303
				}
304
			}
305
		}
306
	} elseif ( is_author() ) {
307
		$author       = get_queried_object();
308
		$image['src'] = get_avatar_url( $author->user_email, array(
309
			'size' => $width,
310
		) );
311
	}
312
313
	// First fall back, blavatar.
314
	if ( empty( $image ) && function_exists( 'blavatar_domain' ) ) {
315
		$blavatar_domain = blavatar_domain( site_url() );
316
		if ( blavatar_exists( $blavatar_domain ) ) {
317
			$image['src']    = blavatar_url( $blavatar_domain, 'img', $width, false, true );
318
			$image['width']  = $width;
319
			$image['height'] = $height;
320
		}
321
	}
322
323
	// Second fall back, Site Logo.
324 View Code Duplication
	if ( empty( $image ) && ( function_exists( 'jetpack_has_site_logo' ) && jetpack_has_site_logo() ) ) {
325
		$image_id = jetpack_get_site_logo( 'id' );
326
		$logo     = wp_get_attachment_image_src( $image_id, 'full' );
327
		if (
328
			isset( $logo[0], $logo[1], $logo[2] )
329
			&& ( _jetpack_og_get_image_validate_size( $logo[1], $logo[2], $width, $height ) )
330
		) {
331
			$image['src']    = $logo[0];
332
			$image['width']  = $logo[1];
333
			$image['height'] = $logo[2];
334
		}
335
	}
336
337
	// Third fall back, Core Site Icon, if valid in size. Added in WP 4.3.
338 View Code Duplication
	if ( empty( $image ) && ( function_exists( 'has_site_icon' ) && has_site_icon() ) ) {
339
		$image_id = get_option( 'site_icon' );
340
		$icon     = wp_get_attachment_image_src( $image_id, 'full' );
341
		if (
342
			isset( $icon[0], $icon[1], $icon[2] )
343
			&& ( _jetpack_og_get_image_validate_size( $icon[1], $icon[2], $width, $height ) )
344
		) {
345
			$image['src']    = $icon[0];
346
			$image['width']  = $icon[1];
347
			$image['height'] = $icon[2];
348
		}
349
	}
350
351
	// Final fall back, blank image.
352
	if ( empty( $image ) ) {
353
		/**
354
		 * Filter the default Open Graph Image tag, used when no Image can be found in a post.
355
		 *
356
		 * @since 3.0.0
357
		 *
358
		 * @param string $str Default Image URL.
359
		 */
360
		$image['src'] = apply_filters( 'jetpack_open_graph_image_default', 'https://s0.wp.com/i/blank.jpg' );
361
	}
362
363
	return $image;
364
}
365
366
367
/**
368
 * Validate the width and height against required width and height
369
 *
370
 * @param int $width      Width of the image.
371
 * @param int $height     Height of the image.
372
 * @param int $req_width  Required width to pass validation.
373
 * @param int $req_height Required height to pass validation.
374
 *
375
 * @return bool - True if the image passed the required size validation
376
 */
377
function _jetpack_og_get_image_validate_size( $width, $height, $req_width, $req_height ) {
378
	if ( ! $width || ! $height ) {
379
		return false;
380
	}
381
382
	$valid_width = ( $width >= $req_width );
383
	$valid_height = ( $height >= $req_height );
384
	$is_image_acceptable = $valid_width && $valid_height;
385
386
	return $is_image_acceptable;
387
}
388
389
/**
390
 * Gets a gravatar URL of the specified size.
391
 *
392
 * @param string $email E-mail address to get gravatar for.
393
 * @param int    $width Size of returned gravatar.
394
 * @return array|bool|mixed|string
395
 */
396
function jetpack_og_get_image_gravatar( $email, $width ) {
397
	return get_avatar_url( $email, array(
398
		'size' => $width,
399
	) );
400
}
401