Completed
Push — add/widget-visibility-toggle ( 95d149...5a67d6 )
by
unknown
10:37 queued 03:01
created

gravatar-hovercards.php ➔ gravatar_hovercards_configuration_url()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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: Yes
10
 * Module Tags: Social, Appearance
11
 * Feature: Appearance
12
 * Additional Search Queries: gravatar, hovercards
13
 */
14
15
define( 'GROFILES__CACHE_BUSTER', gmdate( 'YM' ) . 'aa' ); // Break CDN cache, increment when gravatar.com/js/gprofiles.js changes
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
	Jetpack::enable_module_configurable( __FILE__ );
29
	add_filter( 'jetpack_module_configuration_url_gravatar-hovercards', 'gravatar_hovercards_configuration_url' );
30
}
31
32
function gravatar_hovercards_configuration_url() {
33
	return admin_url( 'options-discussion.php#show_avatars' );
34
}
35
36
add_action( 'jetpack_modules_loaded', 'grofiles_hovercards_init' );
37
38
/* Hovercard Settings */
39
40
/**
41
 * Adds Gravatar Hovercard setting
42
 *
43
 * @todo - always print HTML, hide via CSS/JS if !show_avatars
44
 */
45
function grofiles_add_settings() {
46
	if ( !get_option( 'show_avatars' ) )
47
		return;
48
49
 	add_settings_field( 'gravatar_disable_hovercards', __( 'Gravatar Hovercards', 'jetpack' ), 'grofiles_setting_callback', 'discussion', 'avatars' );
50
 	register_setting( 'discussion', 'gravatar_disable_hovercards', 'grofiles_hovercard_option_sanitize' );
51
}
52
53
/**
54
 * HTML for Gravatar Hovercard setting
55
 */
56
function grofiles_setting_callback() {
57
	global $current_user;
58
59
	$checked = 'disabled' == get_option( 'gravatar_disable_hovercards' ) ? '' : 'checked="checked" ';
60
61
 	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>";
62
?>
63
<style type="text/css">
64
#grav-profile-example img {
65
	float: left;
66
}
67
#grav-profile-example span {
68
	padding: 0 1em;
69
}
70
</style>
71
<script type="text/javascript">
72
// <![CDATA[
73
jQuery( function($) {
74
	var tr = $( '#gravatar_disable_hovercards' ).change( function() {
75
		if ( $( this ).is( ':checked' ) ) {
76
			$( '#grav-profile-example' ).slideDown( 'fast' );
77
		} else {
78
			$( '#grav-profile-example' ).slideUp( 'fast' );
79
		}
80
	} ).parents( 'tr' );
81
	var ftr = tr.parents( 'table' ).find( 'tr:first' );
82
	if ( ftr.length && !ftr.find( '#gravatar_disable_hovercards' ).length ) {
83
		ftr.after( tr );
84
	}
85
} );
86
// ]]>
87
</script>
88
	<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>
89
<?php
90
}
91
92
/**
93
 * Sanitation filter for Gravatar Hovercard setting
94
 */
95
function grofiles_hovercard_option_sanitize( $val ) {
96
	if ( 'disabled' == $val ) {
97
		return $val;
98
	}
99
100
	return $val ? 'enabled' : 'disabled';
101
}
102
103
104
/* Hovercard Display */
105
106
/**
107
 * Stores the gravatars' users that need extra profile data attached.
108
 *
109
 * Getter/Setter
110
 *
111
 * @param int|string|null $author Setter: User ID or email address.  Getter: null.
112
 *
113
 * @return mixed Setter: void.  Getter: array of user IDs and email addresses.
114
 */
115
function grofiles_gravatars_to_append( $author = null ) {
116
	static $authors = array();
117
118
	// Get
119
	if ( is_null( $author ) ) {
120
		return array_keys( $authors );
121
	}
122
123
	// Set
124
125
	if ( is_numeric( $author ) ) {
126
		$author = (int) $author;
127
	}
128
129
	$authors[$author] = true;
130
}
131
132
/**
133
 * Stores the user ID or email address for each gravatar generated.
134
 *
135
 * Attached to the 'get_avatar' filter.
136
 *
137
 * @param string $avatar The <img/> element of the avatar.
138
 * @param mixed $author User ID, email address, user login, comment object, user object, post object
139
 *
140
 * @return The <img/> element of the avatar.
141
 */
142
function grofiles_get_avatar( $avatar, $author ) {
143
	if ( is_numeric( $author ) ) {
144
		grofiles_gravatars_to_append( $author );
145
	} else if ( is_string( $author ) ) {
146
		if ( false !== strpos( $author, '@' ) ) {
147
			grofiles_gravatars_to_append( $author );
148
		} else {
149
			if ( $user = get_user_by( 'slug', $author ) )
150
				grofiles_gravatars_to_append( $user->ID );
151
		}
152
	} else if ( isset( $author->comment_type ) ) {
153
		if ( '' != $author->comment_type && 'comment' != $author->comment_type )
154
			return $avatar;
155
		if ( $author->user_id )
156
			grofiles_gravatars_to_append( $author->user_id );
157
		else
158
			grofiles_gravatars_to_append( $author->comment_author_email );
159
	} else if ( isset( $author->user_login ) ) {
160
		grofiles_gravatars_to_append( $author->ID );
161
	} else if ( isset( $author->post_author ) ) {
162
		grofiles_gravatars_to_append( $author->post_author );
163
	}
164
165
	return $avatar;
166
}
167
168
/**
169
 * Loads Gravatar Hovercard script.
170
 *
171
 * @todo is_singular() only?
172
 */
