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

181 lines 5.3 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 * Comment meta Highlander and Verbum wrote a stored avatar URL to.
19 */
20 const AVATAR_META = 'hc_avatar';
21
22 /**
23 * Hosts whose avatars are served.
24 *
25 * @var string[]
26 */
27 private static $avatar_hosts = array( 'graph.facebook.com', 'twimg.com' );
28
29 /**
30 * Register the avatar filters.
31 *
32 * @return void
33 */
34 public static function init() {
35 add_filter( 'pre_get_avatar_data', array( __CLASS__, 'avatar_data' ), 10, 2 );
36 // WordPress.com replaces get_avatar() with its own, which never reaches pre_get_avatar_data.
37 add_filter( 'wpcom_get_avatar_url', array( __CLASS__, 'wpcom_avatar_url' ), 10, 6 );
38 }
39
40 /**
41 * Serve a stored avatar for comments that carry one.
42 *
43 * @param array $args Avatar arguments.
44 * @param mixed $id_or_email What the avatar was requested for.
45 * @return array
46 */
47 public static function avatar_data( $args, $id_or_email ) {
48 if ( ! $id_or_email instanceof \WP_Comment || isset( $args['url'] ) ) {
49 return $args;
50 }
51
52 $url = self::stored_url( (int) $id_or_email->comment_ID, isset( $args['size'] ) ? (int) $args['size'] : 96 );
53
54 if ( null !== $url ) {
55 $args['url'] = $url;
56 $args['found_avatar'] = true;
57 } elseif ( self::is_signed_in( (int) $id_or_email->comment_ID ) ) {
58 // The provider had no photo, so show the site default rather than a Gravatar the commenter never chose.
59 $args['force_default'] = true;
60 }
61
62 return $args;
63 }
64
65 /**
66 * Serve a stored avatar on WordPress.com.
67 *
68 * @param array|false $url_class Avatar URL and CSS class, or false.
69 * @param mixed $id_or_email What the avatar was requested for.
70 * @param int|string $size Avatar size.
71 * @param string $default_value Default avatar. Unused.
72 * @param bool $force_display Whether to show avatars when disabled. Unused.
73 * @param bool $force_default Whether to force the default avatar.
74 * @return array|false
75 */
76 public static function wpcom_avatar_url( $url_class, $id_or_email, $size = 96, $default_value = '', $force_display = false, $force_default = false ) {
77 if ( $force_default || ! is_array( $url_class ) || ! is_object( $id_or_email ) || empty( $id_or_email->comment_ID ) ) {
78 return $url_class;
79 }
80
81 $url = self::stored_url( (int) $id_or_email->comment_ID, (int) $size );
82
83 if ( null !== $url ) {
84 $url_class[0] = $url;
85 } elseif ( self::is_signed_in( (int) $id_or_email->comment_ID ) ) {
86 $url_class[0] = self::default_url( (int) $size );
87 $url_class[1] = ( isset( $url_class[1] ) ? $url_class[1] . ' ' : '' ) . 'avatar-default';
88 }
89
90 return $url_class;
91 }
92
93 /**
94 * The site's default avatar, resolved the way the host resolves it.
95 *
96 * @param int $size Avatar size.
97 * @return string
98 */
99 public static function default_url( $size ) {
100 if ( function_exists( 'wpcom_get_avatar_url' ) ) {
101 // Re-enters wpcom_avatar_url() with no comment, so it returns early there.
102 $url_class = wpcom_get_avatar_url( '', $size, '', true, true );
103
104 return is_array( $url_class ) ? (string) $url_class[0] : '';
105 }
106
107 return (string) get_avatar_url(
108 '',
109 array(
110 'size' => $size,
111 'force_default' => true,
112 )
113 );
114 }
115
116 /**
117 * Whether the comment was left through a popup sign-in.
118 *
119 * @param int $comment_id The comment ID.
120 * @return bool
121 */
122 private static function is_signed_in( $comment_id ) {
123 return '' !== (string) get_comment_meta( $comment_id, Checkpoint::META_PROVIDER, true );
124 }
125
126 /**
127 * The stored avatar for a comment, sized through the image CDN.
128 *
129 * @param int $comment_id The comment ID.
130 * @param int $size Avatar size.
131 * @return string|null Null when the comment carries no servable avatar.
132 */
133 private static function stored_url( $comment_id, $size ) {
134 // WordPress.com asks twice per comment, through get_avatar_data() and again through wpcom_get_avatar_url.
135 static $resolved = array();
136
137 $key = get_current_blog_id() . ":$comment_id:$size";
138
139 if ( array_key_exists( $key, $resolved ) ) {
140 return $resolved[ $key ];
141 }
142
143 // Written only from an authenticated exchange with WordPress.com, so any https URL is served.
144 $stored = get_comment_meta( $comment_id, Checkpoint::META_AVATAR, true );
145
146 if ( ! is_string( $stored ) || $stored === '' || 'https' !== wp_parse_url( $stored, PHP_URL_SCHEME ) ) {
147 $stored = get_comment_meta( $comment_id, self::AVATAR_META, true );
148
149 if ( ! is_string( $stored ) || $stored === '' || ! self::is_servable_avatar( $stored ) ) {
150 $stored = null;
151 }
152 }
153
154 $resolved[ $key ] = null === $stored ? null : Image_CDN_Core::cdn_url( $stored, array( 'resize' => "$size,$size" ) );
155
156 return $resolved[ $key ];
157 }
158
159 /**
160 * Whether a stored avatar URL is one we are willing to serve.
161 *
162 * @param string $url The stored avatar URL.
163 * @return bool
164 */
165 private static function is_servable_avatar( $url ) {
166 $host = wp_parse_url( $url, PHP_URL_HOST );
167
168 if ( ! is_string( $host ) ) {
169 return false;
170 }
171
172 foreach ( self::$avatar_hosts as $allowed ) {
173 if ( $host === $allowed || str_ends_with( $host, ".$allowed" ) ) {
174 return true;
175 }
176 }
177
178 return false;
179 }
180 }
181