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