PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 7.2.1
Jetpack – WP Security, Backup, Speed, & Growth v7.2.1
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 7 years ago _inc 7 years ago bin 7 years ago css 7 years ago extensions 7 years ago images 7 years ago json-endpoints 7 years ago languages 7 years ago logs 9 years ago modules 7 years ago sal 7 years ago scss 7 years ago sync 7 years ago views 7 years ago .svnignore 12 years ago CODE-OF-CONDUCT.md 9 years ago changelog.txt 7 years ago class.frame-nonce-preview.php 9 years ago class.jetpack-admin.php 7 years ago class.jetpack-affiliate.php 7 years ago class.jetpack-autoupdate.php 8 years ago class.jetpack-bbpress-json-api-compat.php 9 years ago class.jetpack-cli.php 7 years ago class.jetpack-client-server.php 8 years ago class.jetpack-client.php 7 years ago class.jetpack-connection-banner.php 7 years ago class.jetpack-constants.php 8 years ago class.jetpack-data.php 7 years ago class.jetpack-debugger.php 7 years ago class.jetpack-error.php 10 years ago class.jetpack-gutenberg.php 7 years ago class.jetpack-heartbeat.php 7 years ago class.jetpack-idc.php 8 years ago class.jetpack-ixr-client.php 10 years ago class.jetpack-jitm.php 7 years ago class.jetpack-modules-list-table.php 7 years ago class.jetpack-network-sites-list-table.php 9 years ago class.jetpack-network.php 7 years ago class.jetpack-options.php 7 years ago class.jetpack-plan.php 7 years ago class.jetpack-post-images.php 7 years ago class.jetpack-signature.php 7 years ago class.jetpack-tracks.php 7 years ago class.jetpack-twitter-cards.php 7 years ago class.jetpack-user-agent.php 8 years ago class.jetpack-xmlrpc-server.php 7 years ago class.jetpack.php 7 years ago class.json-api-endpoints.php 7 years ago class.json-api.php 7 years ago class.photon.php 7 years ago composer.json 7 years ago functions.compat.php 7 years ago functions.gallery.php 8 years ago functions.global.php 7 years ago functions.opengraph.php 7 years ago functions.photon.php 7 years ago jetpack.php 7 years ago json-api-config.php 10 years ago json-endpoints.php 7 years ago locales.php 7 years ago readme.txt 7 years ago require-lib.php 7 years ago uninstall.php 8 years ago wpml-config.xml 10 years ago
class.jetpack-twitter-cards.php
271 lines
1 <?php
2
3 /* Twitter Cards
4 *
5 * Hooks onto the Open Graph protocol and extends it by adding only the tags
6 * we need for twitter cards.
7 *
8 * @see /wp-content/blog-plugins/open-graph.php
9 * @see https://dev.twitter.com/cards/overview
10 */
11 class Jetpack_Twitter_Cards {
12
13 static function twitter_cards_tags( $og_tags ) {
14 global $post;
15
16 /**
17 * Maximum alt text length.
18 *
19 * @see https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary-card-with-large-image.html
20 */
21 $alt_length = 420;
22
23 if ( post_password_required() ) {
24 return $og_tags;
25 }
26
27 /** This action is documented in class.jetpack.php */
28 if ( apply_filters( 'jetpack_disable_twitter_cards', false ) ) {
29 return $og_tags;
30 }
31
32 /*
33 * These tags apply to any page (home, archives, etc)
34 */
35
36 // If we have information on the author/creator, then include that as well
37 if ( ! empty( $post ) && ! empty( $post->post_author ) ) {
38 /** This action is documented in modules/sharedaddy/sharing-sources.php */
39 $handle = apply_filters( 'jetpack_sharing_twitter_via', '', $post->ID );
40 if ( ! empty( $handle ) && ! self::is_default_site_tag( $handle ) ) {
41 $og_tags['twitter:creator'] = self::sanitize_twitter_user( $handle );
42 }
43 }
44
45 $site_tag = self::site_tag();
46 /** This action is documented in modules/sharedaddy/sharing-sources.php */
47 $site_tag = apply_filters( 'jetpack_sharing_twitter_via', $site_tag, ( is_singular() ? $post->ID : null ) );
48 /** This action is documented in modules/sharedaddy/sharing-sources.php */
49 $site_tag = apply_filters( 'jetpack_twitter_cards_site_tag', $site_tag, $og_tags );
50 if ( ! empty( $site_tag ) ) {
51 $og_tags['twitter:site'] = self::sanitize_twitter_user( $site_tag );
52 }
53
54 if ( ! is_singular() || ! empty( $og_tags['twitter:card'] ) ) {
55 /**
56 * Filter the default Twitter card image, used when no image can be found in a post.
57 *
58 * @module sharedaddy, publicize
59 *
60 * @since 5.9.0
61 *
62 * @param string $str Default image URL.
63 */
64 $image = apply_filters( 'jetpack_twitter_cards_image_default', '' );
65 if ( ! empty( $image ) ) {
66 $og_tags['twitter:image'] = $image;
67 }
68
69 return $og_tags;
70 }
71
72 $the_title = get_the_title();
73 if ( ! $the_title ) {
74 $the_title = get_bloginfo( 'name' );
75 }
76 $og_tags['twitter:text:title'] = $the_title;
77
78 /*
79 * The following tags only apply to single pages.
80 */
81
82 $card_type = 'summary';
83
84 // Try to give priority to featured images
85 if ( class_exists('Jetpack_PostImages') ) {
86 $featured = Jetpack_PostImages::from_thumbnail( $post->ID, 240, 240 );
87 if ( !empty( $featured ) && count( $featured ) > 0 ) {
88 if ( (int) $featured[0]['src_width'] >= 280 && (int) $featured[0]['src_height'] >= 150 ) {
89 $card_type = 'summary_large_image';
90 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 640, $featured[0]['src'] ) );
91 } else {
92 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 240, $featured[0]['src'] ) );
93 }
94
95 // Add the alt tag if we have one.
96 if ( ! empty( $featured[0]['alt_text'] ) ) {
97 // Shorten it if it is too long.
98 if ( strlen( $featured[0]['alt_text'] ) > $alt_length ) {
99 $og_tags['twitter:image:alt'] = esc_attr( mb_substr( $featured[0]['alt_text'], 0, $alt_length ) . '' );
100 } else {
101 $og_tags['twitter:image:alt'] = esc_attr( $featured[0]['alt_text'] );
102 }
103 }
104 }
105 }
106
107 // Only proceed with media analysis if a featured image has not superseded it already.
108 if ( empty( $og_tags['twitter:image'] ) && empty( $og_tags['twitter:image:src'] ) ) {
109 if ( ! class_exists( 'Jetpack_Media_Summary' ) && defined('IS_WPCOM') && IS_WPCOM ) {
110 include( WP_CONTENT_DIR . '/lib/class.wpcom-media-summary.php' );
111 }
112
113 if ( ! class_exists( 'Jetpack_Media_Summary' ) ) {
114 jetpack_require_lib( 'class.media-summary' );
115 }
116
117 // Test again, class should already be auto-loaded in Jetpack.
118 // If not, skip extra media analysis and stick with a summary card
119 if ( class_exists( 'Jetpack_Media_Summary' ) ) {
120 $extract = Jetpack_Media_Summary::get( $post->ID );
121
122 if ( 'gallery' == $extract['type'] ) {
123 list( $og_tags, $card_type ) = self::twitter_cards_define_type_based_on_image_count( $og_tags, $extract );
124 } elseif ( 'video' == $extract['type'] ) {
125 // Leave as summary, but with large pict of poster frame (we know those comply to Twitter's size requirements)
126 $card_type = 'summary_large_image';
127 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 640, $extract['image'] ) );
128 } else {
129 list( $og_tags, $card_type ) = self::twitter_cards_define_type_based_on_image_count( $og_tags, $extract );
130 }
131 }
132 }
133
134 $og_tags['twitter:card'] = $card_type;
135
136 // Make sure we have a description for Twitter, their validator isn't happy without some content (single space not valid).
137 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
138 $has_creator = ( ! empty($og_tags['twitter:creator']) && '@wordpressdotcom' != $og_tags['twitter:creator'] ) ? true : false;
139 if ( ! empty( $extract ) && 'video' == $extract['type'] ) { // use $extract['type'] since $card_type is 'summary' for video posts
140 /* translators: %s is the post author */
141 $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __( 'Video post by %s.', 'jetpack' ), $og_tags['twitter:creator'] ) : __( 'Video post.', 'jetpack' );
142 } else {
143 /* translators: %s is the post author */
144 $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __( 'Post by %s.', 'jetpack' ), $og_tags['twitter:creator'] ) : __( 'Visit the post for more.', 'jetpack');
145 }
146 }
147
148 if ( empty( $og_tags['twitter:image'] ) && empty( $og_tags['twitter:image:src'] ) ) {
149 /** This action is documented in class.jetpack-twitter-cards.php */
150 $image = apply_filters( 'jetpack_twitter_cards_image_default', '' );
151 if ( ! empty( $image ) ) {
152 $og_tags['twitter:image'] = $image;
153 }
154 }
155
156 return $og_tags;
157 }
158
159 static function sanitize_twitter_user( $str ) {
160 return '@' . preg_replace( '/^@/', '', $str );
161 }
162
163 static function is_default_site_tag( $site_tag ) {
164 return in_array( $site_tag, array( '@wordpressdotcom', '@jetpack', 'wordpressdotcom', 'jetpack' ) );
165 }
166
167 static function prioritize_creator_over_default_site( $site_tag, $og_tags = array() ) {
168 if ( ! empty( $og_tags['twitter:creator'] ) && self::is_default_site_tag( $site_tag ) ) {
169 return $og_tags['twitter:creator'];
170 }
171 return $site_tag;
172 }
173
174 static function twitter_cards_define_type_based_on_image_count( $og_tags, $extract ) {
175 $card_type = 'summary';
176 $img_count = $extract['count']['image'];
177
178 if ( empty( $img_count ) ) {
179
180 // No images, use Blavatar as a thumbnail for the summary type.
181 if ( function_exists('blavatar_domain') ) {
182 $blavatar_domain = blavatar_domain( site_url() );
183 if ( blavatar_exists( $blavatar_domain ) ) {
184 $og_tags['twitter:image'] = blavatar_url( $blavatar_domain, 'img', 240 );
185 }
186 }
187
188 // Second fall back, Site Logo
189 if ( empty( $og_tags['twitter:image'] ) && ( function_exists( 'jetpack_has_site_logo' ) && jetpack_has_site_logo() ) ) {
190 $og_tags['twitter:image'] = jetpack_get_site_logo( 'url' );
191 }
192
193 // Third fall back, Site Icon
194 if ( empty( $og_tags['twitter:image'] ) && has_site_icon() ) {
195 $og_tags['twitter:image'] = get_site_icon_url( '240' );
196 }
197
198 // Not falling back on Gravatar, because there's no way to know if we end up with an auto-generated one.
199
200 } elseif ( $img_count && ( 'image' == $extract['type'] || 'gallery' == $extract['type'] ) ) {
201 // 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.
202 $card_type = 'summary_large_image';
203 $og_tags['twitter:image'] = esc_url( add_query_arg( 'w', 1400, ( empty( $extract['images'] ) ) ? $extract['image'] : $extract['images'][0]['url'] ) );
204 }
205
206 return array( $og_tags, $card_type );
207 }
208
209 static function twitter_cards_output( $og_tag ) {
210 return ( false !== strpos( $og_tag, 'twitter:' ) ) ? preg_replace( '/property="([^"]+)"/', 'name="\1"', $og_tag ) : $og_tag;
211 }
212
213 static function settings_init() {
214 add_settings_section( 'jetpack-twitter-cards-settings', 'Twitter Cards', '__return_false', 'sharing' );
215 add_settings_field(
216 'jetpack-twitter-cards-site-tag',
217 __( 'Twitter Site Tag', 'jetpack' ),
218 array( __CLASS__, 'settings_field' ),
219 'sharing',
220 'jetpack-twitter-cards-settings',
221 array(
222 'label_for' => 'jetpack-twitter-cards-site-tag',
223 )
224 );
225 }
226
227 static function sharing_global_options() {
228 do_settings_fields( 'sharing', 'jetpack-twitter-cards-settings' );
229 }
230
231 static function site_tag() {
232 $site_tag = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ?
233 trim( get_option( 'twitter_via' ) ) :
234 Jetpack_Options::get_option_and_ensure_autoload( 'jetpack-twitter-cards-site-tag', '' );
235 if ( empty( $site_tag ) ) {
236 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
237 return 'wordpressdotcom';
238 } else {
239 return;
240 }
241 }
242 return $site_tag;
243 }
244
245 static function settings_field() {
246 wp_nonce_field( 'jetpack-twitter-cards-settings', 'jetpack_twitter_cards_nonce', false );
247 ?>
248 <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' ) ); ?>" />
249 <p class="description" style="width: auto;"><?php esc_html_e( 'The Twitter username of the owner of this site\'s domain.', 'jetpack' ); ?></p>
250 <?php
251 }
252
253 static function settings_validate() {
254 if ( wp_verify_nonce( $_POST['jetpack_twitter_cards_nonce'], 'jetpack-twitter-cards-settings' ) ) {
255 update_option( 'jetpack-twitter-cards-site-tag', trim( ltrim( strip_tags( $_POST['jetpack-twitter-cards-site-tag'] ), '@' ) ) );
256 }
257 }
258
259 static function init() {
260 add_filter( 'jetpack_open_graph_tags', array( __CLASS__, 'twitter_cards_tags' ) );
261 add_filter( 'jetpack_open_graph_output', array( __CLASS__, 'twitter_cards_output' ) );
262 add_filter( 'jetpack_twitter_cards_site_tag', array( __CLASS__, 'site_tag' ), -99 );
263 add_filter( 'jetpack_twitter_cards_site_tag', array( __CLASS__, 'prioritize_creator_over_default_site' ), 99, 2 );
264 add_action( 'admin_init', array( __CLASS__, 'settings_init' ) );
265 add_action( 'sharing_global_options', array( __CLASS__, 'sharing_global_options' ) );
266 add_action( 'sharing_admin_update', array( __CLASS__, 'settings_validate' ) );
267 }
268 }
269
270 Jetpack_Twitter_Cards::init();
271