PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 15.4.1
Jetpack – WP Security, Backup, Speed, & Growth v15.4.1
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / class.jetpack-twitter-cards.php
jetpack Last commit date
3rd-party 8 months ago _inc 21 hours ago css 9 months ago extensions 7 months ago images 9 months ago jetpack_vendor 21 hours ago json-endpoints 8 months ago modules 8 months ago sal 8 months ago src 8 months ago vendor 7 months ago views 9 months ago CHANGELOG.md 7 months ago LICENSE.txt 8 months ago SECURITY.md 2 years ago class-jetpack-connection-status.php 2 years ago class-jetpack-gallery-settings.php 9 months ago class-jetpack-newsletter-dashboard-widget.php 9 months ago class-jetpack-pre-connection-jitms.php 2 years ago class-jetpack-stats-dashboard-widget.php 9 months ago class-jetpack-xmlrpc-methods.php 9 months ago class.frame-nonce-preview.php 9 months ago class.jetpack-admin.php 9 months ago class.jetpack-autoupdate.php 9 months ago class.jetpack-cli.php 8 months ago class.jetpack-client-server.php 2 years ago class.jetpack-gutenberg.php 9 months ago class.jetpack-heartbeat.php 2 years ago class.jetpack-modules-list-table.php 9 months ago class.jetpack-network-sites-list-table.php 9 months ago class.jetpack-network.php 9 months ago class.jetpack-plan.php 3 years ago class.jetpack-post-images.php 9 months ago class.jetpack-twitter-cards.php 9 months ago class.jetpack-user-agent.php 2 years ago class.jetpack.php 8 months ago class.json-api-endpoints.php 7 months ago class.json-api.php 8 months ago class.photon.php 3 years ago composer.json 7 months ago enhanced-open-graph.php 8 months ago functions.compat.php 9 months ago functions.cookies.php 2 years ago functions.global.php 9 months ago functions.is-mobile.php 2 years ago functions.opengraph.php 9 months ago functions.photon.php 2 years ago jetpack.php 21 hours ago json-api-config.php 3 years ago json-endpoints.php 2 years ago load-jetpack.php 9 months ago locales.php 9 months ago readme.txt 21 hours ago unauth-file-upload.php 8 months ago uninstall.php 9 months ago wpml-config.xml 4 years ago
class.jetpack-twitter-cards.php
353 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Jetpack Twitter Card handling.
4 *
5 * @package automattic/jetpack
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit( 0 );
10 }
11
12 /**
13 * Twitter Cards
14 *
15 * Hooks onto the Open Graph protocol and extends it by adding only the tags
16 * we need for twitter cards.
17 *
18 * @see /wp-content/blog-plugins/open-graph.php
19 * @see https://dev.twitter.com/cards/overview
20 */
21 class Jetpack_Twitter_Cards {
22
23 /**
24 * Adds Twitter Card tags.
25 *
26 * @param array $og_tags Existing OG tags.
27 *
28 * @return array OG tags inclusive of Twitter Card output.
29 */
30 public static function twitter_cards_tags( $og_tags ) {
31 global $post;
32 $post_id = ( $post instanceof WP_Post ) ? $post->ID : null;
33
34 /**
35 * Maximum alt text length.
36 *
37 * @see https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary-card-with-large-image.html
38 */
39 $alt_length = 420;
40
41 if ( post_password_required() ) {
42 return $og_tags;
43 }
44
45 /** This action is documented in class.jetpack.php */
46 if ( apply_filters( 'jetpack_disable_twitter_cards', false ) ) {
47 return $og_tags;
48 }
49
50 /*
51 * These tags apply to any page (home, archives, etc).
52 */
53
54 // If we have information on the author/creator, then include that as well.
55 if ( ! empty( $post ) && ! empty( $post->post_author ) ) {
56 /** This action is documented in modules/sharedaddy/sharing-sources.php */
57 $handle = apply_filters( 'jetpack_sharing_twitter_via', '', $post_id );
58 if ( ! empty( $handle ) && ! self::is_default_site_tag( $handle ) ) {
59 $og_tags['twitter:creator'] = self::sanitize_twitter_user( $handle );
60 }
61 }
62
63 $site_tag = self::site_tag();
64 /** This action is documented in modules/sharedaddy/sharing-sources.php */
65 $site_tag = apply_filters( 'jetpack_sharing_twitter_via', $site_tag, ( is_singular() ? $post_id : null ) );
66 /** This action is documented in modules/sharedaddy/sharing-sources.php */
67 $site_tag = apply_filters( 'jetpack_twitter_cards_site_tag', $site_tag, $og_tags );
68 if ( ! empty( $site_tag ) ) {
69 $og_tags['twitter:site'] = self::sanitize_twitter_user( $site_tag );
70 }
71
72 if ( ! is_singular() || ! empty( $og_tags['twitter:card'] ) ) {
73 /**
74 * Filter the default Twitter card image, used when no image can be found in a post.
75 *
76 * @module sharedaddy
77 *
78 * @since 5.9.0
79 *
80 * @param string $str Default image URL.
81 */
82 $image = apply_filters( 'jetpack_twitter_cards_image_default', '' );
83 if ( ! empty( $image ) ) {
84 $og_tags['twitter:image'] = $image;
85 }
86
87 return $og_tags;
88 }
89
90 $the_title = get_the_title();
91 if ( ! $the_title ) {
92 $the_title = get_bloginfo( 'name' );
93 }
94 $og_tags['twitter:text:title'] = $the_title;
95
96 /*
97 * The following tags only apply to single pages.
98 */
99
100 $card_type = 'summary';
101
102 // Try to give priority to featured images.
103 if ( class_exists( 'Jetpack_PostImages' ) && ! empty( $post_id ) ) {
104 $post_image = Jetpack_PostImages::get_image(
105 $post_id,
106 array(
107 'width' => 144,
108 'height' => 144,
109 )
110 );
111 if ( ! empty( $post_image ) && is_array( $post_image ) ) {
112 // 4096 is the maximum size for an image per https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary .
113 if (
114 isset( $post_image['src_width'] ) && isset( $post_image['src_height'] )
115 && (int) $post_image['src_width'] <= 4096
116 && (int) $post_image['src_height'] <= 4096
117 ) {
118 // 300x157 is the minimum size for a summary_large_image per https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary-card-with-large-image .
119 if ( (int) $post_image['src_width'] >= 300 && (int) $post_image['src_height'] >= 157 ) {
120 $card_type = 'summary_large_image';
121 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 640, $post_image['src'] ) );
122 } else {
123 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 144, $post_image['src'] ) );
124 }
125
126 // Add the alt tag if we have one.
127 if ( ! empty( $post_image['alt_text'] ) ) {
128 // Shorten it if it is too long.
129 if ( strlen( $post_image['alt_text'] ) > $alt_length ) {
130 $og_tags['twitter:image:alt'] = esc_attr( mb_substr( $post_image['alt_text'], 0, $alt_length ) . '' );
131 } else {
132 $og_tags['twitter:image:alt'] = esc_attr( $post_image['alt_text'] );
133 }
134 }
135 }
136 }
137 }
138
139 // Only proceed with media analysis if a featured image has not superseded it already.
140 if ( empty( $og_tags['twitter:image'] ) && empty( $og_tags['twitter:image:src'] ) ) {
141 if ( ! class_exists( 'Jetpack_Media_Summary' ) ) {
142 require_once JETPACK__PLUGIN_DIR . '_inc/lib/class.media-summary.php';
143 }
144
145 // Test again, class should already be auto-loaded in Jetpack.
146 // If not, skip extra media analysis and stick with a summary card.
147 if ( class_exists( 'Jetpack_Media_Summary' ) && ! empty( $post_id ) ) {
148 $extract = Jetpack_Media_Summary::get( $post_id );
149
150 if ( 'gallery' === $extract['type'] ) {
151 list( $og_tags, $card_type ) = self::twitter_cards_define_type_based_on_image_count( $og_tags, $extract );
152 } elseif ( 'video' === $extract['type'] ) {
153 // Leave as summary, but with large pict of poster frame (we know those comply to Twitter's size requirements).
154 $card_type = 'summary_large_image';
155 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 640, $extract['image'] ) );
156 } else {
157 list( $og_tags, $card_type ) = self::twitter_cards_define_type_based_on_image_count( $og_tags, $extract );
158 }
159 }
160 }
161
162 $og_tags['twitter:card'] = $card_type;
163
164 // Make sure we have a description for Twitter, their validator isn't happy without some content (single space not valid).
165 if ( ! isset( $og_tags['og:description'] ) || '' === trim( $og_tags['og:description'] ) || __( 'Visit the post for more.', 'jetpack' ) === $og_tags['og:description'] ) { // empty( trim( $og_tags['og:description'] ) ) isn't valid php.
166 $has_creator = ( ! empty( $og_tags['twitter:creator'] ) && '@wordpressdotcom' !== $og_tags['twitter:creator'] ) ? true : false;
167 if ( ! empty( $extract ) && 'video' === $extract['type'] ) { // use $extract['type'] since $card_type is 'summary' for video posts.
168 /* translators: %s is the post author */
169 $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __( 'Video post by %s.', 'jetpack' ), $og_tags['twitter:creator'] ) : __( 'Video post.', 'jetpack' );
170 } else {
171 /* translators: %s is the post author */
172 $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __( 'Post by %s.', 'jetpack' ), $og_tags['twitter:creator'] ) : __( 'Visit the post for more.', 'jetpack' );
173 }
174 }
175
176 if ( empty( $og_tags['twitter:image'] ) && empty( $og_tags['twitter:image:src'] ) ) {
177 /** This action is documented in class.jetpack-twitter-cards.php */
178 $image = apply_filters( 'jetpack_twitter_cards_image_default', '' );
179 if ( ! empty( $image ) ) {
180 $og_tags['twitter:image'] = $image;
181 }
182 }
183
184 return $og_tags;
185 }
186
187 /**
188 * Sanitize the Twitter user by normalizing the @.
189 *
190 * @param string $str Twitter user value.
191 *
192 * @return string Twitter user value.
193 */
194 public static function sanitize_twitter_user( $str ) {
195 return '@' . preg_replace( '/^@/', '', $str );
196 }
197
198 /**
199 * Determines if a site tag is one of the default WP.com/Jetpack ones.
200 *
201 * @param string $site_tag Site tag.
202 *
203 * @return bool True if the default site tag is being used.
204 */
205 public static function is_default_site_tag( $site_tag ) {
206 return in_array( $site_tag, array( '@wordpressdotcom', '@jetpack', 'wordpressdotcom', 'jetpack' ), true );
207 }
208
209 /**
210 * Give priority to the creator tag if using the default site tag.
211 *
212 * @param string $site_tag Site tag.
213 * @param array $og_tags OG tags.
214 *
215 * @return string Site tag.
216 */
217 public static function prioritize_creator_over_default_site( $site_tag, $og_tags = array() ) {
218 if ( ! empty( $og_tags['twitter:creator'] ) && self::is_default_site_tag( $site_tag ) ) {
219 return $og_tags['twitter:creator'];
220 }
221 return $site_tag;
222 }
223
224 /**
225 * Define the Twitter Card type based on image count.
226 *
227 * @param array $og_tags Existing OG tags.
228 * @param array $extract Result of the Image Extractor class.
229 *
230 * @return array
231 */
232 public static function twitter_cards_define_type_based_on_image_count( $og_tags, $extract ) {
233 $card_type = 'summary';
234 $img_count = $extract['count']['image'];
235
236 if ( empty( $img_count ) ) {
237
238 // No images, use Blavatar as a thumbnail for the summary type.
239 if ( function_exists( 'blavatar_domain' ) ) {
240 $blavatar_domain = blavatar_domain( site_url() );
241 if ( blavatar_exists( $blavatar_domain ) ) {
242 $og_tags['twitter:image'] = blavatar_url( $blavatar_domain, 'img', 240 );
243 }
244 }
245
246 // Second fall back, Site Logo.
247 if ( empty( $og_tags['twitter:image'] ) && ( function_exists( 'jetpack_has_site_logo' ) && jetpack_has_site_logo() ) ) {
248 $og_tags['twitter:image'] = jetpack_get_site_logo( 'url' );
249 }
250
251 // Third fall back, Site Icon.
252 if ( empty( $og_tags['twitter:image'] ) && has_site_icon() ) {
253 $og_tags['twitter:image'] = get_site_icon_url( '240' );
254 }
255
256 // Not falling back on Gravatar, because there's no way to know if we end up with an auto-generated one.
257
258 } elseif ( 'image' === $extract['type'] || 'gallery' === $extract['type'] ) {
259 // Test for $extract['type'] to limit to image and gallery, so we don't send a potential fallback image like a Gravatar as a photo post.
260 $card_type = 'summary_large_image';
261 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 1400, ( empty( $extract['images'] ) ) ? $extract['image'] : $extract['images'][0]['url'] ) );
262 }
263
264 return array( $og_tags, $card_type );
265 }
266
267 /**
268 * Updates the Twitter Card output.
269 *
270 * @param string $og_tag A single OG tag.
271 *
272 * @return string Result of the OG tag.
273 */
274 public static function twitter_cards_output( $og_tag ) {
275 return ( str_contains( $og_tag, 'twitter:' ) ) ? preg_replace( '/property="([^"]+)"/', 'name="\1"', $og_tag ) : $og_tag;
276 }
277
278 /**
279 * Adds settings section and field.
280 */
281 public static function settings_init() {
282 add_settings_section( 'jetpack-twitter-cards-settings', 'Twitter Cards', '__return_false', 'sharing' );
283 add_settings_field(
284 'jetpack-twitter-cards-site-tag',
285 __( 'Twitter Site Tag', 'jetpack' ),
286 array( __CLASS__, 'settings_field' ),
287 'sharing',
288 'jetpack-twitter-cards-settings',
289 array(
290 'label_for' => 'jetpack-twitter-cards-site-tag',
291 )
292 );
293 }
294
295 /**
296 * Add global sharing options.
297 */
298 public static function sharing_global_options() {
299 do_settings_fields( 'sharing', 'jetpack-twitter-cards-settings' );
300 }
301
302 /**
303 * Get the Twitter Via tag.
304 *
305 * @return string Twitter via tag.
306 */
307 public static function site_tag() {
308 $site_tag = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ?
309 trim( get_option( 'twitter_via' ) ) :
310 Jetpack_Options::get_option_and_ensure_autoload( 'jetpack-twitter-cards-site-tag', '' );
311 if ( empty( $site_tag ) ) {
312 /** This action is documented in modules/sharedaddy/sharing-sources.php */
313 return apply_filters( 'jetpack_sharing_twitter_via', '', null );
314 }
315 return $site_tag;
316 }
317
318 /**
319 * Output the settings field.
320 */
321 public static function settings_field() {
322 wp_nonce_field( 'jetpack-twitter-cards-settings', 'jetpack_twitter_cards_nonce', false );
323 ?>
324 <input type="text" id="jetpack-twitter-cards-site-tag" class="regular-text" name="jetpack-twitter-cards-site-tag" value="<?php echo esc_attr( get_option( 'jetpack-twitter-cards-site-tag' ) ); ?>" />
325 <p class="description" style="width: auto;"><?php esc_html_e( 'The Twitter username of the owner of this site\'s domain.', 'jetpack' ); ?></p>
326 <?php
327 }
328
329 /**
330 * Validate the settings submission.
331 */
332 public static function settings_validate() {
333 if ( isset( $_POST['jetpack_twitter_cards_nonce'] ) && wp_verify_nonce( $_POST['jetpack_twitter_cards_nonce'], 'jetpack-twitter-cards-settings' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
334 update_option( 'jetpack-twitter-cards-site-tag', isset( $_POST['jetpack-twitter-cards-site-tag'] ) ? trim( ltrim( wp_strip_all_tags( filter_var( wp_unslash( $_POST['jetpack-twitter-cards-site-tag'] ) ) ), '@' ) ) : '' );
335 }
336 }
337
338 /**
339 * Initiates the class.
340 */
341 public static function init() {
342 add_filter( 'jetpack_open_graph_tags', array( __CLASS__, 'twitter_cards_tags' ), 11 ); // $priority=11: this should hook into jetpack_open_graph_tags after 'class.jetpack-seo.php' has done so.
343 add_filter( 'jetpack_open_graph_output', array( __CLASS__, 'twitter_cards_output' ) );
344 add_filter( 'jetpack_twitter_cards_site_tag', array( __CLASS__, 'site_tag' ), -99 );
345 add_filter( 'jetpack_twitter_cards_site_tag', array( __CLASS__, 'prioritize_creator_over_default_site' ), 99, 2 );
346 add_action( 'admin_init', array( __CLASS__, 'settings_init' ) );
347 add_action( 'sharing_global_options', array( __CLASS__, 'sharing_global_options' ) );
348 add_action( 'sharing_admin_update', array( __CLASS__, 'settings_validate' ) );
349 }
350 }
351
352 Jetpack_Twitter_Cards::init();
353