173
function grofiles_attach_cards() {
174
	global $blog_id;
175
176
	// Is the display of Avatars disabled?
177
	if ( ! get_option( 'show_avatars' ) ) {
178
		return;
179
	}
180
181
	// Is the display of Gravatar Hovercards disabled?
182
	if ( 'disabled' == Jetpack_Options::get_option_and_ensure_autoload( 'gravatar_disable_hovercards', '0' ) ) {
183
		return;
184
	}
185
186
	wp_enqueue_script( 'grofiles-cards', 'https://secure.gravatar.com/js/gprofiles.js', array( 'jquery' ), GROFILES__CACHE_BUSTER, true );
187
	wp_enqueue_script( 'wpgroho', plugins_url( 'wpgroho.js', __FILE__ ), array( 'grofiles-cards' ), false, true );
188
	if ( is_user_logged_in() ) {
189
		$cu = wp_get_current_user();
190
		$my_hash = md5( $cu->user_email );
191
	} else if ( !empty( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) {
192
		$my_hash = md5( $_COOKIE['comment_author_email_' . COOKIEHASH] );
193
	} else {
194
		$my_hash = '';
195
	}
196
	wp_localize_script( 'wpgroho', 'WPGroHo', compact( 'my_hash' ) );
197
}
198
199
function grofiles_attach_cards_forced() {
200
	add_filter( 'pre_option_gravatar_disable_hovercards', 'grofiles_force_gravatar_enable_hovercards' );
201
	grofiles_attach_cards();
202
}
203
204
function grofiles_force_gravatar_enable_hovercards() {
205
	return 'enabled';
206
}
207
208
function grofiles_admin_cards_forced() {
209
	add_action( 'admin_footer', 'grofiles_attach_cards_forced' );
210
}
211
212
function grofiles_admin_cards() {
213
	add_action( 'admin_footer', 'grofiles_attach_cards' );
214
}
215
216
function grofiles_extra_data() {
217
?>
218
	<div style="display:none">
219
<?php
220
	foreach ( grofiles_gravatars_to_append() as $author )
0 ignored issues
show
Bug introduced by
The expression grofiles_gravatars_to_append() of type array<integer,integer|string>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
221
		grofiles_hovercards_data_html( $author );
222
?>
223
	</div>
224
<?php
225
}
226
227
/**
228
 * Echoes the data from grofiles_hovercards_data() as HTML elements.
229
 *
230
 * @since 5.5.0 Add support for a passed WP_User object
231
 *
232
 * @param int|string|WP_User $author User ID, email address, or a WP_User object
233
 */
234
function grofiles_hovercards_data_html( $author ) {
235
	$data = grofiles_hovercards_data( $author );
236
	$hash = '';
237
	if ( is_numeric( $author ) ) {
238
		$user = get_userdata( $author );
239
		if ( $user ) {
240
			$hash = md5( $user->user_email );
241
		}
242
	} elseif ( is_email( $author ) ) {
243
		$hash = md5( $author );
244
	} elseif ( is_a( $author, 'WP_User' ) ) {
245
		$hash = md5( $author->user_email );
246
	}
247
248
	if ( ! $hash ) {
249
		return;
250
	}
251
?>
252
	<div class="grofile-hash-map-<?php echo $hash; ?>">
253
<?php	foreach ( $data as $key => $value ) : ?>
254
		<span class="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></span>
255
<?php	endforeach; ?>
256
	</div>
257
<?php
258
}
259
260
261
/* API */
262
263
/**
264
 * Returns the PHP callbacks for data sources.
265
 *
266
 * 'grofiles_hovercards_data_callbacks' filter
267
 *
268
 * @return array( data_key => data_callback, ... )
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
269
 */
270
function grofiles_hovercards_data_callbacks() {
271
	/**
272
	 * Filter the Gravatar Hovercard PHP callbacks.
273
	 *
274
	 * @module gravatar-hovercards
275
	 *
276
	 * @since 1.1.0
277
	 *
278
	 * @param array $args Array of data callbacks.
279
	 */
280
	return apply_filters( 'grofiles_hovercards_data_callbacks', array() );
281
}
282
283
/**
284
 * Keyed JSON object containing all profile data provided by registered callbacks
285
 *
286
 * @param int|strung $author User ID or email address
287
 *
288
 * @return array( data_key => data, ... )
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
289
 */
290
function grofiles_hovercards_data( $author ) {
291
	$r = array();
292
	foreach ( grofiles_hovercards_data_callbacks() as $key => $callback ) {
293
		if ( !is_callable( $callback ) )
294
			continue;
295
		$data = call_user_func( $callback, $author, $key );
296
		if ( !is_null( $data ) )
297
			$r[$key] = $data;
298
	}
299
300
	return $r;
301
}
302