comment_ID, isset( $args['size'] ) ? (int) $args['size'] : 96 ); if ( null !== $url ) { $args['url'] = $url; $args['found_avatar'] = true; } elseif ( self::is_signed_in( (int) $id_or_email->comment_ID ) ) { // The provider had no photo: the site default, not a Gravatar the commenter never chose. $args['force_default'] = true; } return $args; } /** * Serve a stored avatar on WordPress.com. * * @param array|false $url_class Avatar URL and CSS class, or false. * @param mixed $id_or_email What the avatar was requested for. * @param int|string $size Avatar size. * @param string $default_value Default avatar. Unused. * @param bool $force_display Whether to show avatars when disabled. Unused. * @param bool $force_default Whether to force the default avatar. * @return array|false */ public static function wpcom_avatar_url( $url_class, $id_or_email, $size = 96, $default_value = '', $force_display = false, $force_default = false ) { if ( $force_default || ! is_array( $url_class ) || ! is_object( $id_or_email ) || empty( $id_or_email->comment_ID ) ) { return $url_class; } $url = self::stored_url( (int) $id_or_email->comment_ID, (int) $size ); if ( null !== $url ) { $url_class[0] = $url; } elseif ( self::is_signed_in( (int) $id_or_email->comment_ID ) ) { $url_class[0] = self::default_url( (int) $size ); $url_class[1] = ( isset( $url_class[1] ) ? $url_class[1] . ' ' : '' ) . 'avatar-default'; } return $url_class; } /** * The site's default avatar, resolved the way the host resolves it. * * @param int $size Avatar size. * @return string */ public static function default_url( $size ) { if ( function_exists( 'wpcom_get_avatar_url' ) ) { // Re-enters wpcom_avatar_url() with no comment, so it returns early there. $url_class = wpcom_get_avatar_url( '', $size, '', false, true ); // Built for HTML, so its query string is joined with &, which Gravatar reads as a parameter named amp;d. return is_array( $url_class ) ? html_entity_decode( (string) $url_class[0], ENT_QUOTES ) : ''; } return (string) get_avatar_url( '', array( 'size' => $size, 'force_default' => true, ) ); } /** * Whether the comment was left through a popup sign-in. * * @param int $comment_id The comment ID. * @return bool */ private static function is_signed_in( $comment_id ) { return '' !== (string) get_comment_meta( $comment_id, Checkpoint::META_PROVIDER, true ); } /** * The stored avatar for a comment, sized through the image CDN. * * @param int $comment_id The comment ID. * @param int $size Avatar size. * @return string|null Null when the comment carries no servable avatar. */ private static function stored_url( $comment_id, $size ) { // WordPress.com asks twice per comment, through get_avatar_data() and again through wpcom_get_avatar_url. static $resolved = array(); $key = get_current_blog_id() . ":$comment_id:$size"; if ( array_key_exists( $key, $resolved ) ) { return $resolved[ $key ]; } // Written only from an authenticated exchange with WordPress.com, so any https URL is served. $stored = get_comment_meta( $comment_id, Checkpoint::META_AVATAR, true ); if ( ! is_string( $stored ) || $stored === '' || 'https' !== wp_parse_url( $stored, PHP_URL_SCHEME ) ) { // Highlander and Verbum stored a Facebook or X avatar here, which the email cannot // bring back. Written by the browser, so only those two hosts are served. $stored = get_comment_meta( $comment_id, 'hc_avatar', true ); $host = is_string( $stored ) ? wp_parse_url( $stored, PHP_URL_HOST ) : null; if ( ! is_string( $host ) || ! preg_match( '/(^|\.)(graph\.facebook\.com|twimg\.com)$/', $host ) ) { $stored = null; } } $resolved[ $key ] = null === $stored ? null : Image_CDN_Core::cdn_url( $stored, array( 'resize' => "$size,$size" ) ); return $resolved[ $key ]; } }