PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 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 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-comments/src/class-avatars.php +150 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,150 @@
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 +}