Ticket #6278: 6278.07.patch
File 6278.07.patch, 52.3 KB (added by , 10 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..44fe3c3 100644
function bp_core_delete_existing_avatar( $args = '' ) { 564 564 * @see bp_core_check_avatar_upload() 565 565 * @see bp_core_check_avatar_type() 566 566 * 567 * @param array $fileThe appropriate entry the from $_FILES superglobal.567 * @param array $file The appropriate entry the from $_FILES superglobal. 568 568 * @param string $upload_dir_filter A filter to be applied to 'upload_dir'. 569 * 569 570 * @return bool True on success, false on failure. 570 571 */ 571 572 function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { … … function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 574 575 * You may want to hook into this filter if you want to override this function. 575 576 * Make sure you return false. 576 577 */ 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 ) ) { 578 579 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 580 } 595 581 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(); 600 585 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 ); 610 589 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'] ) ) { 619 592 bp_core_add_message( sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->original['error'] ), 'error' ); 620 593 return false; 621 594 } 622 595 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(); 663 599 664 600 // We only want to handle one image after resize. 665 601 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'] ); 667 604 } 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'] ); 669 607 @unlink( $bp->avatar_admin->original['file'] ); 670 608 } 671 609 … … function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 675 613 return false; 676 614 } 677 615 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' ); 685 619 } 686 620 687 621 // Set the url value for the image … … function bp_core_avatar_handle_crop( $args = '' ) { 738 672 * You may want to hook into this filter if you want to override this function. 739 673 * Make sure you return false. 740 674 */ 741 if ( ! apply_filters( 'bp_core_pre_avatar_handle_crop', true, $r ) )675 if ( ! apply_filters( 'bp_core_pre_avatar_handle_crop', true, $r ) ) { 742 676 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 677 } 759 678 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 } 783 } 784 785 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 ); 679 // Crop the file 680 $avatar_attachment = new BP_Attachment_Avatar(); 681 $cropped = $avatar_attachment->crop( $r ); 807 682 808 683 // Check for errors 809 if ( empty( $ full_cropped ) || empty( $thumb_cropped ) || is_wp_error( $full_cropped ) || is_wp_error( $thumb_cropped ) )684 if ( empty( $cropped['full'] ) || empty( $cropped['thumb'] ) || is_wp_error( $cropped['full'] ) || is_wp_error( $cropped['thumb'] ) ) { 810 685 return false; 811 812 // Remove the original 813 @unlink( $original_file ); 686 } 814 687 815 688 return true; 816 689 } … … function bp_core_check_avatar_type($file) { 926 799 /** 927 800 * Fetch data from the BP root blog's upload directory. 928 801 * 929 * Handy for multisite instances because all uploads are made on the BP root930 * 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 *935 802 * @since BuddyPress (1.8.0) 936 803 * 937 * @uses wp_upload_dir()938 *939 804 * @param string $type The variable we want to return from the $bp->avatars 940 805 * object. Only 'upload_path' and 'url' are supported. Default: 'upload_path'. 941 806 * @return string The avatar upload directory path. … … function bp_core_get_upload_dir( $type = 'upload_path' ) { 977 842 978 843 // No cache, so query for it 979 844 } else { 980 // We need to switch to the root blog on multisite installs981 if ( is_multisite() ) {982 switch_to_blog( bp_get_root_blog_id() );983 }984 845 985 846 // Get upload directory information from current site 986 $upload_dir = wp_upload_dir(); 987 988 // Will bail if not switched 989 restore_current_blog(); 847 $upload_dir = bp_upload_dir(); 990 848 991 849 // Stash upload directory data for later use 992 850 $bp->avatar->upload_dir = $upload_dir; … … function bp_core_get_upload_dir( $type = 'upload_path' ) { 1018 876 /** 1019 877 * Get the absolute upload path for the WP installation. 1020 878 * 1021 * @uses wp_upload_dirTo get upload directory info879 * @uses bp_core_get_upload_dir() To get upload directory info 1022 880 * 1023 881 * @return string Absolute path to WP upload directory. 1024 882 */ … … function bp_core_avatar_upload_path() { 1029 887 /** 1030 888 * Get the raw base URL for root site upload location. 1031 889 * 1032 * @uses wp_upload_dirTo get upload directory info.890 * @uses bp_core_get_upload_dir() To get upload directory info. 1033 891 * 1034 892 * @return string Full URL to current upload location. 1035 893 */ -
src/bp-core/bp-core-classes.php
diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php index 70d9084..41be065 100644
require dirname( __FILE__ ) . '/classes/class-bp-suggestions.php'; 21 21 require dirname( __FILE__ ) . '/classes/class-bp-members-suggestions.php'; 22 22 require dirname( __FILE__ ) . '/classes/class-bp-recursive-query.php'; 23 23 require dirname( __FILE__ ) . '/classes/class-bp-media-extractor.php'; 24 require dirname( __FILE__ ) . '/classes/class-bp-attachment.php'; 25 require 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 f308211..2c246ef 100644
function bp_core_get_suggestions( $args ) { 2147 2147 2148 2148 return apply_filters( 'bp_core_get_suggestions', $retval, $args ); 2149 2149 } 2150 2151 /** 2152 * Set data from the BP root blog's upload directory. 2153 * 2154 * Handy for multisite instances because all uploads are made on the BP root 2155 * blog and we need to query the BP root blog for the upload directory data. 2156 * 2157 * This function ensures that we only need to use {@link switch_to_blog()} 2158 * once to get what we need. 2159 * 2160 * @since BuddyPress (2.3.0) 2161 * 2162 * @uses is_multisite() 2163 * @uses bp_is_root_blog() 2164 * @uses switch_to_blog() 2165 * @uses wp_upload_dir() 2166 * @uses restore_current_blog() 2167 */ 2168 function bp_upload_dir() { 2169 $bp = buddypress(); 2170 2171 if ( empty( $bp->upload_dir ) ) { 2172 $need_switch = (bool) ( is_multisite() && ! bp_is_root_blog() ); 2173 2174 // Maybe juggle to root blog 2175 if ( true === $need_switch ) { 2176 switch_to_blog( bp_get_root_blog_id() ); 2177 } 2178 2179 // Get the upload directory (maybe for root blog) 2180 $wp_upload_dir = wp_upload_dir(); 2181 2182 // Maybe juggle back to current blog 2183 if ( true === $need_switch ) { 2184 restore_current_blog(); 2185 } 2186 2187 // Bail if an error occurred 2188 if ( ! empty( $wp_upload_dir['error'] ) ) { 2189 return false; 2190 } 2191 2192 $bp->upload_dir = $wp_upload_dir; 2193 } 2194 2195 return $bp->upload_dir; 2196 } -
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..dcc63e1 100644
1 <?php 2 3 /** 4 * Core avatar attachment class 5 * 6 * @package BuddyPress 7 * @subpackage Core 8 */ 9 10 // Exit if accessed directly 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * BP Attachment class to manage your avatar upload needs 15 * 16 * @since BuddyPress (2.3.0) 17 */ 18 class 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 bp_core_avatar_original_max_filesize() 27 * @uses BP_Attachment::__construct() 28 */ 29 public function __construct() { 30 parent::__construct( array( 31 'action' => 'bp_avatar_upload', 32 'file_input' => 'file', 33 'original_max_filesize' => bp_core_avatar_original_max_filesize(), 34 35 // Specific errors for avatars 36 'upload_error_strings' => array( 37 9 => sprintf( __( 'That photo is too big. Please upload one smaller than %s', 'buddypress' ), size_format( bp_core_avatar_original_max_filesize() ) ), 38 10 => __( 'Please upload only JPG, GIF or PNG photos.', 'buddypress' ), 39 ), 40 ) ); 41 } 42 43 /** 44 * Set Upload Dir data for avatars 45 * 46 * @since BuddyPress (2.3.0) 47 * 48 * @uses bp_core_avatar_upload_path() 49 * @uses bp_core_avatar_url() 50 * @uses bp_upload_dir() 51 */ 52 public function set_upload_dir() { 53 if ( bp_core_avatar_upload_path() && bp_core_avatar_url() ) { 54 $this->upload_path = bp_core_avatar_upload_path(); 55 $this->url = bp_core_avatar_url(); 56 $this->upload_dir = bp_upload_dir(); 57 } else { 58 parent::set_upload_dir(); 59 } 60 } 61 62 /** 63 * Avatar specific rules 64 * 65 * Adds an error if the avatar size or type don't match BuddyPress needs 66 * The error code is the index of $upload_error_strings 67 * 68 * @since BuddyPress (2.3.0) 69 * 70 * @param array $file the temporary file attributes (before it has been moved) 71 * @uses bp_core_check_avatar_size() 72 * @uses bp_core_check_avatar_type() 73 * @return array the file with extra errors if needed 74 */ 75 public function validate_upload( $file = array() ) { 76 // Bail if already an error 77 if ( ! empty( $file['error'] ) ) { 78 return $file; 79 } 80 81 // File size is too big 82 if ( ! bp_core_check_avatar_size( array( 'file' => $file ) ) ) { 83 $file['error'] = 9; 84 85 // File is of invalid type 86 } else if ( ! bp_core_check_avatar_type( array( 'file' => $file ) ) ) { 87 $file['error'] = 10; 88 } 89 90 // Return with error code attached 91 return $file; 92 } 93 94 /** 95 * Maybe shrink the attachment to fit maximum allowed width 96 * 97 * @since BuddyPress (2.3.0) 98 * 99 * @param string $file the absolute path to the file 100 * @uses bp_core_avatar_original_max_width() 101 * @uses wp_get_image_editor() 102 * @return mixed 103 */ 104 public static function shrink( $file = '' ) { 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 string $file the absolute path to the file 147 * @uses bp_core_avatar_full_width() 148 * @uses bp_core_avatar_full_height() 149 * @return boolean 150 */ 151 public static function is_too_small( $file = '' ) { 152 $uploaded_image = @getimagesize( $file ); 153 $full_width = bp_core_avatar_full_width(); 154 $full_height = bp_core_avatar_full_height(); 155 156 if ( isset( $uploaded_image[0] ) && $uploaded_image[0] < $full_width || $uploaded_image[1] < $full_height ) { 157 return true; 158 } 159 160 return false; 161 } 162 163 /** 164 * Crop the avatar 165 * 166 * @since BuddyPress (2.3.0) 167 * 168 * @see BP_Attachment::crop for the list of parameters 169 * @param array $args 170 * @return array the cropped avatars (full and thumb) 171 */ 172 public function crop( $args = array() ) { 173 // Bail if the original file is missing 174 if ( empty( $args['original_file'] ) ) { 175 return false; 176 } 177 178 /** 179 * Original file is a relative path to the image 180 * eg: /avatars/1/avatar.jpg 181 */ 182 $relative_path = $args['original_file']; 183 $absolute_path = $this->upload_path . $relative_path; 184 185 // Bail if the avatar is not available 186 if ( ! file_exists( $absolute_path ) ) { 187 return false; 188 } 189 190 if ( empty( $args['item_id'] ) ) { 191 $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', dirname( $absolute_path ), $args['item_id'], $args['object'], $args['avatar_dir'] ); 192 } else { 193 $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'] ); 194 } 195 196 // Bail if the avatar folder is missing for this item_id 197 if ( ! file_exists( $avatar_folder_dir ) ) { 198 return false; 199 } 200 201 // Delete the existing avatar files for the object 202 $existing_avatar = bp_core_fetch_avatar( array( 203 'object' => $args['object'], 204 'item_id' => $args['item_id'], 205 'html' => false, 206 ) ); 207 208 /** 209 * Check that the new avatar doesn't have the same name as the 210 * old one before deleting 211 */ 212 if ( ! empty( $existing_avatar ) && $existing_avatar !== $this->url . $relative_path ) { 213 bp_core_delete_existing_avatar( array( 'object' => $args['object'], 'item_id' => $args['item_id'], 'avatar_path' => $avatar_folder_dir ) ); 214 } 215 216 // Make sure we at least have minimal data for cropping 217 if ( empty( $args['crop_w'] ) ) { 218 $args['crop_w'] = bp_core_avatar_full_width(); 219 } 220 221 if ( empty( $args['crop_h'] ) ) { 222 $args['crop_h'] = bp_core_avatar_full_height(); 223 } 224 225 // Get the file extension 226 $data = @getimagesize( $absolute_path ); 227 $ext = $data['mime'] == 'image/png' ? 'png' : 'jpg'; 228 229 $args['original_file'] = $absolute_path; 230 $args['src_abs'] = false; 231 $avatar_types = array( 'full' => '', 'thumb' => '' ); 232 233 foreach ( $avatar_types as $key_type => $type ) { 234 $args['dst_w'] = bp_core_avatar_dimension( $key_type, 'width' ); 235 $args['dst_h'] = bp_core_avatar_dimension( $key_type, 'height' ); 236 $args['dst_file'] = $avatar_folder_dir . '/' . wp_hash( $absolute_path . time() ) . '-bp' . $key_type . '.' . $ext; 237 238 $avatar_types[ $key_type ] = parent::crop( $args ); 239 } 240 241 // Remove the original 242 @unlink( $absolute_path ); 243 244 // Return the full and thumb cropped avatars 245 return $avatar_types; 246 } 247 } -
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..05bd841 100644
1 <?php 2 3 /** 4 * Core attachment class. 5 * 6 * @package BuddyPress 7 * @subpackage Core 8 */ 9 10 // Exit if accessed directly 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * BP Attachment class to manage your component's uploads 15 * 16 * @since BuddyPress (2.3.0) 17 */ 18 class 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 = 0; 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 = ''; 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. Defaults to php.ini settings. 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()} (required) 91 * @type string $file_input The name attribute used in the file input. (required) 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 // Upload action and the file input name are required parameters 102 if ( empty( $args['action'] ) || empty( $args['file_input'] ) ) { 103 return false; 104 } 105 106 // Sanitize the action ID and the file input name 107 $this->action = sanitize_key( $args['action'] ); 108 $this->file_input = sanitize_key( $args['file_input'] ); 109 110 /** 111 * Max file size defaults to php ini settings or, in the case of 112 * a multisite config, the root site fileupload_maxk option 113 */ 114 $this->original_max_filesize = (int) wp_max_upload_size(); 115 116 $params = bp_parse_args( $args, get_class_vars( __CLASS__ ), $this->action . '_upload_params' ); 117 118 foreach ( $params as $key => $param ) { 119 if ( 'upload_error_strings' === $key ) { 120 $this->{$key} = $this->set_upload_error_strings( $param ); 121 } else { 122 $this->{$key} = $param; 123 } 124 } 125 126 // Set the path/url and base dir for uploads 127 $this->set_upload_dir(); 128 } 129 130 /** 131 * Set upload path and url for the component. 132 * 133 * @since BuddyPress (2.3.0) 134 * 135 * @uses bp_upload_dir() 136 */ 137 public function set_upload_dir() { 138 // Set the directory, path, & url variables 139 $this->upload_dir = bp_upload_dir(); 140 141 if ( empty( $this->upload_dir ) ) { 142 return false; 143 } 144 145 $this->upload_path = $this->upload_dir['basedir']; 146 $this->url = $this->upload_dir['baseurl']; 147 148 // Ensure URL is https if SSL is set/forced 149 if ( is_ssl() ) { 150 $this->url = str_replace( 'http://', 'https://', $this->url ); 151 } 152 153 /** 154 * Custom base dir. 155 * 156 * If the component set this property, set the specific path, url and create the dir 157 */ 158 if ( ! empty( $this->base_dir ) ) { 159 $this->upload_path = trailingslashit( $this->upload_path ) . $this->base_dir; 160 $this->url = trailingslashit( $this->url ) . $this->base_dir; 161 162 // Finally create the base dir 163 $this->create_dir(); 164 } 165 } 166 167 /** 168 * Set Upload error messages 169 * 170 * Used into the $overrides argument of BP_Attachment->upload() 171 * 172 * @since BuddyPress (2.3.0) 173 * 174 * @param array $param a list of error messages to add to BuddyPress core ones 175 * @return array the list of upload errors 176 */ 177 public function set_upload_error_strings( $param = array() ) { 178 /** 179 * Index of the array is the error code 180 * Custom errors will start at 9 code 181 */ 182 $upload_errors = array( 183 0 => __( 'The file was uploaded successfully', 'buddypress' ), 184 1 => __( 'The uploaded file exceeds the maximum allowed file size for this site', 'buddypress' ), 185 2 => sprintf( __( 'The uploaded file exceeds the maximum allowed file size of: %s', 'buddypress' ), size_format( $this->original_max_filesize ) ), 186 3 => __( 'The uploaded file was only partially uploaded.', 'buddypress' ), 187 4 => __( 'No file was uploaded.', 'buddypress' ), 188 5 => '', 189 6 => __( 'Missing a temporary folder.', 'buddypress' ), 190 7 => __( 'Failed to write file to disk.', 'buddypress' ), 191 8 => __( 'File upload stopped by extension.', 'buddypress' ), 192 ); 193 194 if ( ! array_intersect_key( $upload_errors, (array) $param ) ) { 195 foreach ( $param as $key_error => $error_message ) { 196 $upload_errors[ $key_error ] = $error_message; 197 } 198 } 199 200 return $upload_errors; 201 } 202 203 /** 204 * Include the WordPress core needed files 205 * 206 * @since BuddyPress (2.3.0) 207 */ 208 public function includes() { 209 foreach ( array_unique( $this->required_wp_files ) as $wp_file ) { 210 if ( ! file_exists( ABSPATH . "/wp-admin/includes/{$wp_file}.php" ) ) { 211 continue; 212 } 213 214 require_once( ABSPATH . "/wp-admin/includes/{$wp_file}.php" ); 215 } 216 } 217 218 /** 219 * Upload the attachment 220 * 221 * @since BuddyPress (2.3.0) 222 * 223 * @param array $file The appropriate entry the from $_FILES superglobal. 224 * @param string $upload_dir_filter A specific filter to be applied to 'upload_dir' (optional). 225 * @uses wp_handle_upload() 226 * @uses apply_filters() Call 'bp_attachment_upload_overrides' to include specific upload overrides 227 * 228 * @return array On success, returns an associative array of file attributes. 229 * On failure, returns an array containing the error message 230 * (eg: array( 'error' => $message ) ) 231 */ 232 public function upload( $file, $upload_dir_filter = '' ) { 233 /** 234 * Upload action and the file input name are required parameters 235 * @see BP_Attachment:__construct() 236 */ 237 if ( empty( $this->action ) || empty( $this->file_input ) ) { 238 return false; 239 } 240 241 /** 242 * Add custom rules before enabling the file upload 243 */ 244 add_filter( "{$this->action}_prefilter", array( $this, 'validate_upload' ), 10, 1 ); 245 246 // Set Default overrides 247 $overrides = array( 248 'action' => $this->action, 249 'upload_error_strings' => $this->upload_error_strings, 250 ); 251 252 /** 253 * Add a mime override if needed 254 * Used to restrict uploads by extensions 255 */ 256 if ( ! empty( $this->allowed_mime_types ) ) { 257 $mime_types = $this->validate_mime_types(); 258 259 if ( ! empty( $mime_types ) ) { 260 $overrides['mimes'] = $mime_types; 261 } 262 } 263 264 /** 265 * If you need to add some overrides we haven't thought of 266 * 267 * @var array $overrides the wp_handle_upload overrides 268 */ 269 $overrides = apply_filters( 'bp_attachment_upload_overrides', $overrides ); 270 271 $this->includes(); 272 273 /** 274 * If the $base_dir was set when constructing the class, 275 * and no specific filter has been requested, use a default 276 * filter to create the specific $base dir 277 * @see BP_Attachment->upload_dir_filter() 278 */ 279 if ( empty( $upload_dir_filter ) && ! empty( $this->base_dir ) ) { 280 $upload_dir_filter = array( $this, 'upload_dir_filter' ); 281 } 282 283 // Make sure the file will be uploaded in the attachment directory 284 add_filter( 'upload_dir', $upload_dir_filter, 10, 0 ); 285 286 // Upload the attachment 287 $this->attachment = wp_handle_upload( $file[ $this->file_input ], $overrides ); 288 289 // Restore WordPress Uploads data 290 remove_filter( 'upload_dir', $upload_dir_filter, 10, 0 ); 291 292 // Finally return the uploaded file or the error 293 return $this->attachment; 294 } 295 296 /** 297 * Validate the allowed mime types using WordPress allowed mime types 298 * 299 * In case of a multisite, the mime types are already restricted by 300 * the 'upload_filetypes' setting. BuddyPress will respect this setting. 301 * @see check_upload_mimes() 302 * 303 * @since BuddyPress (2.3.0) 304 * 305 * @uses get_allowed_mime_types() 306 */ 307 protected function validate_mime_types() { 308 $wp_mimes = get_allowed_mime_types(); 309 $valid_mimes = array(); 310 311 // Set the allowed mimes for the upload 312 foreach ( (array) $this->allowed_mime_types as $ext ) { 313 foreach ( $wp_mimes as $ext_pattern => $mime ) { 314 if ( $ext != '' && strpos( $ext_pattern, $ext ) !== false ) { 315 $valid_mimes[$ext_pattern] = $mime; 316 } 317 } 318 } 319 return $valid_mimes; 320 } 321 322 /** 323 * Specific upload rules 324 * 325 * Override this function from your child class to build your specific rules 326 * By default, if an original_max_filesize is provided, a check will be done 327 * on the file size. 328 * 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 // Bail if already an error 338 if ( ! empty( $file['error'] ) ) { 339 return $file; 340 } 341 342 if ( ! empty( $this->original_max_filesize ) && $file['size'] > $this->original_max_filesize ) { 343 $file['error'] = 2; 344 } 345 346 // Return the file 347 return $file; 348 } 349 350 /** 351 * Default filter to save the attachments 352 * 353 * @since BuddyPress (2.3.0) 354 * 355 * @uses apply_filters() call 'bp_attachment_upload_dir' to eventually override the upload location 356 * regarding to context 357 * @return array the upload directory data 358 */ 359 public function upload_dir_filter() { 360 /** 361 * Filters the component's upload directory. 362 * 363 * @since BuddyPress (2.3.0) 364 * 365 * @param array $value Array containing the path, URL, and other helpful settings. 366 */ 367 return apply_filters( 'bp_attachment_upload_dir', array( 368 'path' => $this->upload_path, 369 'url' => $this->url, 370 'subdir' => false, 371 'basedir' => $this->upload_path, 372 'baseurl' => $this->url, 373 'error' => false 374 ) ); 375 } 376 377 /** 378 * Create the custom base directory for the component uploads 379 * 380 * Override this function in your child class to run specific actions 381 * (eg: add an .htaccess file) 382 * 383 * @since BuddyPress (2.3.0) 384 * 385 * @uses wp_mkdir_p() 386 */ 387 public function create_dir() { 388 // Bail if no specific base dir is set 389 if ( empty( $this->base_dir ) ) { 390 return false; 391 } 392 393 // Check if upload path already exists 394 if ( ! file_exists( $this->upload_path ) ) { 395 396 // If path does not exist, attempt to create it 397 if ( ! wp_mkdir_p( $this->upload_path ) ) { 398 return false; 399 } 400 } 401 402 // Directory exists 403 return true; 404 } 405 406 /** 407 * Crop an image file 408 * 409 * @since BuddyPress (2.3.0) 410 * 411 * @param array $args { 412 * @type string $original_file The source file (absolute path) for the Attachment. 413 * @type int $crop_x The start x position to crop from. 414 * @type int $crop_y The start y position to crop from. 415 * @type int $crop_w The width to crop. 416 * @type int $crop_h The height to crop. 417 * @type int $dst_w The destination width. 418 * @type int $dst_h The destination height. 419 * @type int $src_abs Optional. If the source crop points are absolute. 420 * @type string $dst_file Optional. The destination file to write to. 421 * } 422 * @uses wp_crop_image() 423 * @return string|WP_Error New filepath on success, WP_Error on failure. 424 */ 425 public function crop( $args = array() ) { 426 $wp_error = new WP_Error(); 427 428 $r = wp_parse_args( $args, array( 429 'original_file' => '', 430 'crop_x' => 0, 431 'crop_y' => 0, 432 'crop_w' => 0, 433 'crop_h' => 0, 434 'dst_w' => 0, 435 'dst_h' => 0, 436 'src_abs' => false, 437 'dst_file' => false, 438 ) ); 439 440 if ( empty( $r['original_file'] ) || ! file_exists( $r['original_file'] ) ) { 441 $wp_error->add( 'crop_error', __( 'Cropping the file failed: missing source file.', 'buddypress' ) ); 442 return $wp_error; 443 } 444 445 // Check image file pathes 446 $path_error = __( 'Cropping the file failed: the file path is not allowed.', 'buddypress' ); 447 448 // Make sure it's coming from an uploaded file 449 if ( false === strpos( $r['original_file'], $this->upload_path ) ) { 450 $wp_error->add( 'crop_error', $path_error ); 451 return $wp_error; 452 } 453 454 /** 455 * If no destination file is provided, WordPress will use a default name 456 * and will write the file in the source file's folder. 457 * If a destination file is provided, we need to make sure it's going into uploads 458 */ 459 if ( ! empty( $r['dst_file'] ) && false === strpos( $r['dst_file'], $this->upload_path ) ) { 460 $wp_error->add( 'crop_error', $path_error ); 461 return $wp_error; 462 } 463 464 // Check image file types 465 $check_types = array( 'src_file' => array( 'file' => $r['original_file'], 'error' => _x( 'source file', 'Attachment source file', 'buddypress' ) ) ); 466 if ( ! empty( $r['dst_file'] ) ) { 467 $check_types['dst_file'] = array( 'file' => $r['dst_file'], 'error' => _x( 'destination file', 'Attachment destination file', 'buddypress' ) ); 468 } 469 470 /** 471 * WordPress image supported types 472 * @see wp_attachment_is() 473 */ 474 $supported_image_types = array( 475 'jpg' => 1, 476 'jpeg' => 1, 477 'jpe' => 1, 478 'gif' => 1, 479 'png' => 1, 480 ); 481 482 foreach ( $check_types as $file ) { 483 $is_image = wp_check_filetype( $file['file'] ); 484 $ext = $is_image['ext']; 485 486 if ( empty( $ext ) || empty( $supported_image_types[ $ext ] ) ) { 487 $wp_error->add( 'crop_error', sprintf( __( 'Cropping the file failed: %s is not a supported image file.', 'buddypress' ), $file['error'] ) ); 488 return $wp_error; 489 } 490 } 491 492 // Add the image.php to the required WordPress files, if it's not already the case 493 $required_files = array_flip( $this->required_wp_files ); 494 if ( ! isset( $required_files['image'] ) ) { 495 $this->required_wp_files[] = 'image'; 496 } 497 498 // Load the files 499 $this->includes(); 500 501 // Finally crop the image 502 return wp_crop_image( $r['original_file'], (int) $r['crop_x'], (int) $r['crop_y'], (int) $r['crop_w'], (int) $r['crop_h'], (int) $r['dst_w'], (int) $r['dst_h'], $r['src_abs'], $r['dst_file'] ); 503 } 504 } -
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 ) { 817 817 $group_id = bp_get_current_group_id(); 818 818 } 819 819 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; 827 824 $newburl = $newurl; 828 $newsubdir = '/ group-avatars/' . $group_id;825 $newsubdir = '/' . $directory . '/' . $group_id; 829 826 830 827 /** 831 828 * Filters the avatar upload directory path for a given group. … … function groups_avatar_upload_dir( $group_id = 0 ) { 834 831 * 835 832 * @param array $value Array of parts related to the groups avatar upload directory. 836 833 */ 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 ) ); 838 842 } 839 843 840 844 /** 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 1a46340..01e9772 100644
function bp_core_signup_avatar_upload_dir() { 2159 2159 return false; 2160 2160 } 2161 2161 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; 2172 2168 2173 2169 /** 2174 2170 * Filters the avatar storage directory for use during registration. … … function bp_core_signup_avatar_upload_dir() { 2183 2179 'subdir' => $newsubdir, 2184 2180 'basedir' => $newbdir, 2185 2181 'baseurl' => $newburl, 2186 'error' => false2182 'error' => false 2187 2183 ) ); 2188 2184 } 2189 2185 -
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 ) { 680 680 $directory = 'avatars'; 681 681 } 682 682 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; 690 685 $newurl = bp_core_avatar_url() . '/' . $directory. '/' . $user_id; 691 686 $newburl = $newurl; 692 687 $newsubdir = '/' . $directory. '/' . $user_id; -
tests/phpunit/assets/attachment-extensions.php
diff --git tests/phpunit/assets/attachment-extensions.php tests/phpunit/assets/attachment-extensions.php index e69de29..117b456 100644
1 <?php 2 /** 3 * The following implementations of BP_Attachment act as dummy plugins 4 * for our unit tests 5 */ 6 class BP_Attachment_Extend extends BP_Attachment { 7 public function __construct( $args = array() ) { 8 return parent::__construct( $args ); 9 } 10 } -
tests/phpunit/testcases/core/class-bp-attachment-avatar.php
diff --git tests/phpunit/testcases/core/class-bp-attachment-avatar.php tests/phpunit/testcases/core/class-bp-attachment-avatar.php index e69de29..d719dd3 100644
1 <?php 2 3 /** 4 * @group core 5 * @group avatars 6 * @group bp_attachments 7 * @group BP_Attachement_Avatar 8 */ 9 class BP_Tests_BP_Attachement_Avatar_TestCases extends BP_UnitTestCase { 10 protected $displayed_user; 11 12 public function setUp() { 13 parent::setUp(); 14 $bp = buddypress(); 15 $this->displayed_user = $bp->displayed_user; 16 $bp->displayed_user = new stdClass; 17 } 18 19 public function tearDown() { 20 parent::tearDown(); 21 buddypress()->displayed_user = $this->displayed_user; 22 } 23 24 public function max_filesize() { 25 return 1000; 26 } 27 28 private function clean_avatars( $type = 'user' ) { 29 if ( 'user' === $type ) { 30 $avatar_dir = 'avatars'; 31 } elseif ( 'group' === $type ) { 32 $avatar_dir = 'group-avatars'; 33 } 34 35 $this->rrmdir( bp_core_avatar_upload_path() . '/' . $avatar_dir ); 36 } 37 38 private function rrmdir( $dir ) { 39 $d = glob( $dir . '/*' ); 40 41 if ( empty( $d ) ) { 42 return; 43 } 44 45 foreach ( $d as $file ) { 46 if ( is_dir( $file ) ) { 47 $this->rrmdir( $file ); 48 } else { 49 @unlink( $file ); 50 } 51 } 52 53 @rmdir( $dir ); 54 } 55 56 /** 57 * @group upload 58 */ 59 public function test_upload_user_avatar_no_error() { 60 $reset_files = $_FILES; 61 $reset_post = $_POST; 62 63 $u1 = $this->factory->user->create(); 64 buddypress()->displayed_user->id = $u1; 65 66 $avatar = BP_TESTS_DIR . 'assets/files/disc.png'; 67 68 $tmp_name = wp_tempnam( $avatar ); 69 70 copy( $avatar, $tmp_name ); 71 72 // Upload the file 73 $avatar_attachment = new BP_Attachment_Avatar(); 74 $_POST['action'] = $avatar_attachment->action; 75 $_FILES[ $avatar_attachment->file_input ] = array( 76 'tmp_name' => $tmp_name, 77 'name' => 'disc.png', 78 'type' => 'image/png', 79 'error' => 0, 80 'size' => filesize( $avatar ) 81 ); 82 83 $user_avatar = $avatar_attachment->upload( $_FILES, 'xprofile_avatar_upload_dir' ); 84 85 $this->assertTrue( empty( $user_avatar['error'] ) ); 86 87 // clean up! 88 $this->clean_avatars(); 89 $_FILES = $reset_files; 90 $_POST = $reset_post; 91 } 92 93 /** 94 * @group upload 95 */ 96 public function test_upload_group_avatar_no_error() { 97 $bp = buddypress(); 98 $reset_files = $_FILES; 99 $reset_post = $_POST; 100 $reset_current_group = $bp->groups->current_group; 101 102 $g = $this->factory->group->create(); 103 104 $bp->groups->current_group = groups_get_group( array( 105 'group_id' => $g, 106 'populate_extras' => true, 107 ) ); 108 109 $avatar = BP_TESTS_DIR . 'assets/files/disc.png'; 110 111 $tmp_name = wp_tempnam( $avatar ); 112 113 copy( $avatar, $tmp_name ); 114 115 // Upload the file 116 $avatar_attachment = new BP_Attachment_Avatar(); 117 $_POST['action'] = $avatar_attachment->action; 118 $_FILES[ $avatar_attachment->file_input ] = array( 119 'tmp_name' => $tmp_name, 120 'name' => 'disc.png', 121 'type' => 'image/png', 122 'error' => 0, 123 'size' => filesize( $avatar ) 124 ); 125 126 $group_avatar = $avatar_attachment->upload( $_FILES, 'groups_avatar_upload_dir' ); 127 128 $this->assertTrue( empty( $group_avatar['error'] ) ); 129 130 // clean up! 131 $this->clean_avatars( 'group' ); 132 $bp->groups->current_group = $reset_current_group; 133 $_FILES = $reset_files; 134 $_POST = $reset_post; 135 } 136 137 /** 138 * @group upload 139 */ 140 public function test_upload_user_avatar_file_size_error() { 141 $reset_files = $_FILES; 142 $reset_post = $_POST; 143 144 $u1 = $this->factory->user->create(); 145 buddypress()->displayed_user->id = $u1; 146 147 $avatar = BP_TESTS_DIR . 'assets/files/disc.png'; 148 149 $tmp_name = wp_tempnam( $avatar ); 150 151 copy( $avatar, $tmp_name ); 152 153 add_filter( 'bp_core_avatar_original_max_filesize', array( $this, 'max_filesize' ) ); 154 155 // Upload the file 156 $avatar_attachment = new BP_Attachment_Avatar(); 157 158 $_POST['action'] = $avatar_attachment->action; 159 $_FILES[ $avatar_attachment->file_input ] = array( 160 'tmp_name' => $tmp_name, 161 'name' => 'disc.png', 162 'type' => 'image/png', 163 'error' => 0, 164 'size' => filesize( $avatar ) 165 ); 166 167 $user_avatar = $avatar_attachment->upload( $_FILES, 'xprofile_avatar_upload_dir' ); 168 169 remove_filter( 'bp_core_avatar_original_max_filesize', array( $this, 'max_filesize' ) ); 170 171 $this->assertFalse( empty( $user_avatar['error'] ) ); 172 173 // clean up! 174 $_FILES = $reset_files; 175 $_POST = $reset_post; 176 } 177 178 /** 179 * @group upload 180 */ 181 public function test_upload_user_avatar_file_type_error() { 182 $reset_files = $_FILES; 183 $reset_post = $_POST; 184 185 $u1 = $this->factory->user->create(); 186 buddypress()->displayed_user->id = $u1; 187 188 $avatar = BP_TESTS_DIR . 'assets/files/buddypress_logo.pdf'; 189 190 $tmp_name = wp_tempnam( $avatar ); 191 192 copy( $avatar, $tmp_name ); 193 194 // Upload the file 195 $avatar_attachment = new BP_Attachment_Avatar(); 196 $_POST['action'] = $avatar_attachment->action; 197 $_FILES[ $avatar_attachment->file_input ] = array( 198 'tmp_name' => $tmp_name, 199 'name' => 'buddypress_logo.pdf', 200 'type' => 'application/pdf', 201 'error' => 0, 202 'size' => filesize( $avatar ) 203 ); 204 205 $user_avatar = $avatar_attachment->upload( $_FILES, 'xprofile_avatar_upload_dir' ); 206 207 $this->assertFalse( empty( $user_avatar['error'] ) ); 208 209 // clean up! 210 $_FILES = $reset_files; 211 $_POST = $reset_post; 212 } 213 214 /** 215 * @group crop 216 */ 217 public function test_crop_avatar() { 218 $avatar = BP_TESTS_DIR . 'assets/files/buddypress-book.jpg'; 219 $pdf = BP_TESTS_DIR . 'assets/files/buddypress_logo.pdf'; 220 221 $u1 = $this->factory->user->create(); 222 223 $upload_dir = xprofile_avatar_upload_dir( 'avatars', $u1 ); 224 225 wp_mkdir_p( $upload_dir['path'] ); 226 227 copy( $avatar, $upload_dir['path'] . '/buddypress-book.jpg' ); 228 copy( $pdf, $upload_dir['path'] . '/buddypress_logo.pdf' ); 229 230 $crop_args = array( 231 'object' => 'user', 232 'avatar_dir' => 'avatars', 233 'item_id' => $u1, 234 'original_file' => '/avatars/' . $u1 . '/buddypress-book.jpg', 235 ); 236 237 $avatar_attachment = new BP_Attachment_Avatar(); 238 $cropped = $avatar_attachment->crop( $crop_args ); 239 240 $this->assertTrue( ! empty( $cropped['full'] ) && ! is_wp_error( $cropped['full'] ) ); 241 242 $crop_args['original_file'] = '/avatars/' . $u1 . '/buddypress_logo.pdf'; 243 244 $cropped = $avatar_attachment->crop( $crop_args ); 245 $this->assertTrue( is_wp_error( $cropped['full'] ) ); 246 247 // Clean up 248 $this->clean_avatars(); 249 } 250 } -
tests/phpunit/testcases/core/class-bp-attachment.php
diff --git tests/phpunit/testcases/core/class-bp-attachment.php tests/phpunit/testcases/core/class-bp-attachment.php index e69de29..2b97b2f 100644
1 <?php 2 3 include_once BP_TESTS_DIR . '/assets/attachment-extensions.php'; 4 5 /** 6 * @group bp_attachments 7 * @group BP_Attachement 8 */ 9 class BP_Tests_BP_Attachment_TestCases extends BP_UnitTestCase { 10 11 private function clean_files( $basedir = 'attachment_base_dir' ) { 12 $upload_dir = bp_upload_dir(); 13 14 $this->rrmdir( $upload_dir['basedir'] . '/' . $basedir ); 15 } 16 17 private function rrmdir( $dir ) { 18 $d = glob( $dir . '/*' ); 19 20 if ( empty( $d ) ) { 21 return; 22 } 23 24 foreach ( $d as $file ) { 25 if ( is_dir( $file ) ) { 26 $this->rrmdir( $file ); 27 } else { 28 @unlink( $file ); 29 } 30 } 31 32 @rmdir( $dir ); 33 } 34 35 public function test_construct_missing_required_parameter() { 36 $reset_files = $_FILES; 37 $reset_post = $_POST; 38 39 $_FILES['file'] = array( 40 'name' => 'disc.png', 41 'type' => 'image/png', 42 'error' => 0, 43 'size' => 10000 44 ); 45 46 $attachment_class = new BP_Attachment_Extend(); 47 $upload = $attachment_class->upload( $_FILES ); 48 49 $this->assertTrue( empty( $upload ) ); 50 51 $_FILES = $reset_files; 52 $_POST = $reset_post; 53 } 54 55 public function test_set_upload_dir() { 56 $upload_dir = bp_upload_dir(); 57 58 $attachment_class = new BP_Attachment_Extend( array( 59 'action' => 'attachment_action', 60 'file_input' => 'attachment_file_input' 61 ) ); 62 63 $this->assertSame( $attachment_class->upload_dir, bp_upload_dir() ); 64 65 $attachment_class = new BP_Attachment_Extend( array( 66 'action' => 'attachment_action', 67 'file_input' => 'attachment_file_input', 68 'base_dir' => 'attachment_base_dir', 69 ) ); 70 71 $this->assertTrue( file_exists( $upload_dir['basedir'] . '/attachment_base_dir' ) ); 72 73 // clean up 74 $this->clean_files(); 75 } 76 77 /** 78 * @group upload 79 */ 80 public function test_upload() { 81 $reset_files = $_FILES; 82 $reset_post = $_POST; 83 84 $file = BP_TESTS_DIR . 'assets/files/disc.png'; 85 86 $tmp_name = wp_tempnam( $file ); 87 88 copy( $file, $tmp_name ); 89 90 $attachment_class = new BP_Attachment_Extend( array( 91 'action' => 'attachment_action', 92 'file_input' => 'attachment_file_input', 93 'base_dir' => 'attachment_base_dir', 94 'original_max_filesize' => 10000, 95 ) ); 96 97 $_POST['action'] = $attachment_class->action; 98 $_FILES[ $attachment_class->file_input ] = array( 99 'tmp_name' => $tmp_name, 100 'name' => 'disc.png', 101 'type' => 'image/png', 102 'error' => 0, 103 'size' => filesize( $file ) 104 ); 105 106 // Error: file size 107 $upload = $attachment_class->upload( $_FILES ); 108 $this->assertFalse( empty( $upload['error'] ) ); 109 110 $attachment_class->allowed_mime_types = array( 'pdf' ); 111 $attachment_class->original_max_filesize = false; 112 113 // Error: file type 114 $upload = $attachment_class->upload( $_FILES ); 115 $this->assertFalse( empty( $upload['error'] ) ); 116 117 $attachment_class->allowed_mime_types = array(); 118 119 // Success 120 $upload = $attachment_class->upload( $_FILES ); 121 $this->assertTrue( empty( $upload['error'] ) ); 122 123 // clean up! 124 $_FILES = $reset_files; 125 $_POST = $reset_post; 126 $this->clean_files(); 127 } 128 129 /** 130 * @group crop 131 */ 132 public function test_crop_image() { 133 $image = BP_TESTS_DIR . 'assets/files/buddypress-book.jpg'; 134 135 $crop_args = array( 136 'original_file' => $image, 137 'crop_x' => 0, 138 'crop_y' => 0, 139 'crop_w' => 150, 140 'crop_h' => 150, 141 'dst_w' => 150, 142 'dst_h' => 150, 143 ); 144 145 $attachment_class = new BP_Attachment_Extend( array( 146 'action' => 'attachment_action', 147 'file_input' => 'attachment_file_input', 148 'base_dir' => 'attachment_base_dir', 149 ) ); 150 $cropped = $attachment_class->crop( $crop_args ); 151 152 // Image must come from the upload basedir 153 $this->assertTrue( is_wp_error( $cropped ) ); 154 155 $crop_args['original_file'] = $attachment_class->upload_path . '/buddypress-book.jpg'; 156 157 // Move to the base upload dir 158 copy( $image, $crop_args['original_file'] ); 159 160 // Image must stay in the upload basedir 161 $crop_args['dst_file'] = BP_TESTS_DIR . 'assets/files/error.jpg'; 162 $cropped = $attachment_class->crop( $crop_args ); 163 164 // Image must stay in the upload basedir 165 $this->assertTrue( is_wp_error( $cropped ) ); 166 167 unset( $crop_args['dst_file'] ); 168 169 $cropped = $attachment_class->crop( $crop_args ); 170 $this->assertFalse( is_wp_error( $cropped ) ); 171 172 // clean up! 173 $this->clean_files(); 174 } 175 } -
tests/phpunit/testcases/core/functions.php
diff --git tests/phpunit/testcases/core/functions.php tests/phpunit/testcases/core/functions.php index 1ab3b45..d165739 100644
class BP_Tests_Core_Functions extends BP_UnitTestCase { 572 572 date_default_timezone_set( $tz_backup ); 573 573 } 574 574 } 575 576 /** 577 * @group bp_attachments 578 * @group bp_upload_dir 579 */ 580 public function test_bp_upload_dir_ms() { 581 if ( ! is_multisite() ) { 582 return; 583 } 584 585 $expected_upload_dir = wp_upload_dir(); 586 587 $b = $this->factory->blog->create(); 588 589 switch_to_blog( $b ); 590 591 $tested_upload_dir = bp_upload_dir(); 592 593 restore_current_blog(); 594 595 $this->assertSame( $expected_upload_dir, $tested_upload_dir ); 596 } 575 597 }