Skip to:
Content

BuddyPress.org

Ticket #6278: 6278.03.patch

File 6278.03.patch, 33.4 KB (added by imath, 5 years ago)
  • src/bp-core/bp-core-avatars.php

    diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php
    index c607bb2..447f913 100644
    add_action( 'bp_init', 'bp_core_set_avatar_constants', 3 ); 
    5252function bp_core_set_avatar_globals() {
    5353        $bp = buddypress();
    5454
    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;
     55        $bp->avatar = new BP_Attachment_Avatar( array(
     56
     57                // Dimensions for thumb size
     58                'thumb' => (object) array(
     59                        'width'   => absint( BP_AVATAR_THUMB_WIDTH ),
     60                        'height'  => absint( BP_AVATAR_THUMB_HEIGHT ),
     61                ),
     62
     63                // Dimensions for full size
     64                'full' => (object) array(
     65                        'width'   => absint( BP_AVATAR_FULL_WIDTH ),
     66                        'height'  => absint( BP_AVATAR_FULL_HEIGHT ),
     67                ),
     68
     69                // Upload maximums
     70                'original_max_width'    => absint( BP_AVATAR_ORIGINAL_MAX_WIDTH ),
     71                'original_max_filesize' => absint( BP_AVATAR_ORIGINAL_MAX_FILESIZE ),
     72
     73                // Cache the root blog's show_avatars setting, to avoid unnecessary
     74                // calls to switch_to_blog()
     75                'show_avatars'          => (bool) BP_SHOW_AVATARS,
     76
     77                // Upload action
     78                'action' => 'bp_avatar_upload',
     79
     80                // Specific errors for avatars
     81                'upload_error_strings'  => array(
     82                        sprintf( __( 'That photo is too big. Please upload one smaller than %s', 'buddypress' ), size_format( BP_AVATAR_ORIGINAL_MAX_FILESIZE ) ),
     83                        __( 'Please upload only JPG, GIF or PNG photos.', 'buddypress' ),
     84                ),
     85        ) );
    8086
    8187        // Backpat for pre-1.5
    82         if ( ! defined( 'BP_AVATAR_UPLOAD_PATH' ) )
     88        if ( ! defined( 'BP_AVATAR_UPLOAD_PATH' ) ) {
    8389                define( 'BP_AVATAR_UPLOAD_PATH', $bp->avatar->upload_path );
     90        }
    8491
    8592        // Backpat for pre-1.5
    86         if ( ! defined( 'BP_AVATAR_URL' ) )
     93        if ( ! defined( 'BP_AVATAR_URL' ) ) {
    8794                define( 'BP_AVATAR_URL', $bp->avatar->url );
     95        }
    8896
    8997        do_action( 'bp_core_set_avatar_globals' );
    9098}
    function bp_core_delete_existing_avatar( $args = '' ) { 
    564572 * @see bp_core_check_avatar_upload()
    565573 * @see bp_core_check_avatar_type()
    566574 *
    567  * @param array $file The appropriate entry the from $_FILES superglobal.
     575 * @param array  $file              The appropriate entry the from $_FILES superglobal.
    568576 * @param string $upload_dir_filter A filter to be applied to 'upload_dir'.
     577 *
    569578 * @return bool True on success, false on failure.
    570579 */
    571580function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) {
    function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
    574583         * You may want to hook into this filter if you want to override this function.
    575584         * Make sure you return false.
    576585         */
    577         if ( !apply_filters( 'bp_core_pre_avatar_handle_upload', true, $file, $upload_dir_filter ) )
     586        if ( ! apply_filters( 'bp_core_pre_avatar_handle_upload', true, $file, $upload_dir_filter ) ) {
    578587                return true;
    579 
    580         require_once( ABSPATH . '/wp-admin/includes/file.php' );
    581 
    582         $uploadErrors = array(
    583                 0 => __( 'The image was uploaded successfully', 'buddypress' ),
    584                 1 => __( 'The image exceeds the maximum allowed file size of: ', 'buddypress' ) . size_format( bp_core_avatar_original_max_filesize() ),
    585                 2 => __( 'The image exceeds the maximum allowed file size of: ', 'buddypress' ) . size_format( bp_core_avatar_original_max_filesize() ),
    586                 3 => __( 'The uploaded file was only partially uploaded.', 'buddypress' ),
    587                 4 => __( 'The image was not uploaded.', 'buddypress' ),
    588                 6 => __( 'Missing a temporary folder.', 'buddypress' )
    589         );
    590 
    591         if ( ! bp_core_check_avatar_upload( $file ) ) {
    592                 bp_core_add_message( sprintf( __( 'Your upload failed. Please try again. Error was: %s', 'buddypress' ), $uploadErrors[$file['file']['error']] ), 'error' );
    593                 return false;
    594         }
    595 
    596         if ( ! bp_core_check_avatar_size( $file ) ) {
    597                 bp_core_add_message( sprintf( __( 'The file you uploaded is too big. Please upload a file under %s', 'buddypress' ), size_format( bp_core_avatar_original_max_filesize() ) ), 'error' );
    598                 return false;
    599588        }
    600589
    601         if ( ! bp_core_check_avatar_type( $file ) ) {
    602                 bp_core_add_message( __( 'Please upload only JPG, GIF or PNG photos.', 'buddypress' ), 'error' );
    603                 return false;
    604         }
    605 
    606         // Filter the upload location
    607         add_filter( 'upload_dir', $upload_dir_filter, 10, 0 );
    608 
    609         $bp = buddypress();
     590        // Setup some variables
     591        $bp          = buddypress();
     592        $upload_path = bp_core_avatar_upload_path();
    610593
    611         $bp->avatar_admin->original = wp_handle_upload( $file['file'], array( 'action'=> 'bp_avatar_upload' ) );
     594        // Upload the file
     595        $bp->avatar_admin->original = $bp->avatar->upload( $file, $upload_dir_filter );
    612596
    613         // Remove the upload_dir filter, so that other upload URLs on the page
    614         // don't break
    615         remove_filter( 'upload_dir', $upload_dir_filter, 10, 0 );
    616 
    617         // Move the file to the correct upload location.
    618         if ( !empty( $bp->avatar_admin->original['error'] ) ) {
     597        // In case of an error, stop the process and display a feedback to the user
     598        if ( ! empty( $bp->avatar_admin->original['error'] ) ) {
    619599                bp_core_add_message( sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->original['error'] ), 'error' );
    620600                return false;
    621601        }
    622602
    623         // Get image size
    624         $size  = @getimagesize( $bp->avatar_admin->original['file'] );
    625         $error = false;
    626 
    627         // Check image size and shrink if too large
    628         if ( $size[0] > bp_core_avatar_original_max_width() ) {
    629                 $editor = wp_get_image_editor( $bp->avatar_admin->original['file'] );
    630 
    631                 if ( ! is_wp_error( $editor ) ) {
    632                         $editor->set_quality( 100 );
    633 
    634                         $resized = $editor->resize( bp_core_avatar_original_max_width(), bp_core_avatar_original_max_width(), false );
    635                         if ( ! is_wp_error( $resized ) ) {
    636                                 $thumb = $editor->save( $editor->generate_filename() );
    637                         } else {
    638                                 $error = $resized;
    639                         }
    640 
    641                         // Check for thumbnail creation errors
    642                         if ( false === $error && is_wp_error( $thumb ) ) {
    643                                 $error = $thumb;
    644                         }
    645 
    646                         // Thumbnail is good so proceed
    647                         if ( false === $error ) {
    648                                 $bp->avatar_admin->resized = $thumb;
    649                         }
    650 
    651                 } else {
    652                         $error = $editor;
    653                 }
    654 
    655                 if ( false !== $error ) {
    656                         bp_core_add_message( sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $error->get_error_message() ), 'error' );
    657                         return false;
    658                 }
    659         }
    660 
    661         if ( ! isset( $bp->avatar_admin->image ) )
    662                 $bp->avatar_admin->image = new stdClass();
     603        // Maybe resize
     604        $bp->avatar_admin->resized = $bp->avatar->shrink( $bp->avatar_admin->original['file'] );
     605        $bp->avatar_admin->image   = new stdClass();
    663606
    664607        // We only want to handle one image after resize.
    665608        if ( empty( $bp->avatar_admin->resized ) ) {
    666                 $bp->avatar_admin->image->dir = str_replace( bp_core_avatar_upload_path(), '', $bp->avatar_admin->original['file'] );
     609                $bp->avatar_admin->image->file = $bp->avatar_admin->original['file'];
     610                $bp->avatar_admin->image->dir  = str_replace( $upload_path, '', $bp->avatar_admin->original['file'] );
    667611        } else {
    668                 $bp->avatar_admin->image->dir = str_replace( bp_core_avatar_upload_path(), '', $bp->avatar_admin->resized['path'] );
     612                $bp->avatar_admin->image->file = $bp->avatar_admin->resized['path'];
     613                $bp->avatar_admin->image->dir  = str_replace( $upload_path, '', $bp->avatar_admin->resized['path'] );
    669614                @unlink( $bp->avatar_admin->original['file'] );
    670615        }
    671616
    function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
    675620                return false;
    676621        }
    677622
    678         // If the uploaded image is smaller than the "full" dimensions, throw
    679         // a warning
    680         $uploaded_image = @getimagesize( bp_core_avatar_upload_path() . buddypress()->avatar_admin->image->dir );
    681         $full_width     = bp_core_avatar_full_width();
    682         $full_height    = bp_core_avatar_full_height();
    683         if ( isset( $uploaded_image[0] ) && $uploaded_image[0] < $full_width || $uploaded_image[1] < $full_height ) {
    684                 bp_core_add_message( sprintf( __( 'You have selected an image that is smaller than recommended. For best results, upload a picture larger than %d x %d pixels.', 'buddypress' ), $full_width, $full_height ), 'error' );
     623        // If the uploaded image is smaller than the "full" dimensions, throw a warning
     624        if ( $bp->avatar->is_too_small( $bp->avatar_admin->image->file ) ) {
     625                bp_core_add_message( sprintf( __( 'You have selected an image that is smaller than recommended. For best results, upload a picture larger than %d x %d pixels.', 'buddypress' ), bp_core_avatar_full_width(), bp_core_avatar_full_height() ), 'error' );
    685626        }
    686627
    687628        // Set the url value for the image
    function bp_core_check_avatar_type($file) { 
    926867/**
    927868 * Fetch data from the BP root blog's upload directory.
    928869 *
    929  * Handy for multisite instances because all uploads are made on the BP root
    930  * blog and we need to query the BP root blog for the upload directory data.
    931  *
    932  * This function ensures that we only need to use {@link switch_to_blog()}
    933  * once to get what we need.
    934  *
    935870 * @since BuddyPress (1.8.0)
    936871 *
    937  * @uses wp_upload_dir()
    938  *
    939872 * @param string $type The variable we want to return from the $bp->avatars
    940873 *        object. Only 'upload_path' and 'url' are supported. Default: 'upload_path'.
    941874 * @return string The avatar upload directory path.
    function bp_core_check_avatar_type($file) { 
    943876function bp_core_get_upload_dir( $type = 'upload_path' ) {
    944877        $bp = buddypress();
    945878
    946         switch ( $type ) {
    947                 case 'upload_path' :
    948                         $constant = 'BP_AVATAR_UPLOAD_PATH';
    949                         $key      = 'basedir';
    950 
    951                         break;
    952 
    953                 case 'url' :
    954                         $constant = 'BP_AVATAR_URL';
    955                         $key      = 'baseurl';
    956 
    957                         break;
    958 
    959                 default :
    960                         return false;
    961 
    962                         break;
    963         }
    964 
    965         // See if the value has already been calculated and stashed in the $bp global
    966         if ( isset( $bp->avatar->$type ) ) {
    967                 $retval = $bp->avatar->$type;
    968         } else {
    969                 // If this value has been set in a constant, just use that
    970                 if ( defined( $constant ) ) {
    971                         $retval = constant( $constant );
    972                 } else {
    973 
    974                         // Use cached upload dir data if available
    975                         if ( ! empty( $bp->avatar->upload_dir ) ) {
    976                                 $upload_dir = $bp->avatar->upload_dir;
    977 
    978                         // No cache, so query for it
    979                         } else {
    980                                 // We need to switch to the root blog on multisite installs
    981                                 if ( is_multisite() ) {
    982                                         switch_to_blog( bp_get_root_blog_id() );
    983                                 }
    984 
    985                                 // Get upload directory information from current site
    986                                 $upload_dir = wp_upload_dir();
    987 
    988                                 // Will bail if not switched
    989                                 restore_current_blog();
    990 
    991                                 // Stash upload directory data for later use
    992                                 $bp->avatar->upload_dir = $upload_dir;
    993                         }
    994 
    995                         // Directory does not exist and cannot be created
    996                         if ( ! empty( $upload_dir['error'] ) ) {
    997                                 $retval = '';
    998 
    999                         } else {
    1000                                 $retval = $upload_dir[$key];
    1001 
    1002                                 // If $key is 'baseurl', check to see if we're on SSL
    1003                                 // Workaround for WP13941, WP15928, WP19037.
    1004                                 if ( $key == 'baseurl' && is_ssl() ) {
    1005                                         $retval = str_replace( 'http://', 'https://', $retval );
    1006                                 }
    1007                         }
    1008 
    1009                 }
    1010 
    1011                 // Stash in $bp for later use
    1012                 $bp->avatar->$type = $retval;
     879        if ( ! isset( $bp->avatar->{$type} ) ) {
     880                return false;
    1013881        }
    1014882
    1015         return $retval;
     883        return $bp->avatar->{$type};
    1016884}
    1017885
    1018886/**
  • src/bp-core/bp-core-classes.php

    diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php
    index b50325d..d23e878 100644
    require dirname( __FILE__ ) . '/classes/class-bp-walker-nav-menu-checklist.php'; 
    2020require dirname( __FILE__ ) . '/classes/class-bp-suggestions.php';
    2121require dirname( __FILE__ ) . '/classes/class-bp-members-suggestions.php';
    2222require dirname( __FILE__ ) . '/classes/class-bp-recursive-query.php';
     23require dirname( __FILE__ ) . '/classes/class-bp-attachment.php';
     24require dirname( __FILE__ ) . '/classes/class-bp-attachment-avatar.php';
  • src/bp-core/classes/class-bp-attachment-avatar.php

    diff --git src/bp-core/classes/class-bp-attachment-avatar.php src/bp-core/classes/class-bp-attachment-avatar.php
    index e69de29..f01db21 100644
     
     1<?php
     2
     3/**
     4 * Core avatar attachment class
     5 *
     6 * @package BuddyPress
     7 * @subpackage Core
     8 */
     9
     10// Exit if accessed directly
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * BP Attachment class to manage your avatar upload needs
     15 *
     16 * @since BuddyPress (2.3.0)
     17 */
     18class BP_Attachment_Avatar extends BP_Attachment {
     19
     20        /**
     21         * Construct Upload parameters
     22         *
     23         * @since BuddyPress (2.3.0)
     24         *
     25         * @see  BP_Attachment::__construct() for list of parameters
     26         * @uses sanitize_key()
     27         * @uses bp_parse_args()
     28         * @uses BP_Attachment->set_upload_error_strings()
     29         * @uses BP_Attachment->set_upload_dir()
     30         */
     31        public function __construct( $args = '' ) {
     32                parent::__construct( $args );
     33
     34                // Set default thumb & full values
     35                if ( isset( $this->thumb, $this->full ) ) {
     36                        $this->thumb->default = bp_core_avatar_default_thumb();
     37                        $this->full->default  = bp_core_avatar_default();
     38                }
     39        }
     40
     41        /**
     42         * Eventually override default path and url to upload dir
     43         * if BP_AVATAR_UPLOAD_PATH && BP_AVATAR_URL are defined
     44         *
     45         * @since BuddyPress (2.3.0)
     46         */
     47        public function set_upload_dir() {
     48                parent::set_upload_dir();
     49
     50                // Defer to constants if set
     51                if ( defined( 'BP_AVATAR_UPLOAD_PATH' ) && defined( 'BP_AVATAR_URL' ) ) {
     52                        $this->upload_path = BP_AVATAR_UPLOAD_PATH;
     53                        $this->url         = BP_AVATAR_URL;
     54                }
     55        }
     56
     57        /**
     58         * Avatar specific rules
     59         *
     60         * Adds an error if the avatar size or type don't match BuddyPress needs
     61         * The error code is the index of $upload_error_strings
     62         *
     63         * @since BuddyPress (2.3.0)
     64         *
     65         * @param  array $file the temporary file attributes (before it has been moved)
     66         * @uses   bp_core_check_avatar_size()
     67         * @uses   bp_core_check_avatar_type()
     68         * @return array the file with extra errors if needed
     69         */
     70        public function validate_upload( $file = array() ) {
     71
     72                // Bail if already an error
     73                if ( ! empty( $file['error'] ) ) {
     74                        return $file;
     75                }
     76
     77                // File size is too big
     78                if ( ! bp_core_check_avatar_size( array( 'file' => $file ) ) ) {
     79                        $file['error'] = 9;
     80
     81                // File is of invalid type
     82                } else if ( ! bp_core_check_avatar_type( array( 'file' => $file ) ) ) {
     83                        $file['error'] = 10;
     84                }
     85
     86                // Return with error code attached
     87                return $file;
     88        }
     89
     90        /**
     91         * Maybe shrink the attachment to fit maximum allowed width
     92         *
     93         * @return mixed
     94         */
     95        public static function shrink( $file = array() ) {
     96
     97                // Get image size
     98                $size   = @getimagesize( $file );
     99                $retval = false;
     100
     101                // Check image size and shrink if too large
     102                if ( $size[0] > bp_core_avatar_original_max_width() ) {
     103                        $editor = wp_get_image_editor( $file );
     104
     105                        if ( ! is_wp_error( $editor ) ) {
     106                                $editor->set_quality( 100 );
     107
     108                                $resized = $editor->resize( bp_core_avatar_original_max_width(), bp_core_avatar_original_max_width(), false );
     109                                if ( ! is_wp_error( $resized ) ) {
     110                                        $thumb = $editor->save( $editor->generate_filename() );
     111                                } else {
     112                                        $retval = $resized;
     113                                }
     114
     115                                // Check for thumbnail creation errors
     116                                if ( ( false === $retval ) && is_wp_error( $thumb ) ) {
     117                                        $retval = $thumb;
     118                                }
     119
     120                                // Thumbnail is good so proceed
     121                                if ( false === $retval ) {
     122                                        $retval = $thumb;
     123                                }
     124
     125                        } else {
     126                                $retval = $editor;
     127                        }
     128                }
     129
     130                return $retval;
     131        }
     132
     133        /**
     134         *
     135         * @param type $file
     136         * @return boolean
     137         */
     138        public static function is_too_small( $file = array() ) {
     139                $uploaded_image = @getimagesize( $file );
     140                $full_width     = bp_core_avatar_full_width();
     141                $full_height    = bp_core_avatar_full_height();
     142
     143                if ( isset( $uploaded_image[0] ) && $uploaded_image[0] < $full_width || $uploaded_image[1] < $full_height ) {
     144                        return true;
     145                }
     146
     147                return false;
     148        }
     149}
  • src/bp-core/classes/class-bp-attachment.php

    diff --git src/bp-core/classes/class-bp-attachment.php src/bp-core/classes/class-bp-attachment.php
    index e69de29..9030267 100644
     
     1<?php
     2
     3/**
     4 * Core attachment class.
     5 *
     6 * @package BuddyPress
     7 * @subpackage Core
     8 */
     9
     10// Exit if accessed directly
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * BP Attachment class to manage your component's uploads
     15 *
     16 * @since BuddyPress (2.3.0)
     17 */
     18class BP_Attachment {
     19
     20        /** Upload properties *****************************************************/
     21
     22        /**
     23         * The file being uploaded
     24         *
     25         * @var array
     26         */
     27        public $attachment = array();
     28
     29        /**
     30         * Maximum file size in kilobytes
     31         *
     32         * @var int
     33         */
     34        public $original_max_filesize = 5120000;
     35
     36        /**
     37         * List of allowed file extensions
     38         * Defaults to get_allowed_mime_types()
     39         *
     40         * @var int
     41         */
     42        public $allowed_mime_types = array();
     43
     44        /**
     45         * component's upload base directory.
     46         *
     47         * @var string
     48         */
     49        public $base_dir = '';
     50
     51        /**
     52         * The upload action.
     53         *
     54         * @var string
     55         */
     56        public $action = '';
     57
     58        /**
     59         * The file input name attribute
     60         *
     61         * @var string
     62         */
     63        public $file_input = 'file';
     64
     65        /**
     66         * List of upload errors.
     67         *
     68         * @var array
     69         */
     70        public $upload_error_strings = array();
     71
     72        /**
     73         * List of required core files
     74         *
     75         * @var array
     76         */
     77        public $required_wp_files = array( 'file' );
     78
     79        /**
     80         * Construct Upload parameters
     81         *
     82         * @since BuddyPress (2.3.0)
     83         *
     84         * @param array $args {
     85         *     @type int    $original_max_filesize Maximum file size in kilobytes. Default: 5120000.
     86         *     @type array  $allowed_mime_types    List of allowed file extensions (eg: array( 'jpg', 'gif', 'png' ) ).
     87         *                                         Defaults to WordPress allowed mime types
     88         *     @type string $base_dir              Component's upload base directory. Defaults to WordPress 'uploads'
     89         *     @type string $action                The upload action used when uploading a file, $_POST['action'] must be set
     90         *                                         and its value must equal $action {@link wp_handle_upload()}
     91         *     @type string $file_input            The name attribute used in the file input. Default: file
     92         *     @type array  $upload_error_strings  A list of specific error messages (optional).
     93         *     @type array  $required_wp_files     The list of required WordPress core files. Default: array( 'file' );
     94         * }
     95         * @uses  sanitize_key()
     96         * @uses  bp_parse_args()
     97         * @uses  BP_Attachment->set_upload_error_strings()
     98         * @uses  BP_Attachment->set_upload_dir()
     99         */
     100        public function __construct( $args = '' ) {
     101
     102                /**
     103                 * Sanitize the action ID
     104                 */
     105                if ( ! empty( $args['action'] ) ) {
     106                        $this->action = sanitize_key( $args['action'] );
     107                }
     108
     109                $params = bp_parse_args( $args, get_class_vars( __CLASS__ ), $this->action . '_upload_params' );
     110
     111                foreach ( $params as $key => $param ) {
     112                        if ( 'upload_error_strings' === $key ) {
     113                                $this->{$key} = $this->set_upload_error_strings( $param );
     114                        } else {
     115                                $this->{$key} = $param;
     116                        }
     117                }
     118
     119                // Set the path/url and base dir for uploads
     120                $this->set_upload_dir();
     121        }
     122
     123        /**
     124         * Set data from the BP root blog's upload directory.
     125         *
     126         * Handy for multisite instances because all uploads are made on the BP root
     127         * blog and we need to query the BP root blog for the upload directory data.
     128         *
     129         * This function ensures that we only need to use {@link switch_to_blog()}
     130         * once to get what we need.
     131         *
     132         * @since BuddyPress (2.3.0)
     133         *
     134         * @uses  is_multisite()
     135         * @uses  bp_is_root_blog()
     136         * @uses  switch_to_blog()
     137         * @uses  wp_upload_dir()
     138         * @uses  restore_current_blog()
     139         */
     140        public function set_upload_dir() {
     141                $bp = buddypress();
     142
     143                if ( empty( $bp->upload_dir ) ) {
     144                        // Do we need to juggle which blog to get the upload dir for?
     145                        $need_switch = (bool) ( is_multisite() && ! bp_is_root_blog() );
     146
     147                        // Maybe juggle to root blog
     148                        if ( true === $need_switch ) {
     149                                switch_to_blog( bp_get_root_blog_id() );
     150                        }
     151
     152                        // Get the upload directory (maybe for root blog)
     153                        $wp_upload_dir = wp_upload_dir();
     154
     155                        // Maybe juggle back to current blog
     156                        if ( true === $need_switch ) {
     157                                restore_current_blog();
     158                        }
     159
     160                        // Bail if an error occurred
     161                        if ( ! empty( $wp_upload_dir['error'] ) ) {
     162                                return;
     163                        }
     164
     165                        $bp->upload_dir = $wp_upload_dir;
     166                }
     167
     168                // Set the directory, path, & url variables
     169                $this->upload_dir  = $bp->upload_dir;
     170                $this->upload_path = $bp->upload_dir['basedir'];
     171                $this->url         = $bp->upload_dir['baseurl'];
     172
     173                // Ensure URL is https if SSL is set/forced
     174                if ( is_ssl() ) {
     175                        $this->url = str_replace( 'http://', 'https://', $this->url );
     176                }
     177
     178                // Custom base dir
     179                if ( ! empty( $this->base_dir ) ) {
     180                        $this->upload_path = trailingslashit( $this->upload_path ) . $this->base_dir;
     181                        $this->url         = trailingslashit( $this->upload_url  ) . $this->base_dir;
     182                }
     183        }
     184
     185        /**
     186         * Set Upload error messages
     187         *
     188         * Used into the $overrides argument of BP_Attachment->upload()
     189         *
     190         * @since BuddyPress (2.3.0)
     191         *
     192         * @param array $param a list of error messages to add to BuddyPress core ones
     193         */
     194        public function set_upload_error_strings( $param = array() ) {
     195                /**
     196                 * Index of the array is the error code
     197                 * Custom errors will start at 9 code
     198                 */
     199                return array_merge( array(
     200                        0 => __( 'The file was uploaded successfully', 'buddypress' ),
     201                        1 => __( 'The uploaded file exceeds the maximum allowed file size on this site', 'buddypress' ),
     202                        2 => sprintf( __( 'The uploaded file exceeds the maximum allowed file size of: %s', 'buddypress' ), size_format( $this->original_max_filesize ) ),
     203                        3 => __( 'The uploaded file was only partially uploaded.', 'buddypress' ),
     204                        4 => __( 'No file was uploaded.', 'buddypress' ),
     205                        5 => '',
     206                        6 => __( 'Missing a temporary folder.', 'buddypress' ),
     207                        7 => __( 'Failed to write file to disk.', 'buddypress' ),
     208                        8 => __( 'File upload stopped by extension.', 'buddypress' ),
     209                ), (array) $param );
     210        }
     211
     212        /**
     213         * Include the WordPress core needed files
     214         *
     215         * @since BuddyPress (2.3.0)
     216         */
     217        private function includes() {
     218                foreach ( $this->required_wp_files as $wp_file ) {
     219                        if ( ! file_exists( ABSPATH . "/wp-admin/includes/{$wp_file}.php" ) ) {
     220                                continue;
     221                        }
     222
     223                        require_once( ABSPATH . "/wp-admin/includes/{$wp_file}.php" );
     224                }
     225        }
     226
     227        /**
     228         * Upload the attachment
     229         *
     230         * @since BuddyPress (2.3.0)
     231         *
     232         * @param  array $file               The appropriate entry the from $_FILES superglobal.
     233         * @param  string $upload_dir_filter A specific filter to be applied to 'upload_dir' (optional).
     234         * @uses   wp_handle_upload()
     235         * @uses   apply_filters()           Call 'bp_attachment_upload_overrides' to include specific upload overrides
     236         *
     237         * @return array                     On success, returns an associative array of file attributes.
     238         *                                   On failure, returns an array containing the error message
     239         *                                   (eg: array( 'error' => $message ) )
     240         */
     241        public function upload( $file, $upload_dir_filter = '' ) {
     242                if ( ! empty( $this->action ) ) {
     243                        /**
     244                         * Add custom rules before enabling the file upload
     245                         */
     246                        add_filter( "{$this->action}_prefilter", array( $this, 'validate_upload' ), 10, 1 );
     247                }
     248
     249                // Set Default overrides
     250                $overrides = array(
     251                        'action'               => $this->action,
     252                        'upload_error_strings' => $this->upload_error_strings,
     253                );
     254
     255                /**
     256                 * Add a mime override if needed
     257                 * Used to restrict uploads by extensions
     258                 */
     259                if ( ! empty( $this->allowed_mime_types ) ) {
     260                        $mime_types = $this->validate_mime_types();
     261
     262                        if ( ! empty( $mime_types ) ) {
     263                                $overrides['mimes'] = $mime_types;
     264                        }
     265                }
     266
     267                /**
     268                 * If you need to add some overrides we haven't thought of
     269                 *
     270                 * @var  array $overrides the wp_handle_upload overrides
     271                 */
     272                $overrides = apply_filters( 'bp_attachment_upload_overrides', $overrides );
     273
     274                $this->includes();
     275
     276                /**
     277                 * If the $base_dir was set when constructing the class,
     278                 * and no specific filter has been requested, use a default
     279                 * filter to create the specific $base dir
     280                 * @see  BP_Attachment->upload_dir_filter()
     281                 */
     282                if ( empty( $upload_dir_filter ) && ! empty( $this->base_dir ) ) {
     283                        $upload_dir_filter = array( $this, 'upload_dir_filter' );
     284                }
     285
     286                // Make sure the file will be uploaded in the attachment directory
     287                add_filter( 'upload_dir', $upload_dir_filter, 10, 0 );
     288
     289                // Upload the attachment
     290                $this->attachment = wp_handle_upload( $file[ $this->file_input ], $overrides );
     291
     292                // Restore WordPress Uploads data
     293                remove_filter( 'upload_dir', $upload_dir_filter, 10, 0 );
     294
     295                // Finally return the uploaded file or the error
     296                return $this->attachment;
     297        }
     298
     299        /**
     300         * Validate the allowed mime types using WordPress allowed mime types
     301         *
     302         * In case of a multisite, the mime types are already restricted by
     303         * the 'upload_filetypes' setting. BuddyPress will respect this setting.
     304         * @see check_upload_mimes()
     305         *
     306         * @since BuddyPress (2.3.0)
     307         *
     308         * @uses get_allowed_mime_types()
     309         */
     310        protected function validate_mime_types() {
     311                $wp_mimes = get_allowed_mime_types();
     312                $valid_mimes = array();
     313
     314                // Set the allowed mimes for the upload
     315                foreach ( (array) $this->allowed_mime_types as $ext ) {
     316                        foreach ( $wp_mimes as $ext_pattern => $mime ) {
     317                                if ( $ext != '' && strpos( $ext_pattern, $ext ) !== false ) {
     318                                        $valid_mimes[$ext_pattern] = $mime;
     319                                }
     320                        }
     321                }
     322                return $valid_mimes;
     323        }
     324
     325        /**
     326         * Specific upload rules
     327         *
     328         * Override this function from your child class to build your specific rules
     329         * @see BP_Attachment_Avatar->validate_upload() for an example of use
     330         *
     331         * @since BuddyPress (2.3.0)
     332         *
     333         * @param  array $file the temporary file attributes (before it has been moved)
     334         * @return array the file
     335         */
     336        public function validate_upload( $file = array() ) {
     337                // Simply return the file, rules must be set in child class
     338                return $file;
     339        }
     340
     341        /**
     342         * Default filter to save the attachments
     343         *
     344         * @since BuddyPress (2.3.0)
     345         *
     346         * @uses   wp_mkdir_p()
     347         * @uses   do_action() call 'bp_attachment_base_upload_dir_created' to run specific action once the
     348         *                     $base_dir is created (eg: add an .htaccess file)
     349         * @uses   apply_filters() call 'bp_attachment_upload_dir' to eventually override the upload location
     350         *                         regarding to context
     351         * @return array the upload directory data
     352         */
     353        public function upload_dir_filter() {
     354
     355                /**
     356                 * Filters the component's upload directory.
     357                 *
     358                 * @since BuddyPress (2.3.0)
     359                 *
     360                 * @param array $value Array containing the path, URL, and other helpful settings.
     361                 */
     362                return apply_filters( 'bp_attachment_upload_dir', array(
     363                        'path'    => $this->upload_path,
     364                        'url'     => $this->url,
     365                        'subdir'  => false,
     366                        'basedir' => $this->upload_path,
     367                        'baseurl' => $this->url,
     368                        'error'   => false
     369                ) );
     370        }
     371
     372        public function create_dir() {
     373
     374                // Bail if we are allowing WordPress to make directories for us
     375                if ( empty( $this->create_dir ) ) {
     376                        return;
     377                }
     378
     379                // Check if upload path already exists
     380                if ( ! file_exists( $this->upload_path ) ) {
     381
     382                        // If path does not exist, attempt to create it
     383                        if ( ! wp_mkdir_p( $this->upload_path ) ) {
     384                                return false;
     385                        }
     386
     387                        /**
     388                         * Use this filter if you need to run specific actions
     389                         * once the directory is created
     390                         *
     391                         * @since BuddyPress (2.3.0)
     392                         *
     393                         * @var  string $component the component id
     394                         * @var  string $base_dir the specific base dir used by the component
     395                         */
     396                        do_action( 'bp_attachment_base_upload_dir_created', $this->component, $this->base_dir );
     397                }
     398        }
     399}
  • src/bp-groups/bp-groups-functions.php

    diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
    index 011231f..49864eb 100644
    function groups_avatar_upload_dir( $group_id = 0 ) { 
    817817                $group_id = bp_get_current_group_id();
    818818        }
    819819
    820         $path    = bp_core_avatar_upload_path() . '/group-avatars/' . $group_id;
    821         $newbdir = $path;
    822 
    823         if ( !file_exists( $path ) )
    824                 @wp_mkdir_p( $path );
    825 
    826         $newurl    = bp_core_avatar_url() . '/group-avatars/' . $group_id;
     820        $directory = 'group-avatars';
     821        $path      = bp_core_avatar_upload_path() . '/' . $directory . '/' . $group_id;
     822        $newbdir   = $path;
     823        $newurl    = bp_core_avatar_url() . '/' . $directory . '/' . $group_id;
    827824        $newburl   = $newurl;
    828         $newsubdir = '/group-avatars/' . $group_id;
     825        $newsubdir = '/' . $directory . '/' . $group_id;
    829826
    830827        /**
    831828         * Filters the avatar upload directory path for a given group.
    function groups_avatar_upload_dir( $group_id = 0 ) { 
    834831         *
    835832         * @param array $value Array of parts related to the groups avatar upload directory.
    836833         */
    837         return apply_filters( 'groups_avatar_upload_dir', array( 'path' => $path, 'url' => $newurl, 'subdir' => $newsubdir, 'basedir' => $newbdir, 'baseurl' => $newburl, 'error' => false ) );
     834        return apply_filters( 'groups_avatar_upload_dir', array(
     835                'path'    => $path,
     836                'url'     => $newurl,
     837                'subdir'  => $newsubdir,
     838                'basedir' => $newbdir,
     839                'baseurl' => $newburl,
     840                'error'   => false
     841        ) );
    838842}
    839843
    840844/** Group Member Status Checks ************************************************/
  • src/bp-members/bp-members-functions.php

    diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php
    index 346e7f9..4bf7a99 100644
    function bp_core_signup_avatar_upload_dir() { 
    21592159                return false;
    21602160        }
    21612161
    2162         $path  = bp_core_avatar_upload_path() . '/avatars/signups/' . $bp->signup->avatar_dir;
    2163         $newbdir = $path;
    2164 
    2165         if ( ! file_exists( $path ) ) {
    2166                 @wp_mkdir_p( $path );
    2167         }
    2168 
    2169         $newurl = bp_core_avatar_url() . '/avatars/signups/' . $bp->signup->avatar_dir;
    2170         $newburl = $newurl;
    2171         $newsubdir = '/avatars/signups/' . $bp->signup->avatar_dir;
     2162        $directory = 'avatars/signups';
     2163        $path      = bp_core_avatar_upload_path() . '/' . $directory . '/' . $bp->signup->avatar_dir;
     2164        $newbdir   = $path;
     2165        $newurl    = bp_core_avatar_url() . '/' . $directory . '/' . $bp->signup->avatar_dir;
     2166        $newburl   = $newurl;
     2167        $newsubdir = '/' . $directory . '/' . $bp->signup->avatar_dir;
    21722168
    21732169        /**
    21742170         * Filters the avatar storage directory for use during registration.
    function bp_core_signup_avatar_upload_dir() { 
    21832179                'subdir'  => $newsubdir,
    21842180                'basedir' => $newbdir,
    21852181                'baseurl' => $newburl,
    2186                 'error' => false
     2182                'error'   => false
    21872183        ) );
    21882184}
    21892185
  • src/bp-xprofile/bp-xprofile-functions.php

    diff --git src/bp-xprofile/bp-xprofile-functions.php src/bp-xprofile/bp-xprofile-functions.php
    index 16c1599..62c37ed 100644
    function xprofile_avatar_upload_dir( $directory = 'avatars', $user_id = 0 ) { 
    680680                $directory = 'avatars';
    681681        }
    682682
    683         $path    = bp_core_avatar_upload_path() . '/' . $directory. '/' . $user_id;
    684         $newbdir = $path;
    685 
    686         if ( ! file_exists( $path ) ) {
    687                 @wp_mkdir_p( $path );
    688         }
    689 
     683        $path      = bp_core_avatar_upload_path() . '/' . $directory. '/' . $user_id;
     684        $newbdir   = $path;
    690685        $newurl    = bp_core_avatar_url() . '/' . $directory. '/' . $user_id;
    691686        $newburl   = $newurl;
    692687        $newsubdir = '/' . $directory. '/' . $user_id;
  • tests/phpunit/testcases/core/avatars.php

    diff --git tests/phpunit/testcases/core/avatars.php tests/phpunit/testcases/core/avatars.php
    index d37fe1a..d11c436 100644
    class BP_Tests_Avatars extends BP_UnitTestCase { 
    3535        }
    3636
    3737        /**
     38         * @group bp_core_set_avatar_globals
     39         */
     40        public function test_bp_core_set_avatar_globals() {
     41                $bp = buddypress();
     42
     43                $bp_avatar = $bp->avatar;
     44                $bp->avatar = new stdClass;
     45
     46                bp_core_set_avatar_globals();
     47
     48                $expected = array(
     49                        'thumb_widh'            => BP_AVATAR_THUMB_WIDTH,
     50                        'thumb_height'          => BP_AVATAR_THUMB_HEIGHT,
     51                        'full_width'            => BP_AVATAR_FULL_WIDTH,
     52                        'full_height'           => BP_AVATAR_FULL_HEIGHT,
     53                        'original_max_width'    => BP_AVATAR_ORIGINAL_MAX_WIDTH,
     54                        'original_max_filesize' => BP_AVATAR_ORIGINAL_MAX_FILESIZE,
     55                        'thumb_default'         => bp_core_avatar_default_thumb(),
     56                        'full_default'          => bp_core_avatar_default(),
     57                        'upload_path'           => bp_core_avatar_upload_path(),
     58                        'url'                   => bp_core_avatar_url(),
     59                        'show_avatars'          => (bool) BP_SHOW_AVATARS,
     60                );
     61
     62                $tested = array(
     63                        'thumb_widh'            => $bp->avatar->thumb->width,
     64                        'thumb_height'          => $bp->avatar->thumb->height,
     65                        'full_width'            => $bp->avatar->full->width,
     66                        'full_height'           => $bp->avatar->full->height,
     67                        'original_max_width'    => $bp->avatar->original_max_width,
     68                        'original_max_filesize' => $bp->avatar->original_max_filesize,
     69                        'thumb_default'         => $bp->avatar->thumb->default,
     70                        'full_default'          => $bp->avatar->full->default,
     71                        'upload_path'           => $bp->avatar->upload_path,
     72                        'url'                   => $bp->avatar->url,
     73                        'show_avatars'          => $bp->avatar->show_avatars,
     74                );
     75
     76                $this->assertSame( $expected, $tested );
     77
     78                // reset $bp->avatar
     79                $bp->avatar = $bp_avatar;
     80        }
     81
     82        /**
    3883         * @ticket BP4948
    3984         */
    4085        function test_avatars_on_non_root_blog() {