PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 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 All 506 releases
jetpack / jetpack_vendor / automattic / jetpack-comments / src / class-avatars.php

class-avatars.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.7, at jetpack_vendor/automattic/jetpack-comments/src/class-avatars.php

151 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Avatars for comments already written.
4 *
5 * @package automattic/jetpack-comments
6 */
7
8 namespace Automattic\Jetpack\Comments;
9
10 use Automattic\Jetpack\Image_CDN\Image_CDN_Core;
11
12 /**
13 * Avatars WordPress cannot derive from an email address.
14 */
15 class Avatars {
16
17 /**
18 * Register the avatar filters.
19 *
20 * @return void
21 */
22 public static function init() {
23 add_filter( 'pre_get_avatar_data', array( __CLASS__, 'avatar_data' ), 10, 2 );
24 // WordPress.com replaces get_avatar() with its own, which never reaches pre_get_avatar_data.
25 add_filter( 'wpcom_get_avatar_url', array( __CLASS__, 'wpcom_avatar_url' ), 10, 6 );
26 }
27
28 /**
29 * Serve a stored avatar for comments that carry one.
30 *
31 * @param array $args Avatar arguments.
32 * @param mixed $id_or_email What the avatar was requested for.
33 * @return array
34 */
35 public static function avatar_data( $args, $id_or_email ) {
36 if ( ! $id_or_email instanceof \WP_Comment || isset( $args['url'] ) ) {
37 return $args;
38 }
39
40 $url = self::stored_url( (int) $id_or_email->comment_ID, isset( $args['size'] ) ? (int) $args['size'] : 96 );
41
42 if ( null !== $url ) {
43 $args['url'] = $url;
44 $args['found_avatar'] = true;
45 } elseif ( self::is_signed_in( (int) $id_or_email->comment_ID ) ) {
46 // The provider had no photo: the site default, not a Gravatar the commenter never chose.
47 $args['force_default'] = true;
48 }
49
50 return $args;
51 }
52
53 /**
54 * Serve a stored avatar on WordPress.com.
55 *
56 * @param array|false $url_class Avatar URL and CSS class, or false.
57 * @param mixed $id_or_email What the avatar was requested for.
58 * @param int|string $size Avatar size.
59 * @param string $default_value Default avatar. Unused.
60 * @param bool $force_display Whether to show avatars when disabled. Unused.
61 * @param bool $force_default Whether to force the default avatar.
62 * @return array|false
63 */
64 public static function wpcom_avatar_url( $url_class, $id_or_email, $size = 96, $default_value = '', $force_display = false, $force_default = false ) {
65 if ( $force_default || ! is_array( $url_class ) || ! is_object( $id_or_email ) || empty( $id_or_email->comment_ID ) ) {
66 return $url_class;
67 }
68
69 $url = self::stored_url( (int) $id_or_email->comment_ID, (int) $size );
70
71 if ( null !== $url ) {
72 $url_class[0] = $url;
73 } elseif ( self::is_signed_in( (int) $id_or_email->comment_ID ) ) {
74 $url_class[0] = self::default_url( (int) $size );
75 $url_class[1] = ( isset( $url_class[1] ) ? $url_class[1] . ' ' : '' ) . 'avatar-default';
76 }
77
78 return $url_class;
79 }
80
81 /**
82 * The site's default avatar, resolved the way the host resolves it.
83 *
84 * @param int $size Avatar size.
85 * @return string
86 */
87 public static function default_url( $size ) {
88 if ( function_exists( 'wpcom_get_avatar_url' ) ) {
89 // Re-enters wpcom_avatar_url() with no comment, so it returns early there.
90 $url_class = wpcom_get_avatar_url( '', $size, '', false, true );
91
92 // Built for HTML, so its query string is joined with &amp;, which Gravatar reads as a parameter named amp;d.
93 return is_array( $url_class ) ? html_entity_decode( (string) $url_class[0], ENT_QUOTES ) : '';
94 }
95
96 return (string) get_avatar_url(
97 '',
98 array(
99 'size' => $size,
100 'force_default' => true,
101 )
102 );
103 }
104
105 /**
106 * Whether the comment was left through a popup sign-in.
107 *
108 * @param int $comment_id The comment ID.
109 * @return bool
110 */
111 private static function is_signed_in( $comment_id ) {
112 return '' !== (string) get_comment_meta( $comment_id, Checkpoint::META_PROVIDER, true );
113 }
114
115 /**
116 * The stored avatar for a comment, sized through the image CDN.
117 *
118 * @param int $comment_id The comment ID.
119 * @param int $size Avatar size.
120 * @return string|null Null when the comment carries no servable avatar.
121 */
122 private static function stored_url( $comment_id, $size ) {
123 // WordPress.com asks twice per comment, through get_avatar_data() and again through wpcom_get_avatar_url.
124 static $resolved = array();
125
126 $key = get_current_blog_id() . ":$comment_id:$size";
127
128 if ( array_key_exists( $key, $resolved ) ) {
129 return $resolved[ $key ];
130 }
131
132 // Written only from an authenticated exchange with WordPress.com, so any https URL is served.
133 $stored = get_comment_meta( $comment_id, Checkpoint::META_AVATAR, true );
134
135 if ( ! is_string( $stored ) || $stored === '' || 'https' !== wp_parse_url( $stored, PHP_URL_SCHEME ) ) {
136 // Highlander and Verbum stored a Facebook or X avatar here, which the email cannot
137 // bring back. Written by the browser, so only those two hosts are served.
138 $stored = get_comment_meta( $comment_id, 'hc_avatar', true );
139 $host = is_string( $stored ) ? wp_parse_url( $stored, PHP_URL_HOST ) : null;
140
141 if ( ! is_string( $host ) || ! preg_match( '/(^|\.)(graph\.facebook\.com|twimg\.com)$/', $host ) ) {
142 $stored = null;
143 }
144 }
145
146 $resolved[ $key ] = null === $stored ? null : Image_CDN_Core::cdn_url( $stored, array( 'resize' => "$size,$size" ) );
147
148 return $resolved[ $key ];
149 }
150 }
151