Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.79% covered (warning)
86.79%
92 / 106
0.00% covered (danger)
0.00%
0 / 2
CRAP
n/a
0 / 0
jetpack_gravatar_shortcode
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
4.01
jetpack_gravatar_profile_shortcode
89.89% covered (warning)
89.89%
80 / 89
0.00% covered (danger)
0.00%
0 / 1
20.41
1<?php
2/**
3 * Gravatar shortcode for avatar and profile.
4 *
5 * Usage:
6 *
7 * [gravatar email="user@example.org" size="48"]
8 * [gravatar_profile who="user@example.org"]
9 *
10 * @package automattic/jetpack
11 */
12
13if ( ! defined( 'ABSPATH' ) ) {
14    exit( 0 );
15}
16
17add_shortcode( 'gravatar', 'jetpack_gravatar_shortcode' );
18add_shortcode( 'gravatar_profile', 'jetpack_gravatar_profile_shortcode' );
19
20/**
21 * Get gravatar using the email provided at the specified size.
22 *
23 * @since 4.5.0
24 *
25 * @param array $atts Shortcode attributes.
26 *
27 * @return bool|string
28 */
29function jetpack_gravatar_shortcode( $atts ) {
30    $atts = shortcode_atts(
31        array(
32            'email' => '',
33            'size'  => 96,
34        ),
35        $atts
36    );
37
38    if ( empty( $atts['email'] ) || ! is_email( $atts['email'] ) ) {
39        return false;
40    }
41
42    $atts['size'] = (int) $atts['size'];
43    if ( 0 > $atts['size'] ) {
44        $atts['size'] = 96;
45    }
46
47    return get_avatar( $atts['email'], $atts['size'] );
48}
49
50/**
51 * Display Gravatar profile
52 *
53 * @since 4.5.0
54 *
55 * @param array $atts Shortcode attributes.
56 *
57 * @uses shortcode_atts()
58 * @uses get_user_by()
59 * @uses is_email()
60 * @uses sanitize_email()
61 * @uses sanitize_user()
62 * @uses set_url_scheme()
63 * @uses wpcom_get_avatar_url()
64 * @uses get_user_attribute()
65 * @uses esc_url()
66 * @uses esc_html()
67 * @uses _e()
68 *
69 * @return string
70 */
71function jetpack_gravatar_profile_shortcode( $atts ) {
72    // Give each use of the shortcode a unique ID.
73    static $instance = 0;
74
75    // Process passed attributes.
76    $atts = shortcode_atts(
77        array(
78            'who' => null,
79        ),
80        $atts,
81        'jetpack_gravatar_profile'
82    );
83
84    // Can specify username, user ID, or email address.
85    if ( is_numeric( $atts['who'] ) ) {
86        $user_id = (int) $atts['who'];
87        if ( ! is_user_member_of_blog( $user_id, get_current_blog_id() ) ) {
88            // Bail if the user id is not a member of this site.
89            return false;
90        }
91        $user = get_user_by( 'id', $user_id );
92    } elseif ( is_email( $atts['who'] ) ) {
93        $user = get_user_by( 'email', sanitize_email( $atts['who'] ) );
94    } elseif ( is_string( $atts['who'] ) ) {
95        $user = get_user_by( 'login', sanitize_user( $atts['who'] ) );
96    } else {
97        $user = false;
98    }
99
100    // Bail if we don't have a user.
101    if ( false === $user ) {
102        return false;
103    }
104
105    $hashed_email = hash( 'sha256', strtolower( trim( $user->user_email ) ) );
106    $cache_key    = 'jetpack_gravatar_profile_' . $hashed_email;
107    $profile      = get_transient( $cache_key );
108
109    if ( empty( $profile ) ) {
110        $profile_url = sprintf(
111            'https://secure.gravatar.com/%s.json',
112            $hashed_email
113        );
114
115        $response      = wp_remote_get(
116            esc_url_raw( $profile_url ),
117            array( 'User-Agent' => 'Jetpack Plugin Gravatar Profile Shortcode' )
118        );
119        $response_code = wp_remote_retrieve_response_code( $response );
120        $expire        = 300; // Cache any errors for 5 minutes.
121        $profile       = array();
122
123        if ( $response_code === 200 ) {
124            $profile = json_decode( wp_remote_retrieve_body( $response ), true );
125
126            if (
127                is_array( $profile )
128                && ! empty( $profile['entry'] )
129                && is_array( $profile['entry'] )
130            ) {
131                // Sucessfully fetched the profile. Cache for 15 minutes.
132                $expire  = 900;
133                $profile = $profile['entry'][0];
134            }
135        }
136
137        set_transient( $cache_key, $profile, $expire );
138    }
139
140    // Fetching the profile returned an error. Bail.
141    if ( empty( $profile ) ) {
142        return false;
143    }
144
145    // Render the shortcode.
146    $gravatar_url     = 'https://gravatar.com/' . $hashed_email;
147    $user_location    = ! empty( $profile['currentLocation'] ) ? $profile['currentLocation'] : '';
148    $display_name     = ! empty( $profile['displayName'] ) ? $profile['displayName'] : '';
149    $user_description = ! empty( $profile['aboutMe'] ) ? $profile['aboutMe'] : '';
150
151    if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
152        $gravatar_url = 'https://gravatar.com/' . $user->user_login;
153        $avatar_url   = wpcom_get_avatar_url( $user->ID, 96 );
154        $avatar_url   = $avatar_url[0];
155    } else {
156        $avatar_url = get_avatar_url( $user->user_email, array( 'size' => 96 ) );
157    }
158
159    ob_start();
160
161    if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
162        wp_enqueue_style( 'gravatar-style', plugins_url( '/css/gravatar-amp.css', __FILE__ ), array(), JETPACK__VERSION );
163    } else {
164        ?>
165        <script type="text/javascript">
166        ( function() {
167            if ( null === document.getElementById( 'gravatar-profile-embed-styles' ) ) {
168                var headID = document.getElementsByTagName( 'head' )[0];
169                var styleNode = document.createElement( 'style' );
170                styleNode.type = 'text/css';
171                styleNode.id = 'gravatar-profile-embed-styles';
172
173                var gCSS = '.grofile-wrap { border: solid 1px #f0f0f1; padding: 10px; } .grofile { padding: 0 0 5px 0; }  .grofile-left { float: left; display: block; width: 96px; margin-right: 15px; } .grofile .gravatar { margin-bottom: 5px; } .grofile-clear { clear: left; font-size: 1px; height: 1px; } .grofile ul li a { text-indent: -99999px; } .grofile .grofile-left a:hover { text-decoration: none !important; border: none !important; } .grofile-name { margin-top: 0; }';
174
175                if ( document.all ) {
176                    styleNode.innerText = gCSS;
177                } else {
178                    styleNode.textContent = gCSS;
179                }
180
181                headID.appendChild( styleNode );
182            }
183        } )();
184        </script>
185        <?php
186    }
187    ?>
188
189    <div class="grofile vcard" id="grofile-embed-<?php echo esc_attr( $instance ); ?>">
190        <div class="grofile-inner">
191            <div class="grofile-left">
192                <div class="grofile-img">
193                    <a href="<?php echo esc_url( $gravatar_url ); ?>">
194                        <img src="<?php echo esc_url( $avatar_url ); ?>" width="96" height="96" class="no-grav gravatar photo" />
195                    </a>
196                </div>
197            </div>
198            <div class="grofile-right">
199                <p class="grofile-name fn">
200                    <strong><?php echo esc_html( $display_name ); ?></strong>
201                    <?php
202                    if ( ! empty( $user_location ) ) :
203                        ?>
204                        <br><span class="grofile-location adr"><?php echo esc_html( $user_location ); ?></span><?php endif; ?>
205                </p>
206                <p class="grofile-bio">
207                    <strong><?php esc_html_e( 'Bio:', 'jetpack' ); ?></strong> <?php echo wp_kses_post( $user_description ); ?>
208                </p>
209                <p class="grofile-view">
210                    <a href="<?php echo esc_url( $gravatar_url ); ?>"><?php esc_html_e( 'View complete profile', 'jetpack' ); ?></a>
211                </p>
212            </div>
213            <span class="grofile-clear">&nbsp;</span>
214        </div>
215    </div>
216    <?php
217
218    // Increment and return the rendered profile.
219    ++$instance;
220
221    return ob_get_clean();
222}