Skip to:
Content

BuddyPress.org

Ticket #8356: bp-core-avatars.php

File bp-core-avatars.php, 66.6 KB (added by shawfactor, 5 years ago)

New file with the filetr order swapped (it is more logical and useful that way)

Line 
1<?php
2/**
3 * BuddyPress Avatars.
4 *
5 * @package BuddyPress
6 * @subpackage Core
7 * @since 1.0.0
8 */
9
10// Exit if accessed directly.
11defined( 'ABSPATH' ) || exit;
12
13/**
14 * Set up the constants we need for avatar support.
15 *
16 * @since 1.2.0
17 */
18function bp_core_set_avatar_constants() {
19
20        $bp = buddypress();
21
22        if ( !defined( 'BP_AVATAR_THUMB_WIDTH' ) )
23                define( 'BP_AVATAR_THUMB_WIDTH', 50 );
24
25        if ( !defined( 'BP_AVATAR_THUMB_HEIGHT' ) )
26                define( 'BP_AVATAR_THUMB_HEIGHT', 50 );
27
28        if ( !defined( 'BP_AVATAR_FULL_WIDTH' ) )
29                define( 'BP_AVATAR_FULL_WIDTH', 150 );
30
31        if ( !defined( 'BP_AVATAR_FULL_HEIGHT' ) )
32                define( 'BP_AVATAR_FULL_HEIGHT', 150 );
33
34        if ( !defined( 'BP_AVATAR_ORIGINAL_MAX_WIDTH' ) )
35                define( 'BP_AVATAR_ORIGINAL_MAX_WIDTH', 450 );
36
37        if ( !defined( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE' ) ) {
38                define( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE', bp_attachments_get_max_upload_file_size( 'avatar' ) );
39        }
40
41        if ( ! defined( 'BP_SHOW_AVATARS' ) ) {
42                define( 'BP_SHOW_AVATARS', bp_get_option( 'show_avatars' ) );
43        }
44}
45add_action( 'bp_init', 'bp_core_set_avatar_constants', 3 );
46
47/**
48 * Set up global variables related to avatars.
49 *
50 * @since 1.5.0
51 */
52function bp_core_set_avatar_globals() {
53        $bp = buddypress();
54
55        $bp->avatar        = new stdClass;
56        $bp->avatar->thumb = new stdClass;
57        $bp->avatar->full  = new stdClass;
58
59        // Dimensions.
60        $bp->avatar->thumb->width  = BP_AVATAR_THUMB_WIDTH;
61        $bp->avatar->thumb->height = BP_AVATAR_THUMB_HEIGHT;
62        $bp->avatar->full->width   = BP_AVATAR_FULL_WIDTH;
63        $bp->avatar->full->height  = BP_AVATAR_FULL_HEIGHT;
64
65        // Upload maximums.
66        $bp->avatar->original_max_width    = BP_AVATAR_ORIGINAL_MAX_WIDTH;
67        $bp->avatar->original_max_filesize = BP_AVATAR_ORIGINAL_MAX_FILESIZE;
68
69        // Defaults.
70        $bp->avatar->thumb->default = bp_core_avatar_default_thumb();
71        $bp->avatar->full->default  = bp_core_avatar_default();
72
73        // These have to be set on page load in order to avoid infinite filter loops at runtime.
74        $bp->avatar->upload_path = bp_core_avatar_upload_path();
75        $bp->avatar->url = bp_core_avatar_url();
76
77        // Cache the root blog's show_avatars setting, to avoid unnecessary
78        // calls to switch_to_blog().
79        $bp->avatar->show_avatars = (bool) BP_SHOW_AVATARS;
80
81        // Backpat for pre-1.5.
82        if ( ! defined( 'BP_AVATAR_UPLOAD_PATH' ) )
83                define( 'BP_AVATAR_UPLOAD_PATH', $bp->avatar->upload_path );
84
85        // Backpat for pre-1.5.
86        if ( ! defined( 'BP_AVATAR_URL' ) )
87                define( 'BP_AVATAR_URL', $bp->avatar->url );
88
89        /**
90         * Fires at the end of the core avatar globals setup.
91         *
92         * @since 1.5.0
93         */
94        do_action( 'bp_core_set_avatar_globals' );
95}
96add_action( 'bp_setup_globals', 'bp_core_set_avatar_globals' );
97
98/**
99 * Get an avatar for a BuddyPress object.
100 *
101 * Supports avatars for users, groups, and blogs by default, but can be
102 * extended to support custom components as well.
103 *
104 * This function gives precedence to locally-uploaded avatars. When a local
105 * avatar is not found, Gravatar is queried. To disable Gravatar fallbacks
106 * locally:
107 *    add_filter( 'bp_core_fetch_avatar_no_grav', '__return_true' );
108 *
109 * @since 1.1.0
110 * @since 2.4.0 Added 'extra_attr', 'scheme', 'rating' and 'force_default' for $args.
111 *              These are inherited from WordPress 4.2.0. See {@link get_avatar()}.
112 *
113 * @param array|string $args {
114 *     An array of arguments. All arguments are technically optional; some
115 *     will, if not provided, be auto-detected by bp_core_fetch_avatar(). This
116 *     auto-detection is described more below, when discussing specific
117 *     arguments.
118 *
119 *     @type int|bool    $item_id    The numeric ID of the item for which you're requesting
120 *                                   an avatar (eg, a user ID). If no 'item_id' is present,
121 *                                   the function attempts to infer an ID from the 'object' + the
122 *                                   current context: if 'object' is 'user' and the current page is a
123 *                                   user page, 'item_id' will default to the displayed user ID; if
124 *                                   'group' and on a group page, to the current group ID; if 'blog',
125 *                                   to the current blog's ID. If no 'item_id' can be determined in
126 *                                   this way, the function returns false. Default: false.
127 *     @type string      $object     The kind of object for which you're getting an
128 *                                   avatar. BuddyPress natively supports three options: 'user',
129 *                                   'group', 'blog'; a plugin may register more.  Default: 'user'.
130 *     @type string      $type       When a new avatar is uploaded to BP, 'thumb' and
131 *                                   'full' versions are saved. This parameter specifies whether you'd
132 *                                   like the 'full' or smaller 'thumb' avatar. Default: 'thumb'.
133 *     @type string|bool $avatar_dir The name of the subdirectory where the
134 *                                   requested avatar should be found. If no value is passed,
135 *                                   'avatar_dir' is inferred from 'object': 'user' becomes 'avatars',
136 *                                   'group' becomes 'group-avatars', 'blog' becomes 'blog-avatars'.
137 *                                   Remember that this string denotes a subdirectory of BP's main
138 *                                   avatar directory (usually based on {@link wp_upload_dir()}); it's a
139 *                                   string like 'group-avatars' rather than the full directory path.
140 *                                   Generally, it'll only be necessary to override the default value if
141 *                                   storing avatars in a non-default location. Defaults to false
142 *                                   (auto-detected).
143 *     @type int|bool    $width      Requested avatar width. The unit is px. This value
144 *                                   is used to build the 'width' attribute for the <img> element. If
145 *                                   no value is passed, BP uses the global avatar width for this
146 *                                   avatar type. Default: false (auto-detected).
147 *     @type int|bool    $height     Requested avatar height. The unit is px. This
148 *                                   value is used to build the 'height' attribute for the <img>
149 *                                   element. If no value is passed, BP uses the global avatar height
150 *                                   for this avatar type. Default: false (auto-detected).
151 *     @type string      $class      The CSS class for the <img> element. Note that BP
152 *                                   uses the 'avatar' class fairly extensively in its default styling,
153 *                                   so if you plan to pass a custom value, consider appending it to
154 *                                   'avatar' (eg 'avatar foo') rather than replacing it altogether.
155 *                                   Default: 'avatar'.
156 *     @type string|bool $css_id     The CSS id for the <img> element.
157 *                                   Default: false.
158 *     @type string      $title      The title attribute for the <img> element.
159 *                                   Default: false.
160 *     @type string      $alt        The alt attribute for the <img> element. In BP, this
161 *                                   value is generally passed by the wrapper functions, where the data
162 *                                   necessary for concatenating the string is at hand; see
163 *                                   {@link bp_get_activity_avatar()} for an example. Default: ''.
164 *     @type string|bool $email      An email to use in Gravatar queries. Unless
165 *                                   otherwise configured, BP uses Gravatar as a fallback for avatars
166 *                                   that are not provided locally. Gravatar's API requires using a hash
167 *                                   of the user's email address; this argument provides it. If not
168 *                                   provided, the function will infer it: for users, by getting the
169 *                                   user's email from the database, for groups/blogs, by concatenating
170 *                                   "{$item_id}-{$object}@{bp_get_root_domain()}". The user query adds
171 *                                   overhead, so it's recommended that wrapper functions provide a
172 *                                   value for 'email' when querying user IDs. Default: false.
173 *     @type bool       $no_grav     Whether to disable the default Gravatar fallback.
174 *                                   By default, BP will fall back on Gravatar when it cannot find a
175 *                                   local avatar. In some cases, this may be undesirable, in which
176 *                                   case 'no_grav' should be set to true. To disable Gravatar
177 *                                   fallbacks globally, see the 'bp_core_fetch_avatar_no_grav' filter.
178 *                                   Default: true for groups, otherwise false.
179 *     @type bool       $html        Whether to return an <img> HTML element, vs a raw URL
180 *                                   to an avatar. If false, <img>-specific arguments (like 'css_id')
181 *                                   will be ignored. Default: true.
182 *     @type string     $extra_attr  HTML attributes to insert in the IMG element. Not sanitized. Default: ''.
183 *     @type string     $scheme      URL scheme to use. See set_url_scheme() for accepted values.
184 *                                   Default null.
185 *     @type string     $rating      What rating to display Gravatars for. Accepts 'G', 'PG', 'R', 'X'.
186 *                                   Default is the value of the 'avatar_rating' option.
187 *     @type bool       $force_default Used when creating the Gravatar URL. Whether to force the default
188 *                                     image regardless if the Gravatar exists. Default: false.
189 * }
190 * @return string Formatted HTML <img> element, or raw avatar URL based on $html arg.
191 */
192function bp_core_fetch_avatar( $args = '' ) {
193        $bp = buddypress();
194
195        // If avatars are disabled for the root site, obey that request and bail.
196        if ( ! $bp->avatar || ! $bp->avatar->show_avatars ) {
197                return;
198        }
199
200        // Set the default variables array and parse it against incoming $args array.
201        $params = wp_parse_args( $args, array(
202                'item_id'       => false,
203                'object'        => 'user',
204                'type'          => 'thumb',
205                'avatar_dir'    => false,
206                'width'         => false,
207                'height'        => false,
208                'class'         => 'avatar',
209                'css_id'        => false,
210                'alt'           => '',
211                'email'         => false,
212                'no_grav'       => null,
213                'html'          => true,
214                'title'         => '',
215                'extra_attr'    => '',
216                'scheme'        => null,
217                'rating'        => get_option( 'avatar_rating' ),
218                'force_default' => false,
219        ) );
220
221        /* Set item_id ***********************************************************/
222
223        if ( empty( $params['item_id'] ) ) {
224
225                switch ( $params['object'] ) {
226
227                        case 'blog'  :
228                                $params['item_id'] = get_current_blog_id();
229                                break;
230
231                        case 'group' :
232                                if ( bp_is_active( 'groups' ) ) {
233                                        $params['item_id'] = $bp->groups->current_group->id;
234                                } else {
235                                        $params['item_id'] = false;
236                                }
237
238                                break;
239
240                        case 'user'  :
241                        default      :
242                                $params['item_id'] = bp_displayed_user_id();
243                                break;
244                }
245
246                /**
247                 * Filters the ID of the item being requested.
248                 *
249                 * @since 1.1.0
250                 *
251                 * @param string $value  ID of avatar item being requested.
252                 * @param string $value  Avatar type being requested.
253                 * @param array  $params Array of parameters for the request.
254                 */
255                $params['item_id'] = apply_filters( 'bp_core_avatar_item_id', $params['item_id'], $params['object'], $params );
256
257                if ( empty( $params['item_id'] ) ) {
258                        return false;
259                }
260        }
261
262        /* Set avatar_dir ********************************************************/
263
264        if ( empty( $params['avatar_dir'] ) ) {
265
266                switch ( $params['object'] ) {
267
268                        case 'blog'  :
269                                $params['avatar_dir'] = 'blog-avatars';
270                                break;
271
272                        case 'group' :
273                                if ( bp_is_active( 'groups' ) ) {
274                                        $params['avatar_dir'] = 'group-avatars';
275                                } else {
276                                        $params['avatar_dir'] = false;
277                                }
278
279                                break;
280
281                        case 'user'  :
282                        default      :
283                                $params['avatar_dir'] = 'avatars';
284                                break;
285                }
286
287                /**
288                 * Filters the avatar directory to use.
289                 *
290                 * @since 1.1.0
291                 *
292                 * @param string $value  Name of the subdirectory where the requested avatar should be found.
293                 * @param string $value  Avatar type being requested.
294                 * @param array  $params Array of parameters for the request.
295                 */
296                $params['avatar_dir'] = apply_filters( 'bp_core_avatar_dir', $params['avatar_dir'], $params['object'], $params );
297
298                if ( empty( $params['avatar_dir'] ) ) {
299                        return false;
300                }
301        }
302
303        /* <img> alt *************************************************************/
304
305        if ( false !== strpos( $params['alt'], '%s' ) || false !== strpos( $params['alt'], '%1$s' ) ) {
306
307                switch ( $params['object'] ) {
308
309                        case 'blog'  :
310                                $item_name = get_blog_option( $params['item_id'], 'blogname' );
311                                break;
312
313                        case 'group' :
314                                $item_name = bp_get_group_name( groups_get_group( $params['item_id'] ) );
315                                break;
316
317                        case 'user'  :
318                        default :
319                                $item_name = bp_core_get_user_displayname( $params['item_id'] );
320                                break;
321                }
322
323                /**
324                 * Filters the alt attribute value to be applied to avatar.
325                 *
326                 * @since 1.5.0
327                 *
328                 * @param string $value  alt to be applied to avatar.
329                 * @param string $value  ID of avatar item being requested.
330                 * @param string $value  Avatar type being requested.
331                 * @param array  $params Array of parameters for the request.
332                 */
333                $item_name = apply_filters( 'bp_core_avatar_alt', $item_name, $params['item_id'], $params['object'], $params );
334                $params['alt'] = sprintf( $params['alt'], $item_name );
335        }
336
337        /* Sanity Checks *********************************************************/
338
339        // Get a fallback for the 'alt' parameter, create html output.
340        if ( empty( $params['alt'] ) ) {
341                $params['alt'] = __( 'Profile Photo', 'buddypress' );
342        }
343        $html_alt = ' alt="' . esc_attr( $params['alt'] ) . '"';
344
345        // Filter image title and create html string.
346        $html_title = '';
347
348        /**
349         * Filters the title attribute value to be applied to avatar.
350         *
351         * @since 1.5.0
352         *
353         * @param string $value  Title to be applied to avatar.
354         * @param string $value  ID of avatar item being requested.
355         * @param string $value  Avatar type being requested.
356         * @param array  $params Array of parameters for the request.
357         */
358        $params['title'] = apply_filters( 'bp_core_avatar_title', $params['title'], $params['item_id'], $params['object'], $params );
359
360        if ( ! empty( $params['title'] ) ) {
361                $html_title = ' title="' . esc_attr( $params['title'] ) . '"';
362        }
363
364        // Extra attributes.
365        $extra_attr = ! empty( $args['extra_attr'] ) ? ' ' . $args['extra_attr'] : '';
366
367        // Set CSS ID and create html string.
368        $html_css_id = '';
369
370        /**
371         * Filters the ID attribute to be applied to avatar.
372         *
373         * @since 2.2.0
374         *
375         * @param string $value  ID to be applied to avatar.
376         * @param string $value  ID of avatar item being requested.
377         * @param string $value  Avatar type being requested.
378         * @param array  $params Array of parameters for the request.
379         */
380        $params['css_id'] = apply_filters( 'bp_core_css_id', $params['css_id'], $params['item_id'], $params['object'], $params );
381
382        if ( ! empty( $params['css_id'] ) ) {
383                $html_css_id = ' id="' . esc_attr( $params['css_id'] ) . '"';
384        }
385
386        // Set image width.
387        if ( false !== $params['width'] ) {
388                // Width has been specified. No modification necessary.
389        } elseif ( 'thumb' == $params['type'] ) {
390                $params['width'] = bp_core_avatar_thumb_width();
391        } else {
392                $params['width'] = bp_core_avatar_full_width();
393        }
394        $html_width = ' width="' . $params['width'] . '"';
395
396        // Set image height.
397        if ( false !== $params['height'] ) {
398                // Height has been specified. No modification necessary.
399        } elseif ( 'thumb' == $params['type'] ) {
400                $params['height'] = bp_core_avatar_thumb_height();
401        } else {
402                $params['height'] = bp_core_avatar_full_height();
403        }
404        $html_height = ' height="' . $params['height'] . '"';
405
406        /**
407         * Filters the classes to be applied to the avatar.
408         *
409         * @since 1.6.0
410         *
411         * @param array|string $value  Class(es) to be applied to the avatar.
412         * @param string       $value  ID of the avatar item being requested.
413         * @param string       $value  Avatar type being requested.
414         * @param array        $params Array of parameters for the request.
415         */
416        $params['class'] = apply_filters( 'bp_core_avatar_class', $params['class'], $params['item_id'], $params['object'], $params );
417
418        // Use an alias to leave the param unchanged.
419        $avatar_classes = $params['class'];
420        if ( ! is_array( $avatar_classes ) ) {
421                $avatar_classes = explode( ' ', $avatar_classes );
422        }
423
424        // Merge classes.
425        $avatar_classes = array_merge( $avatar_classes, array(
426                $params['object'] . '-' . $params['item_id'] . '-avatar',
427                'avatar-' . $params['width'],
428        ) );
429
430        // Sanitize each class.
431        $avatar_classes = array_map( 'sanitize_html_class', $avatar_classes );
432
433        // Populate the class attribute.
434        $html_class = ' class="' . join( ' ', $avatar_classes ) . ' photo"';
435
436        // Set img URL and DIR based on prepopulated constants.
437        $avatar_loc        = new stdClass();
438        $avatar_loc->path  = trailingslashit( bp_core_avatar_upload_path() );
439        $avatar_loc->url   = trailingslashit( bp_core_avatar_url() );
440
441        $avatar_loc->dir   = trailingslashit( $params['avatar_dir'] );
442
443        /**
444         * Filters the avatar folder directory path.
445         *
446         * @since 1.1.0
447         *
448         * @param string $value Path to the avatar folder directory.
449         * @param int    $value ID of the avatar item being requested.
450         * @param string $value Avatar type being requested.
451         * @param string $value Subdirectory where the requested avatar should be found.
452         */
453        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', ( $avatar_loc->path . $avatar_loc->dir . $params['item_id'] ), $params['item_id'], $params['object'], $params['avatar_dir'] );
454
455        /**
456         * Filters the avatar folder directory URL.
457         *
458         * @since 1.1.0
459         *
460         * @param string $value Path to the avatar folder URL.
461         * @param int    $value ID of the avatar item being requested.
462         * @param string $value Avatar type being requested.
463         * @param string $value Subdirectory where the requested avatar should be found.
464         */
465        $avatar_folder_url = apply_filters( 'bp_core_avatar_folder_url', ( $avatar_loc->url  . $avatar_loc->dir . $params['item_id'] ), $params['item_id'], $params['object'], $params['avatar_dir'] );
466
467        /**
468         * Look for uploaded avatar first. Use it if it exists.
469         * Set the file names to search for, to select the full size
470         * or thumbnail image.
471         */
472        $avatar_size              = ( 'full' == $params['type'] ) ? '-bpfull' : '-bpthumb';
473        $legacy_user_avatar_name  = ( 'full' == $params['type'] ) ? '-avatar2' : '-avatar1';
474        $legacy_group_avatar_name = ( 'full' == $params['type'] ) ? '-groupavatar-full' : '-groupavatar-thumb';
475       
476
477
478        // Check for directory.
479        if ( ! $params['force_default'] && file_exists( $avatar_folder_dir ) ) {
480           
481
482
483                // Open directory.
484                if ( $av_dir = opendir( $avatar_folder_dir ) ) {
485
486                        // Stash files in an array once to check for one that matches.
487                        $avatar_files = array();
488                        while ( false !== ( $avatar_file = readdir( $av_dir ) ) ) {
489                                // Only add files to the array (skip directories).
490                                if ( 2 < strlen( $avatar_file ) ) {
491                                        $avatar_files[] = $avatar_file;
492                                }
493                        }
494
495                        // Check for array.
496                        if ( 0 < count( $avatar_files ) ) {
497
498                                // Check for current avatar.
499                                foreach( $avatar_files as $key => $value ) {
500                                        if ( strpos ( $value, $avatar_size )!== false ) {
501                                                $avatar_url = $avatar_folder_url . '/' . $avatar_files[$key];
502                                        }
503                                }
504
505                                // Legacy avatar check.
506                                if ( !isset( $avatar_url ) ) {
507                                        foreach( $avatar_files as $key => $value ) {
508                                                if ( strpos ( $value, $legacy_user_avatar_name )!== false ) {
509                                                        $avatar_url = $avatar_folder_url . '/' . $avatar_files[$key];
510                                                }
511                                        }
512
513                                        // Legacy group avatar check.
514                                        if ( !isset( $avatar_url ) ) {
515                                                foreach( $avatar_files as $key => $value ) {
516                                                        if ( strpos ( $value, $legacy_group_avatar_name )!== false ) {
517                                                                $avatar_url = $avatar_folder_url . '/' . $avatar_files[$key];
518                                                        }
519                                                }
520                                        }
521                                }
522                        }
523                }
524
525                // Close the avatar directory.
526                closedir( $av_dir );
527
528                // If we found a locally uploaded avatar.
529                if ( isset( $avatar_url ) ) {
530                        // Support custom scheme.
531                        $avatar_url = set_url_scheme( $avatar_url, $params['scheme'] );
532
533                        // Return it wrapped in an <img> element.
534                        if ( true === $params['html'] ) {
535
536                                /**
537                                 * Filters an avatar URL wrapped in an <img> element.
538                                 *
539                                 * @since 1.1.0
540                                 *
541                                 * @param string $value             Full <img> element for an avatar.
542                                 * @param array  $params            Array of parameters for the request.
543                                 * @param string $value             ID of the item requested.
544                                 * @param string $value             Subdirectory where the requested avatar should be found.
545                                 * @param string $html_css_id       ID attribute for avatar.
546                                 * @param string $html_width        Width attribute for avatar.
547                                 * @param string $html_height       Height attribute for avatar.
548                                 * @param string $avatar_folder_url Avatar URL path.
549                                 * @param string $avatar_folder_dir Avatar DIR path.
550                                 */
551                                return apply_filters( 'bp_core_fetch_avatar', '<img src="' . $avatar_url . '"' . $html_class . $html_css_id  . $html_width . $html_height . $html_alt . $html_title . $extra_attr . ' />', $params, $params['item_id'], $params['avatar_dir'], $html_css_id, $html_width, $html_height, $avatar_folder_url, $avatar_folder_dir );
552
553                        // ...or only the URL
554                        } else {
555
556                                /**
557                                 * Filters a locally uploaded avatar URL.
558                                 *
559                                 * @since 1.2.5
560                                 *
561                                 * @param string $avatar_url URL for a locally uploaded avatar.
562                                 * @param array  $params     Array of parameters for the request.
563                                 */
564                                return apply_filters( 'bp_core_fetch_avatar_url', $avatar_url, $params );
565                        }
566                }
567        }
568
569        // By default, Gravatar is not pinged for groups.
570        if ( null === $params['no_grav'] ) {
571                $params['no_grav'] = 'group' === $params['object'];
572        }
573
574        /**
575         * Filters whether or not to skip Gravatar check.
576         *
577         * @since 1.5.0
578         *
579         * @param bool  $value  Whether or not to skip Gravatar.
580         * @param array $params Array of parameters for the avatar request.
581         */
582        if ( ! apply_filters( 'bp_core_fetch_avatar_no_grav', $params['no_grav'], $params ) ) {
583
584                // Set gravatar type.
585                if ( empty( $bp->grav_default->{$params['object']} ) ) {
586                        $default_grav = 'wavatar';
587                } elseif ( 'mystery' == $bp->grav_default->{$params['object']} ) {
588
589                        /**
590                         * Filters the Mystery person avatar src value.
591                         *
592                         * @since 1.2.0
593                         *
594                         * @param string $value Avatar value.
595                         * @param string $value Width to display avatar at.
596                         */
597                        $default_grav = apply_filters( 'bp_core_mysteryman_src', 'mm', $params['width'] );
598                } else {
599                        $default_grav = $bp->grav_default->{$params['object']};
600                }
601
602                // Set gravatar object.
603                if ( empty( $params['email'] ) ) {
604                        if ( 'user' == $params['object'] ) {
605                                $params['email'] = bp_core_get_user_email( $params['item_id'] );
606                        } elseif ( 'group' == $params['object'] || 'blog' == $params['object'] ) {
607                                $params['email'] = $params['item_id'] . '-' . $params['object'] . '@' . bp_get_root_domain();
608                        }
609                }
610
611                /**
612                 * Filters the Gravatar email to use.
613                 *
614                 * @since 1.1.0
615                 *
616                 * @param string $value Email to use in Gravatar request.
617                 * @param string $value ID of the item being requested.
618                 * @param string $value Object type being requested.
619                 */
620                $params['email'] = apply_filters( 'bp_core_gravatar_email', $params['email'], $params['item_id'], $params['object'] );
621
622                /**
623                 * Filters the Gravatar URL host.
624                 *
625                 * @since 1.0.2
626                 *
627                 * @param string $value Gravatar URL host.
628                 */
629                $gravatar = apply_filters( 'bp_gravatar_url', '//www.gravatar.com/avatar/' );
630
631                // Append email hash to Gravatar.
632                $gravatar .=  md5( strtolower( $params['email'] ) );
633
634                // Main Gravatar URL args.
635                $url_args = array(
636                        's' => $params['width']
637                );
638
639                // Custom Gravatar URL args.
640                if ( ! empty( $params['force_default'] ) ) {
641                        $url_args['f'] = 'y';
642                        $url_args['d'] = $params['default'];
643                }
644                if ( ! empty( $params['rating'] ) ) {
645                        $url_args['r'] = strtolower( $params['rating'] );
646                }
647
648                /**
649                 * Filters the Gravatar "d" parameter.
650                 *
651                 * @since 2.6.0
652                 *
653                 * @param string $default_grav The avatar default.
654                 * @param array  $params       The avatar's data.
655                 */
656                $default_grav = apply_filters( 'bp_core_avatar_default', $default_grav, $params );
657
658                // Only set default image if 'Gravatar Logo' is not requested.
659                if ( ! $params['force_default'] && 'gravatar_default' !== $default_grav ) {
660                        $url_args['d'] = $default_grav;
661                }
662
663                // Set up the Gravatar URL.
664                $gravatar = esc_url( add_query_arg(
665                        rawurlencode_deep( array_filter( $url_args ) ),
666                        $gravatar
667                ) );
668
669        // No avatar was found, and we've been told not to use a gravatar.
670        } else {
671
672                /**
673                 * Filters the avatar default when Gravatar is not used.
674                 *
675                 * This is a variable filter dependent on the avatar type being requested.
676                 *
677                 * @since 1.5.0
678                 *
679                 * @param string $value  Default avatar for non-gravatar requests.
680                 * @param array  $params Array of parameters for the avatar request.
681                 */
682                $gravatar = apply_filters( 'bp_core_default_avatar_' . $params['object'], bp_core_avatar_default( 'local', $params ), $params );
683        }
684
685        if ( true === $params['html'] ) {
686
687                /** This filter is documented in bp-core/bp-core-avatars.php */
688                return apply_filters( 'bp_core_fetch_avatar', '<img src="' . $gravatar . '"' . $html_css_id . $html_class . $html_width . $html_height . $html_alt . $html_title . $extra_attr . ' />', $params, $params['item_id'], $params['avatar_dir'], $html_css_id, $html_width, $html_height, $avatar_folder_url, $avatar_folder_dir );
689        } else {
690
691                /** This filter is documented in bp-core/bp-core-avatars.php */
692                return apply_filters( 'bp_core_fetch_avatar_url', $gravatar, $params );
693        }
694}
695
696/**
697 * Delete an existing avatar.
698 *
699 * @since 1.1.0
700 *
701 * @param array|string $args {
702 *     Array of function parameters.
703 *     @type bool|int    $item_id    ID of the item whose avatar you're deleting.
704 *                                   Defaults to the current item of type $object.
705 *     @type string      $object     Object type of the item whose avatar you're
706 *                                   deleting. 'user', 'group', 'blog', or custom.
707 *                                   Default: 'user'.
708 *     @type bool|string $avatar_dir Subdirectory where avatar is located.
709 *                                   Default: false, which falls back on the default location
710 *                                   corresponding to the $object.
711 * }
712 * @return bool True on success, false on failure.
713 */
714function bp_core_delete_existing_avatar( $args = '' ) {
715
716        $defaults = array(
717                'item_id'    => false,
718                'object'     => 'user', // User OR group OR blog OR custom type (if you use filters).
719                'avatar_dir' => false
720        );
721
722        $args = wp_parse_args( $args, $defaults );
723
724        /**
725         * Filters whether or not to handle deleting an existing avatar.
726         *
727         * If you want to override this function, make sure you return false.
728         *
729         * @since 2.5.1
730         *
731         * @param bool  $value Whether or not to delete the avatar.
732         * @param array $args {
733         *     Array of function parameters.
734         *
735         *     @type bool|int    $item_id    ID of the item whose avatar you're deleting.
736         *                                   Defaults to the current item of type $object.
737         *     @type string      $object     Object type of the item whose avatar you're
738         *                                   deleting. 'user', 'group', 'blog', or custom.
739         *                                   Default: 'user'.
740         *     @type bool|string $avatar_dir Subdirectory where avatar is located.
741         *                                   Default: false, which falls back on the default location
742         *                                   corresponding to the $object.
743         * }
744         */
745        if ( ! apply_filters( 'bp_core_pre_delete_existing_avatar', true, $args ) ) {
746                return true;
747        }
748
749        if ( empty( $args['item_id'] ) ) {
750                if ( 'user' === $args['object'] ) {
751                        $args['item_id'] = bp_displayed_user_id();
752                } elseif ( 'group' === $args['object'] ) {
753                        $args['item_id'] = buddypress()->groups->current_group->id;
754                } elseif ( 'blog' === $args['object'] ) {
755                        $args['item_id'] = get_current_blog_id();
756                }
757
758                /** This filter is documented in bp-core/bp-core-avatars.php */
759                $item_id = apply_filters( 'bp_core_avatar_item_id', $args['item_id'], $args['object'] );
760        } else {
761                $item_id = $args['item_id'];
762        }
763
764        if ( $item_id && ( ctype_digit( $item_id ) || is_int( $item_id ) ) ) {
765                $item_id = (int) $item_id;
766        } else {
767                return false;
768        }
769
770        if ( empty( $args['avatar_dir'] ) ) {
771                if ( 'user' === $args['object'] ) {
772                        $args['avatar_dir'] = 'avatars';
773                } elseif ( 'group' === $args['object'] ) {
774                        $args['avatar_dir'] = 'group-avatars';
775                } elseif ( 'blog' === $args['object'] ) {
776                        $args['avatar_dir'] = 'blog-avatars';
777                }
778
779                /** This filter is documented in bp-core/bp-core-avatars.php */
780                $avatar_dir = apply_filters( 'bp_core_avatar_dir', $args['avatar_dir'], $args['object'] );
781        } else {
782                $avatar_dir = $args['avatar_dir'];
783        }
784
785        if ( ! $avatar_dir ) {
786                return false;
787        }
788
789        /** This filter is documented in bp-core/bp-core-avatars.php */
790        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', bp_core_avatar_upload_path() . '/' . $avatar_dir . '/' . $item_id, $item_id, $args['object'], $avatar_dir );
791
792        if ( ! is_dir( $avatar_folder_dir ) ) {
793                return false;
794        }
795
796        if ( $av_dir = opendir( $avatar_folder_dir ) ) {
797                while ( false !== ( $avatar_file = readdir( $av_dir ) ) ) {
798                        if ( ( preg_match( "/-bpfull/", $avatar_file ) || preg_match( "/-bpthumb/", $avatar_file ) ) && '.' != $avatar_file && '..' != $avatar_file ) {
799                                @unlink( $avatar_folder_dir . '/' . $avatar_file );
800                        }
801                }
802        }
803        closedir( $av_dir );
804
805        @rmdir( $avatar_folder_dir );
806
807        /**
808         * Fires after deleting an existing avatar.
809         *
810         * @since 1.1.0
811         *
812         * @param array $args Array of arguments used for avatar deletion.
813         */
814        do_action( 'bp_core_delete_existing_avatar', $args );
815
816        return true;
817}
818
819/**
820 * Ajax delete an avatar for a given object and item id.
821 *
822 * @since 2.3.0
823 *
824 * @return string|null A JSON object containing success data if the avatar was deleted,
825 *                     error message otherwise.
826 */
827function bp_avatar_ajax_delete() {
828        if ( ! bp_is_post_request() ) {
829                wp_send_json_error();
830        }
831
832        $avatar_data = $_POST;
833
834        if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) ) {
835                wp_send_json_error();
836        }
837
838        $nonce = 'bp_delete_avatar_link';
839        if ( 'group' === $avatar_data['object'] ) {
840                $nonce = 'bp_group_avatar_delete';
841        }
842
843        // Check the nonce.
844        check_admin_referer( $nonce, 'nonce' );
845
846        // Capability check.
847        if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) {
848                wp_send_json_error();
849        }
850
851        // Handle delete.
852        if ( bp_core_delete_existing_avatar( array( 'item_id' => $avatar_data['item_id'], 'object' => $avatar_data['object'] ) ) ) {
853                $return = array(
854                        'avatar' => esc_url( bp_core_fetch_avatar( array(
855                                'object'  => $avatar_data['object'],
856                                'item_id' => $avatar_data['item_id'],
857                                'html'    => false,
858                                'type'    => 'full',
859                        ) ) ),
860                        'feedback_code' => 4,
861                        'item_id'       => $avatar_data['item_id'],
862                );
863
864                wp_send_json_success( $return );
865        } else {
866                wp_send_json_error( array(
867                        'feedback_code' => 3,
868                ) );
869        }
870}
871add_action( 'wp_ajax_bp_avatar_delete', 'bp_avatar_ajax_delete' );
872
873/**
874 * Handle avatar uploading.
875 *
876 * The functions starts off by checking that the file has been uploaded
877 * properly using bp_core_check_avatar_upload(). It then checks that the file
878 * size is within limits, and that it has an accepted file extension (jpg, gif,
879 * png). If everything checks out, crop the image and move it to its real
880 * location.
881 *
882 * @since 1.1.0
883 *
884 * @see bp_core_check_avatar_upload()
885 * @see bp_core_check_avatar_type()
886 *
887 * @param array  $file              The appropriate entry the from $_FILES superglobal.
888 * @param string $upload_dir_filter A filter to be applied to 'upload_dir'.
889 * @return bool True on success, false on failure.
890 */
891function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) {
892
893        /**
894         * Filters whether or not to handle uploading.
895         *
896         * If you want to override this function, make sure you return false.
897         *
898         * @since 1.2.4
899         *
900         * @param bool   $value             Whether or not to crop.
901         * @param array  $file              Appropriate entry from $_FILES superglobal.
902         * @parma string $upload_dir_filter A filter to be applied to 'upload_dir'.
903         */
904        if ( ! apply_filters( 'bp_core_pre_avatar_handle_upload', true, $file, $upload_dir_filter ) ) {
905                return true;
906        }
907
908        // Setup some variables.
909        $bp          = buddypress();
910        $upload_path = bp_core_avatar_upload_path();
911
912        // Upload the file.
913        $avatar_attachment = new BP_Attachment_Avatar();
914        $bp->avatar_admin->original = $avatar_attachment->upload( $file, $upload_dir_filter );
915
916        // In case of an error, stop the process and display a feedback to the user.
917        if ( ! empty( $bp->avatar_admin->original['error'] ) ) {
918                /* translators: %s: the upload error message */
919                bp_core_add_message( sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->original['error'] ), 'error' );
920                return false;
921        }
922
923        // The Avatar UI available width.
924        $ui_available_width = 0;
925
926        // Try to set the ui_available_width using the avatar_admin global.
927        if ( isset( $bp->avatar_admin->ui_available_width ) ) {
928                $ui_available_width = $bp->avatar_admin->ui_available_width;
929        }
930
931        // Maybe resize.
932        $bp->avatar_admin->resized = $avatar_attachment->shrink( $bp->avatar_admin->original['file'], $ui_available_width );
933        $bp->avatar_admin->image   = new stdClass();
934
935        // We only want to handle one image after resize.
936        if ( empty( $bp->avatar_admin->resized ) ) {
937                $bp->avatar_admin->image->file = $bp->avatar_admin->original['file'];
938                $bp->avatar_admin->image->dir  = str_replace( $upload_path, '', $bp->avatar_admin->original['file'] );
939        } else {
940                $bp->avatar_admin->image->file = $bp->avatar_admin->resized['path'];
941                $bp->avatar_admin->image->dir  = str_replace( $upload_path, '', $bp->avatar_admin->resized['path'] );
942                @unlink( $bp->avatar_admin->original['file'] );
943        }
944
945        // Check for WP_Error on what should be an image.
946        if ( is_wp_error( $bp->avatar_admin->image->dir ) ) {
947                /* translators: %s: the upload error message */
948                bp_core_add_message( sprintf( __( 'Upload failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->image->dir->get_error_message() ), 'error' );
949                return false;
950        }
951
952        // If the uploaded image is smaller than the "full" dimensions, throw a warning.
953        if ( $avatar_attachment->is_too_small( $bp->avatar_admin->image->file ) ) {
954                /* translators: 1: the advised width size in pixels. 2: the advised height size in pixels. */
955                bp_core_add_message( sprintf( __( 'You have selected an image that is smaller than recommended. For best results, upload a picture larger than %1$d x %2$d pixels.', 'buddypress' ), bp_core_avatar_full_width(), bp_core_avatar_full_height() ), 'error' );
956        }
957
958        // Set the url value for the image.
959        $bp->avatar_admin->image->url = bp_core_avatar_url() . $bp->avatar_admin->image->dir;
960
961        return true;
962}
963
964/**
965 * Ajax upload an avatar.
966 *
967 * @since 2.3.0
968 *
969 * @return string|null A JSON object containing success data if the upload succeeded
970 *                     error message otherwise.
971 */
972function bp_avatar_ajax_upload() {
973        if ( ! bp_is_post_request() ) {
974                wp_die();
975        }
976
977        /**
978         * Sending the json response will be different if
979         * the current Plupload runtime is html4.
980         */
981        $is_html4 = false;
982        if ( ! empty( $_POST['html4' ] ) ) {
983                $is_html4 = true;
984        }
985
986        // Check the nonce.
987        check_admin_referer( 'bp-uploader' );
988
989        // Init the BuddyPress parameters.
990        $bp_params = array();
991
992        // We need it to carry on.
993        if ( ! empty( $_POST['bp_params' ] ) ) {
994                $bp_params = $_POST['bp_params' ];
995        } else {
996                bp_attachments_json_response( false, $is_html4 );
997        }
998
999        // We need the object to set the uploads dir filter.
1000        if ( empty( $bp_params['object'] ) ) {
1001                bp_attachments_json_response( false, $is_html4 );
1002        }
1003
1004        // Capability check.
1005        if ( ! bp_attachments_current_user_can( 'edit_avatar', $bp_params ) ) {
1006                bp_attachments_json_response( false, $is_html4 );
1007        }
1008
1009        $bp = buddypress();
1010        $bp_params['upload_dir_filter'] = '';
1011        $needs_reset = array();
1012
1013        if ( 'user' === $bp_params['object'] && bp_is_active( 'members' ) ) {
1014                $bp_params['upload_dir_filter'] = 'bp_members_avatar_upload_dir';
1015
1016                if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) {
1017                        $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user );
1018                        $bp->displayed_user->id = $bp_params['item_id'];
1019                }
1020        } elseif ( 'group' === $bp_params['object'] && bp_is_active( 'groups' ) ) {
1021                $bp_params['upload_dir_filter'] = 'groups_avatar_upload_dir';
1022
1023                if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
1024                        $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
1025                        $bp->groups->current_group = groups_get_group( $bp_params['item_id'] );
1026                }
1027        } else {
1028                /**
1029                 * Filter here to deal with other components.
1030                 *
1031                 * @since 2.3.0
1032                 *
1033                 * @var array $bp_params the BuddyPress Ajax parameters.
1034                 */
1035                $bp_params = apply_filters( 'bp_core_avatar_ajax_upload_params', $bp_params );
1036        }
1037
1038        if ( ! isset( $bp->avatar_admin ) ) {
1039                $bp->avatar_admin = new stdClass();
1040        }
1041
1042        /**
1043         * The BuddyPress upload parameters is including the Avatar UI Available width,
1044         * add it to the avatar_admin global for a later use.
1045         */
1046        if ( isset( $bp_params['ui_available_width'] ) ) {
1047                $bp->avatar_admin->ui_available_width =  (int) $bp_params['ui_available_width'];
1048        }
1049
1050        // Upload the avatar.
1051        $avatar = bp_core_avatar_handle_upload( $_FILES, $bp_params['upload_dir_filter'] );
1052
1053        // Reset objects.
1054        if ( ! empty( $needs_reset ) ) {
1055                if ( ! empty( $needs_reset['component'] ) ) {
1056                        $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value'];
1057                } else {
1058                        $bp->{$needs_reset['key']} = $needs_reset['value'];
1059                }
1060        }
1061
1062        // Init the feedback message.
1063        $feedback_message = false;
1064
1065        if ( ! empty( $bp->template_message ) ) {
1066                $feedback_message = $bp->template_message;
1067
1068                // Remove template message.
1069                $bp->template_message      = false;
1070                $bp->template_message_type = false;
1071
1072                @setcookie( 'bp-message', false, time() - 1000, COOKIEPATH, COOKIE_DOMAIN, is_ssl() );
1073                @setcookie( 'bp-message-type', false, time() - 1000, COOKIEPATH, COOKIE_DOMAIN, is_ssl() );
1074        }
1075
1076        if ( empty( $avatar ) ) {
1077                // Default upload error.
1078                $message = __( 'Upload failed.', 'buddypress' );
1079
1080                // Use the template message if set.
1081                if ( ! empty( $feedback_message ) ) {
1082                        $message = $feedback_message;
1083                }
1084
1085                // Upload error reply.
1086                bp_attachments_json_response( false, $is_html4, array(
1087                        'type'    => 'upload_error',
1088                        'message' => $message,
1089                ) );
1090        }
1091
1092        if ( empty( $bp->avatar_admin->image->file ) ) {
1093                bp_attachments_json_response( false, $is_html4 );
1094        }
1095
1096        $uploaded_image = @getimagesize( $bp->avatar_admin->image->file );
1097
1098        // Set the name of the file.
1099        $name = $_FILES['file']['name'];
1100        $name_parts = pathinfo( $name );
1101        $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) );
1102
1103        // Finally return the avatar to the editor.
1104        bp_attachments_json_response( true, $is_html4, array(
1105                'name'      => $name,
1106                'url'       => $bp->avatar_admin->image->url,
1107                'width'     => $uploaded_image[0],
1108                'height'    => $uploaded_image[1],
1109                'feedback'  => $feedback_message,
1110        ) );
1111}
1112add_action( 'wp_ajax_bp_avatar_upload', 'bp_avatar_ajax_upload' );
1113
1114/**
1115 * Handle avatar webcam capture.
1116 *
1117 * @since 2.3.0
1118 *
1119 * @param string $data    Base64 encoded image.
1120 * @param int    $item_id Item to associate.
1121 * @return bool True on success, false on failure.
1122 */
1123function bp_avatar_handle_capture( $data = '', $item_id = 0 ) {
1124        if ( empty( $data ) || empty( $item_id ) ) {
1125                return false;
1126        }
1127
1128        /**
1129         * Filters whether or not to handle avatar webcam capture.
1130         *
1131         * If you want to override this function, make sure you return false.
1132         *
1133         * @since 2.5.1
1134         *
1135         * @param bool   $value   Whether or not to crop.
1136         * @param string $data    Base64 encoded image.
1137         * @param int    $item_id Item to associate.
1138         */
1139        if ( ! apply_filters( 'bp_avatar_pre_handle_capture', true, $data, $item_id ) ) {
1140                return true;
1141        }
1142
1143        $avatar_dir = bp_core_avatar_upload_path() . '/avatars';
1144
1145        // It's not a regular upload, we may need to create this folder.
1146        if ( ! file_exists( $avatar_dir ) ) {
1147                if ( ! wp_mkdir_p( $avatar_dir ) ) {
1148                        return false;
1149                }
1150        }
1151
1152        /**
1153         * Filters the Avatar folder directory.
1154         *
1155         * @since 2.3.0
1156         *
1157         * @param string $avatar_dir Directory for storing avatars.
1158         * @param int    $item_id    ID of the item being acted on.
1159         * @param string $value      Avatar type.
1160         * @param string $value      Avatars word.
1161         */
1162        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $avatar_dir . '/' . $item_id, $item_id, 'user', 'avatars' );
1163
1164        // It's not a regular upload, we may need to create this folder.
1165        if( ! is_dir( $avatar_folder_dir ) ) {
1166                if ( ! wp_mkdir_p( $avatar_folder_dir ) ) {
1167                        return false;
1168                }
1169        }
1170
1171        $original_file = $avatar_folder_dir . '/webcam-capture-' . $item_id . '.png';
1172
1173        if ( file_put_contents( $original_file, $data ) ) {
1174                $avatar_to_crop = str_replace( bp_core_avatar_upload_path(), '', $original_file );
1175
1176                // Crop to default values.
1177                $crop_args = array( 'item_id' => $item_id, 'original_file' => $avatar_to_crop, 'crop_x' => 0, 'crop_y' => 0 );
1178
1179                return bp_core_avatar_handle_crop( $crop_args );
1180        } else {
1181                return false;
1182        }
1183}
1184
1185/**
1186 * Crop an uploaded avatar.
1187 *
1188 * @since 1.1.0
1189 *
1190 * @param array|string $args {
1191 *     Array of function parameters.
1192 *
1193 *     @type string      $object        Object type of the item whose avatar you're
1194 *                                      handling. 'user', 'group', 'blog', or custom.
1195 *                                      Default: 'user'.
1196 *     @type string      $avatar_dir    Subdirectory where avatar should be stored.
1197 *                                      Default: 'avatars'.
1198 *     @type bool|int    $item_id       ID of the item that the avatar belongs to.
1199 *     @type bool|string $original_file Absolute path to the original avatar file.
1200 *     @type int         $crop_w        Crop width. Default: the global 'full' avatar width,
1201 *                                      as retrieved by bp_core_avatar_full_width().
1202 *     @type int         $crop_h        Crop height. Default: the global 'full' avatar height,
1203 *                                      as retrieved by bp_core_avatar_full_height().
1204 *     @type int         $crop_x        The horizontal starting point of the crop. Default: 0.
1205 *     @type int         $crop_y        The vertical starting point of the crop. Default: 0.
1206 * }
1207 * @return bool True on success, false on failure.
1208 */
1209function bp_core_avatar_handle_crop( $args = '' ) {
1210
1211        $r = wp_parse_args( $args, array(
1212                'object'        => 'user',
1213                'avatar_dir'    => 'avatars',
1214                'item_id'       => false,
1215                'original_file' => false,
1216                'crop_w'        => bp_core_avatar_full_width(),
1217                'crop_h'        => bp_core_avatar_full_height(),
1218                'crop_x'        => 0,
1219                'crop_y'        => 0
1220        ) );
1221
1222        /**
1223         * Filters whether or not to handle cropping.
1224         *
1225         * If you want to override this function, make sure you return false.
1226         *
1227         * @since 1.2.4
1228         *
1229         * @param bool  $value Whether or not to crop.
1230         * @param array $r     Array of parsed arguments for function.
1231         */
1232        if ( ! apply_filters( 'bp_core_pre_avatar_handle_crop', true, $r ) ) {
1233                return true;
1234        }
1235
1236        // Crop the file.
1237        $avatar_attachment = new BP_Attachment_Avatar();
1238        $cropped           = $avatar_attachment->crop( $r );
1239
1240        // Check for errors.
1241        if ( empty( $cropped['full'] ) || empty( $cropped['thumb'] ) || is_wp_error( $cropped['full'] ) || is_wp_error( $cropped['thumb'] ) ) {
1242                return false;
1243        }
1244
1245        return true;
1246}
1247
1248/**
1249 * Ajax set an avatar for a given object and item id.
1250 *
1251 * @since 2.3.0
1252 *
1253 * @return string|null A JSON object containing success data if the crop/capture succeeded
1254 *                     error message otherwise.
1255 */
1256function bp_avatar_ajax_set() {
1257        if ( ! bp_is_post_request() ) {
1258                wp_send_json_error();
1259        }
1260
1261        // Check the nonce.
1262        check_admin_referer( 'bp_avatar_cropstore', 'nonce' );
1263
1264        $avatar_data = wp_parse_args( $_POST, array(
1265                'crop_w' => bp_core_avatar_full_width(),
1266                'crop_h' => bp_core_avatar_full_height(),
1267                'crop_x' => 0,
1268                'crop_y' => 0
1269        ) );
1270
1271        if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) || empty( $avatar_data['original_file'] ) ) {
1272                wp_send_json_error();
1273        }
1274
1275        // Capability check.
1276        if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) {
1277                wp_send_json_error();
1278        }
1279
1280        if ( ! empty( $avatar_data['type'] ) && 'camera' === $avatar_data['type'] && 'user' === $avatar_data['object'] ) {
1281                $webcam_avatar = false;
1282
1283                if ( ! empty( $avatar_data['original_file'] ) ) {
1284                        $webcam_avatar = str_replace( array( 'data:image/png;base64,', ' ' ), array( '', '+' ), $avatar_data['original_file'] );
1285                        $webcam_avatar = base64_decode( $webcam_avatar );
1286                }
1287
1288                if ( ! bp_avatar_handle_capture( $webcam_avatar, $avatar_data['item_id'] ) ) {
1289                        wp_send_json_error( array(
1290                                'feedback_code' => 1
1291                        ) );
1292
1293                } else {
1294                        $return = array(
1295                                'avatar' => esc_url( bp_core_fetch_avatar( array(
1296                                        'object'  => $avatar_data['object'],
1297                                        'item_id' => $avatar_data['item_id'],
1298                                        'html'    => false,
1299                                        'type'    => 'full',
1300                                ) ) ),
1301                                'feedback_code' => 2,
1302                                'item_id'       => $avatar_data['item_id'],
1303                        );
1304
1305                        /** This action is documented in wp-includes/deprecated.php */
1306                        do_action_deprecated( 'xprofile_avatar_uploaded', array( (int) $avatar_data['item_id'], $avatar_data['type'], $avatar_data ), '6.0.0', 'bp_members_avatar_uploaded' );
1307
1308                        /**
1309                         * Fires if the new avatar was successfully captured.
1310                         *
1311                         * @since 6.0.0
1312                         *
1313                         * @param string $item_id     Inform about the user id the avatar was set for.
1314                         * @param string $type        Inform about the way the avatar was set ('camera').
1315                         * @param array  $avatar_data Array of parameters passed to the avatar handler.
1316                         */
1317                        do_action( 'bp_members_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $avatar_data );
1318
1319                        wp_send_json_success( $return );
1320                }
1321
1322                return;
1323        }
1324
1325        $original_file = str_replace( bp_core_avatar_url(), '', $avatar_data['original_file'] );
1326
1327        // Set avatars dir & feedback part.
1328        if ( 'user' === $avatar_data['object'] ) {
1329                $avatar_dir = 'avatars';
1330
1331        // Defaults to object-avatars dir.
1332        } else {
1333                $avatar_dir = sanitize_key( $avatar_data['object'] ) . '-avatars';
1334        }
1335
1336        // Crop args.
1337        $r = array(
1338                'item_id'       => $avatar_data['item_id'],
1339                'object'        => $avatar_data['object'],
1340                'avatar_dir'    => $avatar_dir,
1341                'original_file' => $original_file,
1342                'crop_w'        => $avatar_data['crop_w'],
1343                'crop_h'        => $avatar_data['crop_h'],
1344                'crop_x'        => $avatar_data['crop_x'],
1345                'crop_y'        => $avatar_data['crop_y']
1346        );
1347
1348        // Handle crop.
1349        if ( bp_core_avatar_handle_crop( $r ) ) {
1350                $return = array(
1351                        'avatar' => esc_url( bp_core_fetch_avatar( array(
1352                                'object'  => $avatar_data['object'],
1353                                'item_id' => $avatar_data['item_id'],
1354                                'html'    => false,
1355                                'type'    => 'full',
1356                        ) ) ),
1357                        'feedback_code' => 2,
1358                        'item_id'       => $avatar_data['item_id'],
1359                );
1360
1361                if ( 'user' === $avatar_data['object'] ) {
1362                        /** This action is documented in wp-includes/deprecated.php */
1363                        do_action_deprecated( 'xprofile_avatar_uploaded', array( (int) $avatar_data['item_id'], $avatar_data['type'], $r ), '6.0.0', 'bp_members_avatar_uploaded' );
1364
1365                        /** This action is documented in bp-core/bp-core-avatars.php */
1366                        do_action( 'bp_members_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r );
1367                } elseif ( 'group' === $avatar_data['object'] ) {
1368                        /** This action is documented in bp-groups/bp-groups-screens.php */
1369                        do_action( 'groups_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r );
1370                }
1371
1372                wp_send_json_success( $return );
1373        } else {
1374                wp_send_json_error( array(
1375                        'feedback_code' => 1,
1376                ) );
1377        }
1378}
1379add_action( 'wp_ajax_bp_avatar_set', 'bp_avatar_ajax_set' );
1380
1381/**
1382 * Filter {@link get_avatar_url()} to use the BuddyPress user avatar URL.
1383 *
1384 * @since 2.9.0
1385 *
1386 * @param  string $retval      The URL of the avatar.
1387 * @param  mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
1388 *                             user email, WP_User object, WP_Post object, or WP_Comment object.
1389 * @param  array  $args        Arguments passed to get_avatar_data(), after processing.
1390 * @return string
1391 */
1392function bp_core_get_avatar_data_url_filter( $retval, $id_or_email, $args ) {
1393        $user = null;
1394
1395        // Ugh, hate duplicating code; process the user identifier.
1396        if ( is_numeric( $id_or_email ) ) {
1397                $user = get_user_by( 'id', absint( $id_or_email ) );
1398        } elseif ( $id_or_email instanceof WP_User ) {
1399                // User Object
1400                $user = $id_or_email;
1401        } elseif ( $id_or_email instanceof WP_Post ) {
1402                // Post Object
1403                $user = get_user_by( 'id', (int) $id_or_email->post_author );
1404        } elseif ( $id_or_email instanceof WP_Comment ) {
1405                if ( ! empty( $id_or_email->user_id ) ) {
1406                        $user = get_user_by( 'id', (int) $id_or_email->user_id );
1407                }
1408        } elseif ( is_email( $id_or_email ) ) {
1409                $user = get_user_by( 'email', $id_or_email );
1410        }
1411
1412        // No user, so bail.
1413        if ( false === $user instanceof WP_User ) {
1414                return $retval;
1415        }
1416
1417        // Set BuddyPress-specific avatar args.
1418        $args['item_id'] = $user->ID;
1419        $args['html']    = false;
1420
1421        // Use the 'full' type if size is larger than BP's thumb width.
1422        if ( (int) $args['size'] > bp_core_avatar_thumb_width() ) {
1423                $args['type'] = 'full';
1424        }
1425
1426        // Get the BuddyPress avatar URL.
1427        if ( $bp_avatar = bp_core_fetch_avatar( $args ) ) {
1428                return $bp_avatar;
1429        }
1430
1431        return $retval;
1432}
1433add_filter( 'get_avatar_url', 'bp_core_get_avatar_data_url_filter', 10, 3 );
1434
1435/**
1436 * Is the current avatar upload error-free?
1437 *
1438 * @since 1.0.0
1439 *
1440 * @param array $file The $_FILES array.
1441 * @return bool True if no errors are found. False if there are errors.
1442 */
1443function bp_core_check_avatar_upload( $file ) {
1444        if ( isset( $file['error'] ) && $file['error'] )
1445                return false;
1446
1447        return true;
1448}
1449
1450/**
1451 * Is the file size of the current avatar upload permitted?
1452 *
1453 * @since 1.0.0
1454 *
1455 * @param array $file The $_FILES array.
1456 * @return bool True if the avatar is under the size limit, otherwise false.
1457 */
1458function bp_core_check_avatar_size( $file ) {
1459        if ( $file['file']['size'] > bp_core_avatar_original_max_filesize() )
1460                return false;
1461
1462        return true;
1463}
1464
1465/**
1466 * Get allowed avatar types.
1467 *
1468 * @since 2.3.0
1469 *
1470 * @return array
1471 */
1472function bp_core_get_allowed_avatar_types() {
1473        $allowed_types = bp_attachments_get_allowed_types( 'avatar' );
1474
1475        /**
1476         * Filters the list of allowed image types.
1477         *
1478         * @since 2.3.0
1479         *
1480         * @param array $allowed_types List of image types.
1481         */
1482        $avatar_types = (array) apply_filters( 'bp_core_get_allowed_avatar_types', $allowed_types );
1483
1484        if ( empty( $avatar_types ) ) {
1485                $avatar_types = $allowed_types;
1486        } else {
1487                $avatar_types = array_intersect( $allowed_types, $avatar_types );
1488        }
1489
1490        return array_values( $avatar_types );
1491}
1492
1493/**
1494 * Get allowed avatar mime types.
1495 *
1496 * @since 2.3.0
1497 *
1498 * @return array
1499 */
1500function bp_core_get_allowed_avatar_mimes() {
1501        $allowed_types  = bp_core_get_allowed_avatar_types();
1502
1503        return bp_attachments_get_allowed_mimes( 'avatar', $allowed_types );
1504}
1505
1506/**
1507 * Does the current avatar upload have an allowed file type?
1508 *
1509 * Permitted file types are JPG, GIF and PNG.
1510 *
1511 * @since 1.0.0
1512 *
1513 * @param array $file The $_FILES array.
1514 * @return bool True if the file extension is permitted, otherwise false.
1515 */
1516function bp_core_check_avatar_type( $file ) {
1517        return bp_attachments_check_filetype( $file['file']['tmp_name'], $file['file']['name'], bp_core_get_allowed_avatar_mimes() );
1518}
1519
1520/**
1521 * Fetch data from the BP root blog's upload directory.
1522 *
1523 * @since 1.8.0
1524 *
1525 * @param string $type The variable we want to return from the $bp->avatars object.
1526 *                     Only 'upload_path' and 'url' are supported. Default: 'upload_path'.
1527 * @return string The avatar upload directory path.
1528 */
1529function bp_core_get_upload_dir( $type = 'upload_path' ) {
1530        $bp = buddypress();
1531
1532        switch ( $type ) {
1533                case 'upload_path' :
1534                        $constant = 'BP_AVATAR_UPLOAD_PATH';
1535                        $key      = 'basedir';
1536
1537                        break;
1538
1539                case 'url' :
1540                        $constant = 'BP_AVATAR_URL';
1541                        $key      = 'baseurl';
1542
1543                        break;
1544
1545                default :
1546                        return false;
1547
1548                        break;
1549        }
1550
1551        // See if the value has already been calculated and stashed in the $bp global.
1552        if ( isset( $bp->avatar->$type ) ) {
1553                $retval = $bp->avatar->$type;
1554        } else {
1555                // If this value has been set in a constant, just use that.
1556                if ( defined( $constant ) ) {
1557                        $retval = constant( $constant );
1558                } else {
1559
1560                        // Use cached upload dir data if available.
1561                        if ( ! empty( $bp->avatar->upload_dir ) ) {
1562                                $upload_dir = $bp->avatar->upload_dir;
1563
1564                        // No cache, so query for it.
1565                        } else {
1566
1567                                // Get upload directory information from current site.
1568                                $upload_dir = bp_upload_dir();
1569
1570                                // Stash upload directory data for later use.
1571                                $bp->avatar->upload_dir = $upload_dir;
1572                        }
1573
1574                        // Directory does not exist and cannot be created.
1575                        if ( ! empty( $upload_dir['error'] ) ) {
1576                                $retval = '';
1577
1578                        } else {
1579                                $retval = $upload_dir[$key];
1580
1581                                // If $key is 'baseurl', check to see if we're on SSL
1582                                // Workaround for WP13941, WP15928, WP19037.
1583                                if ( $key == 'baseurl' && is_ssl() ) {
1584                                        $retval = str_replace( 'http://', 'https://', $retval );
1585                                }
1586                        }
1587
1588                }
1589
1590                // Stash in $bp for later use.
1591                $bp->avatar->$type = $retval;
1592        }
1593
1594        return $retval;
1595}
1596
1597/**
1598 * Get the absolute upload path for the WP installation.
1599 *
1600 * @since 1.2.0
1601 *
1602 * @return string Absolute path to WP upload directory.
1603 */
1604function bp_core_avatar_upload_path() {
1605
1606        /**
1607         * Filters the absolute upload path for the WP installation.
1608         *
1609         * @since 1.2.0
1610         *
1611         * @param string $value Absolute upload path for the WP installation.
1612         */
1613        return apply_filters( 'bp_core_avatar_upload_path', bp_core_get_upload_dir() );
1614}
1615
1616/**
1617 * Get the raw base URL for root site upload location.
1618 *
1619 * @since 1.2.0
1620 *
1621 * @return string Full URL to current upload location.
1622 */
1623function bp_core_avatar_url() {
1624
1625        /**
1626         * Filters the raw base URL for root site upload location.
1627         *
1628         * @since 1.2.0
1629         *
1630         * @param string $value Raw base URL for the root site upload location.
1631         */
1632        return apply_filters( 'bp_core_avatar_url', bp_core_get_upload_dir( 'url' ) );
1633}
1634
1635/**
1636 * Check if a given user ID has an uploaded avatar.
1637 *
1638 * @since 1.0.0
1639 *
1640 * @param int $user_id ID of the user whose avatar is being checked.
1641 * @return bool True if the user has uploaded a local avatar. Otherwise false.
1642 */
1643function bp_get_user_has_avatar( $user_id = 0 ) {
1644
1645        if ( empty( $user_id ) )
1646                $user_id = bp_displayed_user_id();
1647
1648        $retval = false;
1649        if ( bp_core_fetch_avatar( array( 'item_id' => $user_id, 'no_grav' => true, 'html' => false, 'type' => 'full' ) ) != bp_core_avatar_default( 'local' ) )
1650                $retval = true;
1651
1652        /**
1653         * Filters whether or not a user has an uploaded avatar.
1654         *
1655         * @since 1.6.0
1656         *
1657         * @param bool $retval  Whether or not a user has an uploaded avatar.
1658         * @param int  $user_id ID of the user being checked.
1659         */
1660        return (bool) apply_filters( 'bp_get_user_has_avatar', $retval, $user_id );
1661}
1662
1663/**
1664 * Utility function for fetching an avatar dimension setting.
1665 *
1666 * @since 1.5.0
1667 *
1668 * @param string $type   Dimension type you're fetching dimensions for. 'thumb'
1669 *                       or 'full'. Default: 'thumb'.
1670 * @param string $h_or_w Which dimension is being fetched. 'height' or 'width'.
1671 *                       Default: 'height'.
1672 * @return int|bool $dim The dimension.
1673 */
1674function bp_core_avatar_dimension( $type = 'thumb', $h_or_w = 'height' ) {
1675        $bp  = buddypress();
1676        $dim = isset( $bp->avatar->{$type}->{$h_or_w} ) ? (int) $bp->avatar->{$type}->{$h_or_w} : false;
1677
1678        /**
1679         * Filters the avatar dimension setting.
1680         *
1681         * @since 1.5.0
1682         *
1683         * @param int|bool $dim    Dimension setting for the type.
1684         * @param string   $type   The type of avatar whose dimensions are requested. Default 'thumb'.
1685         * @param string   $h_or_w The dimension parameter being requested. Default 'height'.
1686         */
1687        return apply_filters( 'bp_core_avatar_dimension', $dim, $type, $h_or_w );
1688}
1689
1690/**
1691 * Get the 'thumb' avatar width setting.
1692 *
1693 * @since 1.5.0
1694 *
1695 * @return int The 'thumb' width.
1696 */
1697function bp_core_avatar_thumb_width() {
1698
1699        /**
1700         * Filters the 'thumb' avatar width setting.
1701         *
1702         * @since 1.5.0
1703         *
1704         * @param int $value Value for the 'thumb' avatar width setting.
1705         */
1706        return apply_filters( 'bp_core_avatar_thumb_width', bp_core_avatar_dimension( 'thumb', 'width' ) );
1707}
1708
1709/**
1710 * Get the 'thumb' avatar height setting.
1711 *
1712 * @since 1.5.0
1713 *
1714 * @return int The 'thumb' height.
1715 */
1716function bp_core_avatar_thumb_height() {
1717
1718        /**
1719         * Filters the 'thumb' avatar height setting.
1720         *
1721         * @since 1.5.0
1722         *
1723         * @param int $value Value for the 'thumb' avatar height setting.
1724         */
1725        return apply_filters( 'bp_core_avatar_thumb_height', bp_core_avatar_dimension( 'thumb', 'height' ) );
1726}
1727
1728/**
1729 * Get the 'full' avatar width setting.
1730 *
1731 * @since 1.5.0
1732 *
1733 * @return int The 'full' width.
1734 */
1735function bp_core_avatar_full_width() {
1736
1737        /**
1738         * Filters the 'full' avatar width setting.
1739         *
1740         * @since 1.5.0
1741         *
1742         * @param int $value Value for the 'full' avatar width setting.
1743         */
1744        return apply_filters( 'bp_core_avatar_full_width', bp_core_avatar_dimension( 'full', 'width' ) );
1745}
1746
1747/**
1748 * Get the 'full' avatar height setting.
1749 *
1750 * @since 1.5.0
1751 *
1752 * @return int The 'full' height.
1753 */
1754function bp_core_avatar_full_height() {
1755
1756        /**
1757         * Filters the 'full' avatar height setting.
1758         *
1759         * @since 1.5.0
1760         *
1761         * @param int $value Value for the 'full' avatar height setting.
1762         */
1763        return apply_filters( 'bp_core_avatar_full_height', bp_core_avatar_dimension( 'full', 'height' ) );
1764}
1765
1766/**
1767 * Get the max width for original avatar uploads.
1768 *
1769 * @since 1.5.0
1770 *
1771 * @return int The max width for original avatar uploads.
1772 */
1773function bp_core_avatar_original_max_width() {
1774
1775        /**
1776         * Filters the max width for original avatar uploads.
1777         *
1778         * @since 1.5.0
1779         *
1780         * @param int $value Value for the max width.
1781         */
1782        return apply_filters( 'bp_core_avatar_original_max_width', (int) buddypress()->avatar->original_max_width );
1783}
1784
1785/**
1786 * Get the max filesize for original avatar uploads.
1787 *
1788 * @since 1.5.0
1789 *
1790 * @return int The max filesize for original avatar uploads.
1791 */
1792function bp_core_avatar_original_max_filesize() {
1793
1794        /**
1795         * Filters the max filesize for original avatar uploads.
1796         *
1797         * @since 1.5.0
1798         *
1799         * @param int $value Value for the max filesize.
1800         */
1801        return apply_filters( 'bp_core_avatar_original_max_filesize', (int) buddypress()->avatar->original_max_filesize );
1802}
1803
1804/**
1805 * Get the URL of the 'full' default avatar.
1806 *
1807 * @since 1.5.0
1808 * @since 2.6.0 Introduced `$params` and `$object_type` parameters.
1809 *
1810 * @param string $type   'local' if the fallback should be the locally-hosted version
1811 *                       of the mystery person, 'gravatar' if the fallback should be
1812 *                       Gravatar's version. Default: 'gravatar'.
1813 * @param array  $params Parameters passed to bp_core_fetch_avatar().
1814 * @return string The URL of the default avatar.
1815 */
1816function bp_core_avatar_default( $type = 'gravatar', $params = array() ) {
1817        // Local override.
1818        if ( defined( 'BP_AVATAR_DEFAULT' ) ) {
1819                $avatar = BP_AVATAR_DEFAULT;
1820
1821        // Use the local default image.
1822        } elseif ( 'local' === $type ) {
1823                $size = '';
1824                if (
1825                        ( isset( $params['type'] ) && 'thumb' === $params['type'] && bp_core_avatar_thumb_width() <= 50 ) ||
1826                        ( isset( $params['width'] ) && $params['width'] <= 50 )
1827                ) {
1828
1829                        $size = '-50';
1830                }
1831
1832                $avatar = buddypress()->plugin_url . "bp-core/images/mystery-man{$size}.jpg";
1833
1834        // Use Gravatar's mystery person as fallback.
1835        } else {
1836                $size = '';
1837                if ( isset( $params['type'] ) && 'thumb' === $params['type'] ) {
1838                        $size = bp_core_avatar_thumb_width();
1839                } else {
1840                        $size = bp_core_avatar_full_width();
1841                }
1842                $avatar = '//www.gravatar.com/avatar/00000000000000000000000000000000?d=mm&amp;s=' . $size;
1843        }
1844
1845        /**
1846         * Filters the URL of the 'full' default avatar.
1847         *
1848         * @since 1.5.0
1849         * @since 2.6.0 Added `$params`.
1850         *
1851         * @param string $avatar URL of the default avatar.
1852         * @param array  $params Params provided to bp_core_fetch_avatar().
1853         */
1854        return apply_filters( 'bp_core_avatar_default', $avatar, $params );
1855}
1856
1857/**
1858 * Get the URL of the 'thumb' default avatar.
1859 *
1860 * Uses Gravatar's mystery-person avatar, unless BP_AVATAR_DEFAULT_THUMB has been
1861 * defined.
1862 *
1863 * @since 1.5.0
1864 * @since 2.6.0 Introduced `$object_type` parameter.
1865 *
1866 * @param string $type   'local' if the fallback should be the locally-hosted version
1867 *                       of the mystery person, 'gravatar' if the fallback should be
1868 *                       Gravatar's version. Default: 'gravatar'.
1869 * @param array  $params Parameters passed to bp_core_fetch_avatar().
1870 * @return string The URL of the default avatar thumb.
1871 */
1872function bp_core_avatar_default_thumb( $type = 'gravatar', $params = array() ) {
1873        // Local override.
1874        if ( defined( 'BP_AVATAR_DEFAULT_THUMB' ) ) {
1875                $avatar = BP_AVATAR_DEFAULT_THUMB;
1876
1877        // Use the local default image.
1878        } elseif ( 'local' === $type ) {
1879                $avatar = buddypress()->plugin_url . 'bp-core/images/mystery-man-50.jpg';
1880
1881        // Use Gravatar's mystery person as fallback.
1882        } else {
1883                $avatar = '//www.gravatar.com/avatar/00000000000000000000000000000000?d=mm&amp;s=' . bp_core_avatar_thumb_width();
1884        }
1885
1886        /**
1887         * Filters the URL of the 'thumb' default avatar.
1888         *
1889         * @since 1.5.0
1890         * @since 2.6.0 Added `$params`.
1891         *
1892         * @param string $avatar URL of the default avatar.
1893         * @param string $params Params provided to bp_core_fetch_avatar().
1894         */
1895        return apply_filters( 'bp_core_avatar_thumb', $avatar, $params );
1896}
1897
1898/**
1899 * Reset the week parameter of the WordPress main query if needed.
1900 *
1901 * When cropping an avatar, a $_POST['w'] var is sent, setting the 'week'
1902 * parameter of the WordPress main query to this posted var. To avoid
1903 * notices, we need to make sure this 'week' query var is reset to 0.
1904 *
1905 * @since 2.2.0
1906 *
1907 * @param WP_Query|null $posts_query The main query object.
1908 */
1909function bp_core_avatar_reset_query( $posts_query = null ) {
1910        $reset_w = false;
1911
1912        // Group's avatar edit screen.
1913        if ( bp_is_group_admin_page() ) {
1914                $reset_w = bp_is_group_admin_screen( 'group-avatar' );
1915
1916        // Group's avatar create screen.
1917        } elseif ( bp_is_group_create() ) {
1918                /**
1919                 * We can't use bp_get_groups_current_create_step().
1920                 * as it's not set yet
1921                 */
1922                $reset_w = 'group-avatar' === bp_action_variable( 1 );
1923
1924        // User's change avatar screen.
1925        } else {
1926                $reset_w = bp_is_user_change_avatar();
1927        }
1928
1929        // A user or a group is cropping an avatar.
1930        if ( true === $reset_w && isset( $_POST['avatar-crop-submit'] ) ) {
1931                $posts_query->set( 'w', 0 );
1932        }
1933}
1934add_action( 'bp_parse_query', 'bp_core_avatar_reset_query', 10, 1 );
1935
1936/**
1937 * Checks whether Avatar UI should be loaded.
1938 *
1939 * @since 2.3.0
1940 *
1941 * @return bool True if Avatar UI should load, false otherwise.
1942 */
1943function bp_avatar_is_front_edit() {
1944        $retval = false;
1945
1946        if ( bp_is_user_change_avatar() && 'crop-image' !== bp_get_avatar_admin_step() ) {
1947                $retval = ! bp_core_get_root_option( 'bp-disable-avatar-uploads' );
1948        }
1949
1950        if ( bp_is_active( 'groups' ) ) {
1951                // Group creation.
1952                if ( bp_is_group_create() && bp_is_group_creation_step( 'group-avatar' ) && 'crop-image' !== bp_get_avatar_admin_step() ) {
1953                        $retval = ! bp_disable_group_avatar_uploads();
1954
1955                // Group Manage.
1956                } elseif ( bp_is_group_admin_page() && bp_is_group_admin_screen( 'group-avatar' ) && 'crop-image' !== bp_get_avatar_admin_step() ) {
1957                        $retval = ! bp_disable_group_avatar_uploads();
1958                }
1959        }
1960
1961        /**
1962         * Use this filter if you need to :
1963         * - Load the avatar UI for a component that is !groups or !user (return true regarding your conditions)
1964         * - Completely disable the avatar UI introduced in 2.3 (eg: __return_false())
1965         *
1966         * @since 2.3.0
1967         *
1968         * @param bool $retval Whether or not to load the Avatar UI.
1969         */
1970        return apply_filters( 'bp_avatar_is_front_edit', $retval );
1971}
1972
1973/**
1974 * Checks whether the Webcam Avatar UI part should be loaded.
1975 *
1976 * @since 2.3.0
1977 *
1978 * @global $is_safari
1979 * @global $is_IE
1980 *
1981 * @return bool True to load the Webcam Avatar UI part. False otherwise.
1982 */
1983function bp_avatar_use_webcam() {
1984        global $is_safari, $is_IE, $is_chrome;
1985
1986        /**
1987         * Do not use the webcam feature for mobile devices
1988         * to avoid possible confusions.
1989         */
1990        if ( wp_is_mobile() ) {
1991                return false;
1992        }
1993
1994        /**
1995         * Bail when the browser does not support getUserMedia.
1996         *
1997         * @see http://caniuse.com/#feat=stream
1998         */
1999        if ( $is_safari || $is_IE || ( $is_chrome && ! is_ssl() ) ) {
2000                return false;
2001        }
2002
2003        /**
2004         * Use this filter if you need to disable the webcam capture feature
2005         * by returning false.
2006         *
2007         * @since 2.3.0
2008         *
2009         * @param bool $value Whether or not to load Webcam Avatar UI part.
2010         */
2011        return apply_filters( 'bp_avatar_use_webcam', true );
2012}
2013
2014/**
2015 * Template function to load the Avatar UI javascript templates.
2016 *
2017 * @since 2.3.0
2018 */
2019function bp_avatar_get_templates() {
2020        if ( ! bp_avatar_is_front_edit() ) {
2021                return;
2022        }
2023
2024        bp_attachments_get_template_part( 'avatars/index' );
2025}
2026
2027/**
2028 * Trick to check if the theme's BuddyPress templates are up to date.
2029 *
2030 * If the "avatar templates" are not including the new template tag, this will
2031 * help users to get the avatar UI.
2032 *
2033 * @since 2.3.0
2034 */
2035function bp_avatar_template_check() {
2036        if ( ! bp_avatar_is_front_edit() ) {
2037                return;
2038        }
2039
2040        if ( ! did_action( 'bp_attachments_avatar_check_template' ) ) {
2041                bp_attachments_get_template_part( 'avatars/index' );
2042        }
2043}