PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 10.1
Jetpack – WP Security, Backup, Speed, & Growth v10.1
16.2-beta 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 All 501 releases
jetpack / modules / gravatar-hovercards.php

gravatar-hovercards.php in Jetpack – WP Security, Backup, Speed, & Growth 10.1, at modules/gravatar-hovercards.php

369 lines 11.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Module Name: Gravatar Hovercards
4 * Module Description: Enable pop-up business cards over commenters’ Gravatars.
5 * Sort Order: 11
6 * Recommendation Order: 13
7 * First Introduced: 1.1
8 * Requires Connection: No
9 * Auto Activate: No
10 * Module Tags: Social, Appearance
11 * Feature: Appearance
12 * Additional Search Queries: gravatar, hovercards
13 */
14
15 define( 'GROFILES__CACHE_BUSTER', gmdate( 'YW' ) );
16
17 function grofiles_hovercards_init() {
18 add_filter( 'get_avatar', 'grofiles_get_avatar', 10, 2 );
19 add_action( 'wp_enqueue_scripts', 'grofiles_attach_cards' );
20 add_action( 'wp_footer', 'grofiles_extra_data' );
21 add_action( 'admin_init', 'grofiles_add_settings' );
22
23 add_action( 'load-index.php', 'grofiles_admin_cards' );
24 add_action( 'load-users.php', 'grofiles_admin_cards' );
25 add_action( 'load-edit-comments.php', 'grofiles_admin_cards' );
26 add_action( 'load-options-discussion.php', 'grofiles_admin_cards_forced' );
27
28 add_filter( 'jetpack_module_configuration_url_gravatar-hovercards', 'gravatar_hovercards_configuration_url' );
29
30 add_filter( 'get_comment_author_url', 'grofiles_amp_comment_author_url', 10, 2 );
31 }
32
33 function gravatar_hovercards_configuration_url() {
34 return admin_url( 'options-discussion.php#show_avatars' );
35 }
36
37 add_action( 'jetpack_modules_loaded', 'grofiles_hovercards_init' );
38
39 /* Hovercard Settings */
40
41 /**
42 * Adds Gravatar Hovercard setting
43 *
44 * @todo - always print HTML, hide via CSS/JS if !show_avatars
45 */
46 function grofiles_add_settings() {
47 if ( !get_option( 'show_avatars' ) )
48 return;
49
50 add_settings_field( 'gravatar_disable_hovercards', __( 'Gravatar Hovercards', 'jetpack' ), 'grofiles_setting_callback', 'discussion', 'avatars' );
51 register_setting( 'discussion', 'gravatar_disable_hovercards', 'grofiles_hovercard_option_sanitize' );
52 }
53
54 /**
55 * HTML for Gravatar Hovercard setting
56 */
57 function grofiles_setting_callback() {
58 global $current_user;
59
60 $checked = 'disabled' == get_option( 'gravatar_disable_hovercards' ) ? '' : 'checked="checked" ';
61
62 echo "<label id='gravatar-hovercard-options'><input {$checked}name='gravatar_disable_hovercards' id='gravatar_disable_hovercards' type='checkbox' value='enabled' class='code' /> " . __( "View people's profiles when you mouse over their Gravatars", 'jetpack' ) . "</label>";
63 ?>
64 <style type="text/css">
65 #grav-profile-example img {
66 float: left;
67 }
68 #grav-profile-example span {
69 padding: 0 1em;
70 }
71 </style>
72 <script type="text/javascript">
73 // <![CDATA[
74 jQuery( function($) {
75 var tr = $( '#gravatar_disable_hovercards' ).change( function() {
76 if ( $( this ).is( ':checked' ) ) {
77 $( '#grav-profile-example' ).slideDown( 'fast' );
78 } else {
79 $( '#grav-profile-example' ).slideUp( 'fast' );
80 }
81 } ).parents( 'tr' );
82 var ftr = tr.parents( 'table' ).find( 'tr:first' );
83 if ( ftr.length && !ftr.find( '#gravatar_disable_hovercards' ).length ) {
84 ftr.after( tr );
85 }
86 } );
87 // ]]>
88 </script>
89 <p id="grav-profile-example" class="hide-if-no-js"<?php if ( !$checked ) echo ' style="display:none"'; ?>><?php echo get_avatar( $current_user->ID, 64 ); ?> <span><?php _e( 'Put your mouse over your Gravatar to check out your profile.', 'jetpack' ); ?> <br class="clear" /></span></p>
90 <?php
91 }
92
93 /**
94 * Sanitation filter for Gravatar Hovercard setting
95 */
96 function grofiles_hovercard_option_sanitize( $val ) {
97 if ( 'disabled' == $val ) {
98 return $val;
99 }
100
101 return $val ? 'enabled' : 'disabled';
102 }
103
104
105 /* Hovercard Display */
106
107 /**
108 * Stores the gravatars' users that need extra profile data attached.
109 *
110 * Getter/Setter
111 *
112 * @param int|string|null $author Setter: User ID or email address. Getter: null.
113 *
114 * @return mixed Setter: void. Getter: array of user IDs and email addresses.
115 */
116 function grofiles_gravatars_to_append( $author = null ) {
117 static $authors = array();
118
119 // Get
120 if ( is_null( $author ) ) {
121 return array_keys( $authors );
122 }
123
124 // Set
125
126 if ( is_numeric( $author ) ) {
127 $author = (int) $author;
128 }
129
130 $authors[$author] = true;
131 }
132
133 /**
134 * In AMP, override the comment URL to allow for interactivity without
135 * navigating to a new page
136 *
137 * @param string $url The comment author's URL.
138 * @param int $id The comment ID.
139 *
140 * @return string The adjusted URL
141 */
142 function grofiles_amp_comment_author_url( $url, $id ) {
143 if ( 'comment' === get_comment_type( $id ) && class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
144 // @todo Disabling the comment author link in this way is not ideal since clicking the link does not cause the lightbox to open in the same way as clicking the gravatar. Likely get_comment_author_url_link should be used instead so that the href attribute can be replaced with an `on` attribute that activates the gallery.
145 return '#!';
146 }
147
148 return $url;
149 }
150
151 /**
152 * Stores the user ID or email address for each gravatar generated.
153 *
154 * Attached to the 'get_avatar' filter.
155 *
156 * @param string $avatar The <img/> element of the avatar.
157 * @param mixed $author User ID, email address, user login, comment object, user object, post object
158 *
159 * @return string The <img/> element of the avatar.
160 */
161 function grofiles_get_avatar( $avatar, $author ) {
162 $is_amp = class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request();
163
164 if ( is_numeric( $author ) ) {
165 grofiles_gravatars_to_append( $author );
166 } else if ( is_string( $author ) ) {
167 if ( false !== strpos( $author, '@' ) ) {
168 grofiles_gravatars_to_append( $author );
169 } else {
170 if ( $user = get_user_by( 'slug', $author ) )
171 grofiles_gravatars_to_append( $user->ID );
172 }
173 } else if ( isset( $author->comment_type ) ) {
174 if ( $is_amp ) {
175 if ( 1 === preg_match( '/avatar\/([a-zA-Z0-9]+)\?/', $avatar, $email_hash ) ) {
176 $email_hash = $email_hash[1];
177 $cache_group = 'gravatar_profiles_';
178 $cache_key = 'gravatar_profile_' . $email_hash;
179
180 $response_body = wp_cache_get( $cache_key, $cache_group );
181 if ( false === $response_body ) {
182 $response = wp_remote_get( esc_url_raw( 'https://en.gravatar.com/' . $email_hash . '.json' ) );
183
184 if ( is_array( $response ) && ! is_wp_error( $response ) ) {
185 $response_body = json_decode( $response['body'] );
186 wp_cache_set( $cache_key, $response_body, $cache_group, 60 * MINUTE_IN_SECONDS );
187 }
188 }
189
190 $profile = $response_body->entry[0];
191 $display_name = $profile->displayName; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
192 $location = isset( $profile->currentLocation ) ? $profile->currentLocation : ''; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
193 $description = isset( $profile->aboutMe ) ? $profile->aboutMe : ''; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
194
195 $avatar = '
196 <figure data-amp-lightbox="true">
197 ' . $avatar . '
198 <figcaption>
199 ' . esc_html( $display_name ) . ( ! empty( $location ) ? '' . esc_html( $location ) : '' ) . ( ! empty( $description ) ? '' . esc_html( $description ) : '' ) . '
200 </figcaption>
201 </figure>
202 ';
203 }
204
205 return $avatar;
206 }
207
208 if ( '' != $author->comment_type && 'comment' != $author->comment_type )
209 return $avatar;
210 if ( $author->user_id )
211 grofiles_gravatars_to_append( $author->user_id );
212 else
213 grofiles_gravatars_to_append( $author->comment_author_email );
214 } else if ( isset( $author->user_login ) ) {
215 grofiles_gravatars_to_append( $author->ID );
216 } else if ( isset( $author->post_author ) ) {
217 grofiles_gravatars_to_append( $author->post_author );
218 }
219
220 return $avatar;
221 }
222
223 /**
224 * Loads Gravatar Hovercard script.
225 *
226 * @todo is_singular() only?
227 */
228 function grofiles_attach_cards() {
229 global $blog_id;
230
231 // Is the display of Avatars disabled?
232 if ( ! get_option( 'show_avatars' ) ) {
233 return;
234 }
235
236 // Is the display of Gravatar Hovercards disabled?
237 if ( 'disabled' == Jetpack_Options::get_option_and_ensure_autoload( 'gravatar_disable_hovercards', '0' ) ) {
238 return;
239 }
240
241 if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
242 wp_enqueue_style( 'gravatar-hovercard-style', plugins_url( '/gravatar/gravatar-hovercards-amp.css', __FILE__ ), array(), JETPACK__VERSION );
243 } else {
244 wp_enqueue_script( 'grofiles-cards', 'https://secure.gravatar.com/js/gprofiles.js', array(), GROFILES__CACHE_BUSTER, true );
245 wp_enqueue_script( 'wpgroho', plugins_url( 'wpgroho.js', __FILE__ ), array( 'grofiles-cards' ), JETPACK__VERSION, true );
246 if ( is_user_logged_in() ) {
247 $cu = wp_get_current_user();
248 $my_hash = md5( $cu->user_email );
249 } elseif ( ! empty( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] ) ) {
250 $my_hash = md5( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] );
251 } else {
252 $my_hash = '';
253 }
254 wp_localize_script( 'wpgroho', 'WPGroHo', compact( 'my_hash' ) );
255 }
256 }
257
258 function grofiles_attach_cards_forced() {
259 add_filter( 'pre_option_gravatar_disable_hovercards', 'grofiles_force_gravatar_enable_hovercards' );
260 grofiles_attach_cards();
261 }
262
263 function grofiles_force_gravatar_enable_hovercards() {
264 return 'enabled';
265 }
266
267 function grofiles_admin_cards_forced() {
268 add_action( 'admin_footer', 'grofiles_attach_cards_forced' );
269 }
270
271 function grofiles_admin_cards() {
272 add_action( 'admin_footer', 'grofiles_attach_cards' );
273 }
274
275 function grofiles_extra_data() {
276 $authors = grofiles_gravatars_to_append();
277
278 if ( ! $authors ) {
279 wp_dequeue_script( 'grofiles-cards' );
280 wp_dequeue_script( 'wpgroho' );
281 } else {
282 ?>
283 <div style="display:none">
284 <?php
285 foreach ( $authors as $author ) {
286 grofiles_hovercards_data_html( $author );
287 }
288 ?>
289 </div>
290 <?php
291 }
292 }
293
294 /**
295 * Echoes the data from grofiles_hovercards_data() as HTML elements.
296 *
297 * @since 5.5.0 Add support for a passed WP_User object
298 *
299 * @param int|string|WP_User $author User ID, email address, or a WP_User object
300 */
301 function grofiles_hovercards_data_html( $author ) {
302 $data = grofiles_hovercards_data( $author );
303 $hash = '';
304 if ( is_numeric( $author ) ) {
305 $user = get_userdata( $author );
306 if ( $user ) {
307 $hash = md5( $user->user_email );
308 }
309 } elseif ( is_email( $author ) ) {
310 $hash = md5( $author );
311 } elseif ( is_a( $author, 'WP_User' ) ) {
312 $hash = md5( $author->user_email );
313 }
314
315 if ( ! $hash ) {
316 return;
317 }
318 ?>
319 <div class="grofile-hash-map-<?php echo $hash; ?>">
320 <?php foreach ( $data as $key => $value ) : ?>
321 <span class="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></span>
322 <?php endforeach; ?>
323 </div>
324 <?php
325 }
326
327
328 /* API */
329
330 /**
331 * Returns the PHP callbacks for data sources.
332 *
333 * 'grofiles_hovercards_data_callbacks' filter
334 *
335 * @return array( data_key => data_callback, ... )
336 */
337 function grofiles_hovercards_data_callbacks() {
338 /**
339 * Filter the Gravatar Hovercard PHP callbacks.
340 *
341 * @module gravatar-hovercards
342 *
343 * @since 1.1.0
344 *
345 * @param array $args Array of data callbacks.
346 */
347 return apply_filters( 'grofiles_hovercards_data_callbacks', array() );
348 }
349
350 /**
351 * Keyed JSON object containing all profile data provided by registered callbacks
352 *
353 * @param int|strung $author User ID or email address
354 *
355 * @return array( data_key => data, ... )
356 */
357 function grofiles_hovercards_data( $author ) {
358 $r = array();
359 foreach ( grofiles_hovercards_data_callbacks() as $key => $callback ) {
360 if ( !is_callable( $callback ) )
361 continue;
362 $data = call_user_func( $callback, $author, $key );
363 if ( !is_null( $data ) )
364 $r[$key] = $data;
365 }
366
367 return $r;
368 }
369