Skip to:
Content

BuddyPress.org

Ticket #6278: 6278.06.patch

File 6278.06.patch, 35.7 KB (added by imath, 10 years ago)

Adds a crop method

  • 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..103ce22 100644
    function bp_core_delete_existing_avatar( $args = '' ) { 
    564564 * @see bp_core_check_avatar_upload()
    565565 * @see bp_core_check_avatar_type()
    566566 *
    567  * @param array $file The appropriate entry the from $_FILES superglobal.
     567 * @param array  $file              The appropriate entry the from $_FILES superglobal.
    568568 * @param string $upload_dir_filter A filter to be applied to 'upload_dir'.
     569 *
    569570 * @return bool True on success, false on failure.
    570571 */
    571572function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) {
    function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
    574575         * You may want to hook into this filter if you want to override this function.
    575576         * Make sure you return false.
    576577         */
    577         if ( !apply_filters( 'bp_core_pre_avatar_handle_upload', true, $file, $upload_dir_filter ) )
     578        if ( ! apply_filters( 'bp_core_pre_avatar_handle_upload', true, $file, $upload_dir_filter ) ) {
    578579                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;
    594580        }
    595581
    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;
    599         }
     582        // Setup some variables
     583        $bp          = buddypress();
     584        $upload_path = bp_core_avatar_upload_path();
    600585
    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();
     586        // Upload the file
     587        $avatar_attachment = new BP_Attachment_Avatar();
     588        $bp->avatar_admin->original = $avatar_attachment->upload( $file, $upload_dir_filter );
    610589
    611         $bp->avatar_admin->original = wp_handle_upload( $file['file'], array( 'action'=> 'bp_avatar_upload' ) );
    612 
    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'] ) ) {
     590        // In case of an error, stop the process and display a feedback to the user
     591        if ( ! empty( $bp->avatar_admin->original['error'] ) ) {
    619592                bp_core_add_message( sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->original['error'] ), 'error' );
    620593                return false;
    621594        }
    622595
    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();
     596        // Maybe resize
     597        $bp->avatar_admin->resized = $avatar_attachment->shrink( $bp->avatar_admin->original['file'] );
     598        $bp->avatar_admin->image   = new stdClass();
    663599
    664600        // We only want to handle one image after resize.
    665601        if ( empty( $bp->avatar_admin->resized ) ) {
    666                 $bp->avatar_admin->image->dir = str_replace( bp_core_avatar_upload_path(), '', $bp->avatar_admin->original['file'] );
     602                $bp->avatar_admin->image->file = $bp->avatar_admin->original['file'];
     603                $bp->avatar_admin->image->dir  = str_replace( $upload_path, '', $bp->avatar_admin->original['file'] );
    667604        } else {
    668                 $bp->avatar_admin->image->dir = str_replace( bp_core_avatar_upload_path(), '', $bp->avatar_admin->resized['path'] );
     605                $bp->avatar_admin->image->file = $bp->avatar_admin->resized['path'];
     606                $bp->avatar_admin->image->dir  = str_replace( $upload_path, '', $bp->avatar_admin->resized['path'] );
    669607                @unlink( $bp->avatar_admin->original['file'] );
    670608        }
    671609
    function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
    675613                return false;
    676614        }
    677615
    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' );
     616        // If the uploaded image is smaller than the "full" dimensions, throw a warning
     617        if ( $avatar_attachment->is_too_small( $bp->avatar_admin->image->file ) ) {
     618                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' );
    685619        }
    686620
    687621        // Set the url value for the image
    function bp_core_avatar_handle_crop( $args = '' ) { 
    738672         * You may want to hook into this filter if you want to override this function.
    739673         * Make sure you return false.
    740674         */
    741         if ( !apply_filters( 'bp_core_pre_avatar_handle_crop', true, $r ) )
     675        if ( ! apply_filters( 'bp_core_pre_avatar_handle_crop', true, $r ) ) {
    742676                return true;
    743 
    744         extract( $r, EXTR_SKIP );
    745 
    746         if ( empty( $original_file ) )
    747                 return false;
    748 
    749         $original_file = bp_core_avatar_upload_path() . $original_file;
    750 
    751         if ( !file_exists( $original_file ) )
    752                 return false;
    753 
    754         if ( empty( $item_id ) ) {
    755                 $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', dirname( $original_file ), $item_id, $object, $avatar_dir );
    756         } else {
    757                 $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', bp_core_avatar_upload_path() . '/' . $avatar_dir . '/' . $item_id, $item_id, $object, $avatar_dir );
    758         }
    759 
    760         if ( !file_exists( $avatar_folder_dir ) )
    761                 return false;
    762 
    763         require_once( ABSPATH . '/wp-admin/includes/image.php' );
    764         require_once( ABSPATH . '/wp-admin/includes/file.php' );
    765 
    766         // Delete the existing avatar files for the object
    767         $existing_avatar = bp_core_fetch_avatar( array(
    768                 'object'  => $object,
    769                 'item_id' => $item_id,
    770                 'html' => false,
    771         ) );
    772 
    773         if ( ! empty( $existing_avatar ) ) {
    774                 // Check that the new avatar doesn't have the same name as the
    775                 // old one before deleting
    776                 $upload_dir           = wp_upload_dir();
    777                 $existing_avatar_path = str_replace( $upload_dir['baseurl'], '', $existing_avatar );
    778                 $new_avatar_path      = str_replace( $upload_dir['basedir'], '', $original_file );
    779 
    780                 if ( $existing_avatar_path !== $new_avatar_path ) {
    781                         bp_core_delete_existing_avatar( array( 'object' => $object, 'item_id' => $item_id, 'avatar_path' => $avatar_folder_dir ) );
    782                 }
    783677        }
    784678
     679        // Crop the file
     680        $avatar_attachment = new BP_Attachment_Avatar();
     681        $cropped           = $avatar_attachment->crop( $r );
    785682
    786 
    787         // Make sure we at least have a width and height for cropping
    788         if ( empty( $crop_w ) ) {
    789                 $crop_w = bp_core_avatar_full_width();
    790         }
    791 
    792         if ( empty( $crop_h ) ) {
    793                 $crop_h = bp_core_avatar_full_height();
    794         }
    795 
    796         // Get the file extension
    797         $data = @getimagesize( $original_file );
    798         $ext  = $data['mime'] == 'image/png' ? 'png' : 'jpg';
    799 
    800         // Set the full and thumb filenames
    801         $full_filename  = wp_hash( $original_file . time() ) . '-bpfull.'  . $ext;
    802         $thumb_filename = wp_hash( $original_file . time() ) . '-bpthumb.' . $ext;
    803 
    804         // Crop the image
    805         $full_cropped  = wp_crop_image( $original_file, (int) $crop_x, (int) $crop_y, (int) $crop_w, (int) $crop_h, bp_core_avatar_full_width(),  bp_core_avatar_full_height(),  false, $avatar_folder_dir . '/' . $full_filename  );
    806         $thumb_cropped = wp_crop_image( $original_file, (int) $crop_x, (int) $crop_y, (int) $crop_w, (int) $crop_h, bp_core_avatar_thumb_width(), bp_core_avatar_thumb_height(), false, $avatar_folder_dir . '/' . $thumb_filename );
    807 
    808         // Check for errors
    809         if ( empty( $full_cropped ) || empty( $thumb_cropped ) || is_wp_error( $full_cropped ) || is_wp_error( $thumb_cropped ) )
    810                 return false;
    811 
    812         // Remove the original
    813         @unlink( $original_file );
    814 
    815         return true;
     683        return is_array( $cropped );
    816684}
    817685
    818686/**
    function bp_core_check_avatar_type($file) { 
    926794/**
    927795 * Fetch data from the BP root blog's upload directory.
    928796 *
    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  *
    935797 * @since BuddyPress (1.8.0)
    936798 *
    937  * @uses wp_upload_dir()
    938  *
    939799 * @param string $type The variable we want to return from the $bp->avatars
    940800 *        object. Only 'upload_path' and 'url' are supported. Default: 'upload_path'.
    941801 * @return string The avatar upload directory path.
    function bp_core_get_upload_dir( $type = 'upload_path' ) { 
    977837
    978838                        // No cache, so query for it
    979839                        } 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                                 }
    984840
    985841                                // Get upload directory information from current site
    986                                 $upload_dir = wp_upload_dir();
    987 
    988                                 // Will bail if not switched
    989                                 restore_current_blog();
     842                                $upload_dir = bp_upload_dir();
    990843
    991844                                // Stash upload directory data for later use
    992845                                $bp->avatar->upload_dir = $upload_dir;
    function bp_core_get_upload_dir( $type = 'upload_path' ) { 
    1018871/**
    1019872 * Get the absolute upload path for the WP installation.
    1020873 *
    1021  * @uses wp_upload_dir To get upload directory info
     874 * @uses bp_core_get_upload_dir() To get upload directory info
    1022875 *
    1023876 * @return string Absolute path to WP upload directory.
    1024877 */
    function bp_core_avatar_upload_path() { 
    1029882/**
    1030883 * Get the raw base URL for root site upload location.
    1031884 *
    1032  * @uses wp_upload_dir To get upload directory info.
     885 * @uses bp_core_get_upload_dir() To get upload directory info.
    1033886 *
    1034887 * @return string Full URL to current upload location.
    1035888 */
  • 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/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 0671b49..5b7bead 100644
    function bp_core_get_suggestions( $args ) { 
    21372137
    21382138        return apply_filters( 'bp_core_get_suggestions', $retval, $args );
    21392139}
     2140
     2141/**
     2142 * Set data from the BP root blog's upload directory.
     2143 *
     2144 * Handy for multisite instances because all uploads are made on the BP root
     2145 * blog and we need to query the BP root blog for the upload directory data.
     2146 *
     2147 * This function ensures that we only need to use {@link switch_to_blog()}
     2148 * once to get what we need.
     2149 *
     2150 * @since BuddyPress (2.3.0)
     2151 *
     2152 * @uses  is_multisite()
     2153 * @uses  bp_is_root_blog()
     2154 * @uses  switch_to_blog()
     2155 * @uses  wp_upload_dir()
     2156 * @uses  restore_current_blog()
     2157 */
     2158function bp_upload_dir() {
     2159        $bp = buddypress();
     2160
     2161        if ( empty( $bp->upload_dir ) ) {
     2162                $need_switch = (bool) ( is_multisite() && ! bp_is_root_blog() );
     2163
     2164                // Maybe juggle to root blog
     2165                if ( true === $need_switch ) {
     2166                        switch_to_blog( bp_get_root_blog_id() );
     2167                }
     2168
     2169                // Get the upload directory (maybe for root blog)
     2170                $wp_upload_dir = wp_upload_dir();
     2171
     2172                // Maybe juggle back to current blog
     2173                if ( true === $need_switch ) {
     2174                        restore_current_blog();
     2175                }
     2176
     2177                // Bail if an error occurred
     2178                if ( ! empty( $wp_upload_dir['error'] ) ) {
     2179                        return false;
     2180                }
     2181
     2182                $bp->upload_dir = $wp_upload_dir;
     2183        }
     2184
     2185        return $bp->upload_dir;
     2186}
  • 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..3df7924 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() {
     32                parent::__construct( array(
     33                        // Upload action
     34                        'action' => 'bp_avatar_upload',
     35
     36                        // Specific errors for avatars
     37                        'upload_error_strings'  => array(
     38                                sprintf( __( 'That photo is too big. Please upload one smaller than %s', 'buddypress' ), size_format( bp_core_avatar_original_max_filesize() ) ),
     39                                __( 'Please upload only JPG, GIF or PNG photos.', 'buddypress' ),
     40                        ),
     41                ) );
     42        }
     43
     44        /**
     45         * Set Upload Dir data for avatars
     46         *
     47         * @since BuddyPress (2.3.0)
     48         *
     49         * @uses bp_core_avatar_upload_path()
     50         * @uses bp_core_avatar_url()
     51         * @uses bp_upload_dir()
     52         */
     53        public function set_upload_dir() {
     54                if ( bp_core_avatar_upload_path() && bp_core_avatar_url() ) {
     55                        $this->upload_path = bp_core_avatar_upload_path();
     56                        $this->url         = bp_core_avatar_url();
     57                        $this->upload_dir  = bp_upload_dir();
     58                } else {
     59                        parent::set_upload_dir();
     60                }
     61        }
     62
     63        /**
     64         * Avatar specific rules
     65         *
     66         * Adds an error if the avatar size or type don't match BuddyPress needs
     67         * The error code is the index of $upload_error_strings
     68         *
     69         * @since BuddyPress (2.3.0)
     70         *
     71         * @param  array $file the temporary file attributes (before it has been moved)
     72         * @uses   bp_core_check_avatar_size()
     73         * @uses   bp_core_check_avatar_type()
     74         * @return array the file with extra errors if needed
     75         */
     76        public function validate_upload( $file = array() ) {
     77
     78                // Bail if already an error
     79                if ( ! empty( $file['error'] ) ) {
     80                        return $file;
     81                }
     82
     83                // File size is too big
     84                if ( ! bp_core_check_avatar_size( array( 'file' => $file ) ) ) {
     85                        $file['error'] = 9;
     86
     87                // File is of invalid type
     88                } else if ( ! bp_core_check_avatar_type( array( 'file' => $file ) ) ) {
     89                        $file['error'] = 10;
     90                }
     91
     92                // Return with error code attached
     93                return $file;
     94        }
     95
     96        /**
     97         * Maybe shrink the attachment to fit maximum allowed width
     98         *
     99         * @since BuddyPress (2.3.0)
     100         *
     101         * @return mixed
     102         */
     103        public static function shrink( $file = array() ) {
     104
     105                // Get image size
     106                $size   = @getimagesize( $file );
     107                $retval = false;
     108
     109                // Check image size and shrink if too large
     110                if ( $size[0] > bp_core_avatar_original_max_width() ) {
     111                        $editor = wp_get_image_editor( $file );
     112
     113                        if ( ! is_wp_error( $editor ) ) {
     114                                $editor->set_quality( 100 );
     115
     116                                $resized = $editor->resize( bp_core_avatar_original_max_width(), bp_core_avatar_original_max_width(), false );
     117                                if ( ! is_wp_error( $resized ) ) {
     118                                        $thumb = $editor->save( $editor->generate_filename() );
     119                                } else {
     120                                        $retval = $resized;
     121                                }
     122
     123                                // Check for thumbnail creation errors
     124                                if ( ( false === $retval ) && is_wp_error( $thumb ) ) {
     125                                        $retval = $thumb;
     126                                }
     127
     128                                // Thumbnail is good so proceed
     129                                if ( false === $retval ) {
     130                                        $retval = $thumb;
     131                                }
     132
     133                        } else {
     134                                $retval = $editor;
     135                        }
     136                }
     137
     138                return $retval;
     139        }
     140
     141        /**
     142         * Check if the image dimensions are smaller than full avatar dimensions
     143         *
     144         * @since BuddyPress (2.3.0)
     145         *
     146         * @param type $file
     147         * @return boolean
     148         */
     149        public static function is_too_small( $file = array() ) {
     150                $uploaded_image = @getimagesize( $file );
     151                $full_width     = bp_core_avatar_full_width();
     152                $full_height    = bp_core_avatar_full_height();
     153
     154                if ( isset( $uploaded_image[0] ) && $uploaded_image[0] < $full_width || $uploaded_image[1] < $full_height ) {
     155                        return true;
     156                }
     157
     158                return false;
     159        }
     160
     161        /**
     162         * Crop the avatar
     163         *
     164         * @since BuddyPress (2.3.0)
     165         *
     166         * @see  bp_core_avatar_handle_crop() for list of parameters
     167         * @param array $args
     168         * @return array the cropped avatars (full and thumb)
     169         */
     170        public function crop( $args = array() ) {
     171                // Bail if the original file is missing
     172                if ( empty( $args['original_file'] ) ) {
     173                        return false;
     174                }
     175
     176                // We need to manipulate the image
     177                $this->required_wp_files[] = 'image';
     178
     179                /**
     180                 * Original file is a relative path to the image
     181                 * eg: /avatars/1/avatar.jpg
     182                 */
     183                $relative_path = $args['original_file'];
     184                $absolute_path = $this->upload_path . $relative_path;
     185
     186                // Bail if the avatar is not available
     187                if ( ! file_exists( $absolute_path ) )  {
     188                        return false;
     189                }
     190
     191                if ( empty( $args['item_id'] ) ) {
     192                        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', dirname( $absolute_path ), $args['item_id'], $args['object'], $args['avatar_dir'] );
     193                } else {
     194                        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $this->upload_path . '/' . $args['avatar_dir'] . '/' . $args['item_id'], $args['item_id'], $args['object'], $args['avatar_dir'] );
     195                }
     196
     197                // Bail if the avatar folder is missing for this item_id
     198                if ( ! file_exists( $avatar_folder_dir ) ) {
     199                        return false;
     200                }
     201
     202                // Include the WordPress core needed files
     203                $this->includes();
     204
     205                // Delete the existing avatar files for the object
     206                $existing_avatar = bp_core_fetch_avatar( array(
     207                        'object'  => $args['object'],
     208                        'item_id' => $args['item_id'],
     209                        'html' => false,
     210                ) );
     211
     212                /**
     213                 * Check that the new avatar doesn't have the same name as the
     214                 * old one before deleting
     215                 */
     216                if ( ! empty( $existing_avatar ) && $existing_avatar !== $this->url . $relative_path ) {
     217                        bp_core_delete_existing_avatar( array( 'object' => $args['object'], 'item_id' => $args['item_id'], 'avatar_path' => $avatar_folder_dir ) );
     218                }
     219
     220                // Make sure we at least have minimal data for cropping
     221                if ( empty( $args['crop_w'] ) ) {
     222                        $crop_w = bp_core_avatar_full_width();
     223                } else {
     224                        $crop_w = $args['crop_w'];
     225                }
     226
     227                if ( empty( $args['crop_h'] ) ) {
     228                        $crop_h = bp_core_avatar_full_height();
     229                } else {
     230                        $crop_h = $args['crop_h'];
     231                }
     232
     233                $crop_x = 0;
     234                if ( ! empty( $args['crop_x'] ) ) {
     235                        $crop_x = $args['crop_x'];
     236                }
     237
     238                $crop_y = 0;
     239                if ( ! empty( $args['crop_y'] ) ) {
     240                        $crop_y = $args['crop_y'];
     241                }
     242
     243                // Get the file extension
     244                $data = @getimagesize( $absolute_path );
     245                $ext  = $data['mime'] == 'image/png' ? 'png' : 'jpg';
     246
     247                // Set the full and thumb filenames
     248                $full_filename  = wp_hash( $absolute_path . time() ) . '-bpfull.'  . $ext;
     249                $thumb_filename = wp_hash( $absolute_path . time() ) . '-bpthumb.' . $ext;
     250
     251                // Crop the image
     252                $full_cropped  = wp_crop_image( $absolute_path, (int) $crop_x, (int) $crop_y, (int) $crop_w, (int) $crop_h, bp_core_avatar_full_width(),  bp_core_avatar_full_height(),  false, $avatar_folder_dir . '/' . $full_filename  );
     253                $thumb_cropped = wp_crop_image( $absolute_path, (int) $crop_x, (int) $crop_y, (int) $crop_w, (int) $crop_h, bp_core_avatar_thumb_width(), bp_core_avatar_thumb_height(), false, $avatar_folder_dir . '/' . $thumb_filename );
     254
     255                // Check for errors
     256                if ( empty( $full_cropped ) || empty( $thumb_cropped ) || is_wp_error( $full_cropped ) || is_wp_error( $thumb_cropped ) ) {
     257                        return false;
     258                }
     259
     260                // Remove the original
     261                @unlink( $absolute_path );
     262
     263                // Return the full and thumb cropped avatars
     264                return array(
     265                        'full'  => trailingslashit( $avatar_folder_dir ) . $full_filename,
     266                        'thumb' => trailingslashit( $avatar_folder_dir ) . $thumb_filename,
     267                );
     268        }
     269}
  • 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..21708f1 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 upload path and url for the component.
     125         *
     126         * @since BuddyPress (2.3.0)
     127         *
     128         * @uses  bp_upload_dir()
     129         */
     130        public function set_upload_dir() {
     131                // Set the directory, path, & url variables
     132                $this->upload_dir  = bp_upload_dir();
     133
     134                if ( empty( $this->upload_dir ) ) {
     135                        return false;
     136                }
     137
     138                $this->upload_path = $this->upload_dir['basedir'];
     139                $this->url         = $this->upload_dir['baseurl'];
     140
     141                // Ensure URL is https if SSL is set/forced
     142                if ( is_ssl() ) {
     143                        $this->url = str_replace( 'http://', 'https://', $this->url );
     144                }
     145
     146                /**
     147                 * Custom base dir.
     148                 *
     149                 * If the component set this property, set the specific path, url and create the dir
     150                 */
     151                if ( ! empty( $this->base_dir ) ) {
     152                        $this->upload_path = trailingslashit( $this->upload_path ) . $this->base_dir;
     153                        $this->url         = trailingslashit( $this->url  ) . $this->base_dir;
     154
     155                        // Finally create the base dir
     156                        $this->create_dir();
     157                }
     158        }
     159
     160        /**
     161         * Set Upload error messages
     162         *
     163         * Used into the $overrides argument of BP_Attachment->upload()
     164         *
     165         * @since BuddyPress (2.3.0)
     166         *
     167         * @param array $param a list of error messages to add to BuddyPress core ones
     168         */
     169        public function set_upload_error_strings( $param = array() ) {
     170                /**
     171                 * Index of the array is the error code
     172                 * Custom errors will start at 9 code
     173                 */
     174                return array_merge( array(
     175                        0 => __( 'The file was uploaded successfully', 'buddypress' ),
     176                        1 => __( 'The uploaded file exceeds the maximum allowed file size on this site', 'buddypress' ),
     177                        2 => sprintf( __( 'The uploaded file exceeds the maximum allowed file size of: %s', 'buddypress' ), size_format( $this->original_max_filesize ) ),
     178                        3 => __( 'The uploaded file was only partially uploaded.', 'buddypress' ),
     179                        4 => __( 'No file was uploaded.', 'buddypress' ),
     180                        5 => '',
     181                        6 => __( 'Missing a temporary folder.', 'buddypress' ),
     182                        7 => __( 'Failed to write file to disk.', 'buddypress' ),
     183                        8 => __( 'File upload stopped by extension.', 'buddypress' ),
     184                ), (array) $param );
     185        }
     186
     187        /**
     188         * Include the WordPress core needed files
     189         *
     190         * @since BuddyPress (2.3.0)
     191         */
     192        public function includes() {
     193                foreach ( $this->required_wp_files as $wp_file ) {
     194                        if ( ! file_exists( ABSPATH . "/wp-admin/includes/{$wp_file}.php" ) ) {
     195                                continue;
     196                        }
     197
     198                        require_once( ABSPATH . "/wp-admin/includes/{$wp_file}.php" );
     199                }
     200        }
     201
     202        /**
     203         * Upload the attachment
     204         *
     205         * @since BuddyPress (2.3.0)
     206         *
     207         * @param  array $file               The appropriate entry the from $_FILES superglobal.
     208         * @param  string $upload_dir_filter A specific filter to be applied to 'upload_dir' (optional).
     209         * @uses   wp_handle_upload()
     210         * @uses   apply_filters()           Call 'bp_attachment_upload_overrides' to include specific upload overrides
     211         *
     212         * @return array                     On success, returns an associative array of file attributes.
     213         *                                   On failure, returns an array containing the error message
     214         *                                   (eg: array( 'error' => $message ) )
     215         */
     216        public function upload( $file, $upload_dir_filter = '' ) {
     217                if ( ! empty( $this->action ) ) {
     218                        /**
     219                         * Add custom rules before enabling the file upload
     220                         */
     221                        add_filter( "{$this->action}_prefilter", array( $this, 'validate_upload' ), 10, 1 );
     222                }
     223
     224                // Set Default overrides
     225                $overrides = array(
     226                        'action'               => $this->action,
     227                        'upload_error_strings' => $this->upload_error_strings,
     228                );
     229
     230                /**
     231                 * Add a mime override if needed
     232                 * Used to restrict uploads by extensions
     233                 */
     234                if ( ! empty( $this->allowed_mime_types ) ) {
     235                        $mime_types = $this->validate_mime_types();
     236
     237                        if ( ! empty( $mime_types ) ) {
     238                                $overrides['mimes'] = $mime_types;
     239                        }
     240                }
     241
     242                /**
     243                 * If you need to add some overrides we haven't thought of
     244                 *
     245                 * @var  array $overrides the wp_handle_upload overrides
     246                 */
     247                $overrides = apply_filters( 'bp_attachment_upload_overrides', $overrides );
     248
     249                $this->includes();
     250
     251                /**
     252                 * If the $base_dir was set when constructing the class,
     253                 * and no specific filter has been requested, use a default
     254                 * filter to create the specific $base dir
     255                 * @see  BP_Attachment->upload_dir_filter()
     256                 */
     257                if ( empty( $upload_dir_filter ) && ! empty( $this->base_dir ) ) {
     258                        $upload_dir_filter = array( $this, 'upload_dir_filter' );
     259                }
     260
     261                // Make sure the file will be uploaded in the attachment directory
     262                add_filter( 'upload_dir', $upload_dir_filter, 10, 0 );
     263
     264                // Upload the attachment
     265                $this->attachment = wp_handle_upload( $file[ $this->file_input ], $overrides );
     266
     267                // Restore WordPress Uploads data
     268                remove_filter( 'upload_dir', $upload_dir_filter, 10, 0 );
     269
     270                // Finally return the uploaded file or the error
     271                return $this->attachment;
     272        }
     273
     274        /**
     275         * Validate the allowed mime types using WordPress allowed mime types
     276         *
     277         * In case of a multisite, the mime types are already restricted by
     278         * the 'upload_filetypes' setting. BuddyPress will respect this setting.
     279         * @see check_upload_mimes()
     280         *
     281         * @since BuddyPress (2.3.0)
     282         *
     283         * @uses get_allowed_mime_types()
     284         */
     285        protected function validate_mime_types() {
     286                $wp_mimes = get_allowed_mime_types();
     287                $valid_mimes = array();
     288
     289                // Set the allowed mimes for the upload
     290                foreach ( (array) $this->allowed_mime_types as $ext ) {
     291                        foreach ( $wp_mimes as $ext_pattern => $mime ) {
     292                                if ( $ext != '' && strpos( $ext_pattern, $ext ) !== false ) {
     293                                        $valid_mimes[$ext_pattern] = $mime;
     294                                }
     295                        }
     296                }
     297                return $valid_mimes;
     298        }
     299
     300        /**
     301         * Specific upload rules
     302         *
     303         * Override this function from your child class to build your specific rules
     304         * @see BP_Attachment_Avatar->validate_upload() for an example of use
     305         *
     306         * @since BuddyPress (2.3.0)
     307         *
     308         * @param  array $file the temporary file attributes (before it has been moved)
     309         * @return array the file
     310         */
     311        public function validate_upload( $file = array() ) {
     312                // Simply return the file, rules must be set in child class
     313                return $file;
     314        }
     315
     316        /**
     317         * Default filter to save the attachments
     318         *
     319         * @since BuddyPress (2.3.0)
     320         *
     321         * @uses   apply_filters() call 'bp_attachment_upload_dir' to eventually override the upload location
     322         *                         regarding to context
     323         * @return array the upload directory data
     324         */
     325        public function upload_dir_filter() {
     326
     327                /**
     328                 * Filters the component's upload directory.
     329                 *
     330                 * @since BuddyPress (2.3.0)
     331                 *
     332                 * @param array $value Array containing the path, URL, and other helpful settings.
     333                 */
     334                return apply_filters( 'bp_attachment_upload_dir', array(
     335                        'path'    => $this->upload_path,
     336                        'url'     => $this->url,
     337                        'subdir'  => false,
     338                        'basedir' => $this->upload_path,
     339                        'baseurl' => $this->url,
     340                        'error'   => false
     341                ) );
     342        }
     343
     344        /**
     345         * Create the custom base directory for the component uploads
     346         *
     347         * Override this function in your child class to run specific actions
     348         * (eg: add an .htaccess file)
     349         *
     350         * @since BuddyPress (2.3.0)
     351         *
     352         * @uses   wp_mkdir_p()
     353         */
     354        public function create_dir() {
     355                // Bail if no specific base dir is set
     356                if ( empty( $this->base_dir ) ) {
     357                        return false;
     358                }
     359
     360                // Check if upload path already exists
     361                if ( ! file_exists( $this->upload_path ) ) {
     362
     363                        // If path does not exist, attempt to create it
     364                        if ( ! wp_mkdir_p( $this->upload_path ) ) {
     365                                return false;
     366                        }
     367                }
     368
     369                // Directory exists
     370                return true;
     371        }
     372}
  • 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;