Ticket #6290: 6290.11.patch
File 6290.11.patch, 91.2 KB (added by , 10 years ago) |
---|
-
src/bp-core/bp-core-attachments.php
diff --git src/bp-core/bp-core-attachments.php src/bp-core/bp-core-attachments.php index e69de29..7df95a6 100644
1 <?php 2 /** 3 * BuddyPress Attachments functions. 4 * 5 * @package BuddyPress 6 * @subpackage Attachments 7 */ 8 9 // Exit if accessed directly 10 defined( 'ABSPATH' ) || exit; 11 12 /** 13 * Get the BuddyPress Plupload settings 14 * 15 * @since BuddyPress (2.3.0) 16 * 17 * @return array list of BuddyPress Plupload settings 18 */ 19 function bp_attachments_get_plupload_default_settings() { 20 21 $max_upload_size = wp_max_upload_size(); 22 23 if ( ! $max_upload_size ) { 24 $max_upload_size = 0; 25 } 26 27 $defaults = array( 28 'runtimes' => 'html5,flash,silverlight,html4', 29 'file_data_name' => 'file', 30 'multipart_params' => array( 31 'action' => 'bp_upload_attachment', 32 '_wpnonce' => wp_create_nonce( 'bp-uploader' ), 33 ), 34 'url' => admin_url( 'admin-ajax.php', 'relative' ), 35 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ), 36 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ), 37 'filters' => array( 38 'max_file_size' => $max_upload_size . 'b', 39 ), 40 'multipart' => true, 41 'urlstream_upload' => true, 42 ); 43 44 // WordPress is not allowing multi selection for iOs 7 device.. See #29602. 45 if ( wp_is_mobile() && strpos( $_SERVER['HTTP_USER_AGENT'], 'OS 7_' ) !== false && 46 strpos( $_SERVER['HTTP_USER_AGENT'], 'like Mac OS X' ) !== false ) { 47 48 $defaults['multi_selection'] = false; 49 } 50 51 $settings = array( 52 'defaults' => $defaults, 53 'browser' => array( 54 'mobile' => wp_is_mobile(), 55 'supported' => _device_can_upload(), 56 ), 57 'limitExceeded' => is_multisite() && ! is_upload_space_available(), 58 ); 59 60 /** 61 * Filter the BuddyPress Plupload default settings. 62 * 63 * @since 2.3.0 64 * 65 * @param array $params Default Plupload parameters array. 66 */ 67 return apply_filters( 'bp_attachments_get_plupload_default_settings', $settings ); 68 } 69 70 /** 71 * Builds localization strings for the BuddyPress Uploader scripts 72 * 73 * @since BuddyPress (2.3.0) 74 * 75 * @return array Plupload default localization strings 76 */ 77 function bp_attachments_get_plupload_l10n() { 78 // Localization strings 79 return apply_filters( 'bp_attachments_get_plupload_l10n', array( 80 'queue_limit_exceeded' => __( 'You have attempted to queue too many files.', 'buddypress' ), 81 'file_exceeds_size_limit' => __( '%s exceeds the maximum upload size for this site.', 'buddypress' ), 82 'zero_byte_file' => __( 'This file is empty. Please try another.', 'buddypress' ), 83 'invalid_filetype' => __( 'This file type is not allowed. Please try another.', 'buddypress' ), 84 'not_an_image' => __( 'This file is not an image. Please try another.', 'buddypress' ), 85 'image_memory_exceeded' => __( 'Memory exceeded. Please try another smaller file.', 'buddypress' ), 86 'image_dimensions_exceeded' => __( 'This is larger than the maximum size. Please try another.', 'buddypress' ), 87 'default_error' => __( 'An error occurred. Please try again later.', 'buddypress' ), 88 'missing_upload_url' => __( 'There was a configuration error. Please contact the server administrator.', 'buddypress' ), 89 'upload_limit_exceeded' => __( 'You may only upload 1 file.', 'buddypress' ), 90 'http_error' => __( 'HTTP error.', 'buddypress' ), 91 'upload_failed' => __( 'Upload failed.', 'buddypress' ), 92 'big_upload_failed' => __( 'Please try uploading this file with the %1$sbrowser uploader%2$s.', 'buddypress' ), 93 'big_upload_queued' => __( '%s exceeds the maximum upload size for the multi-file uploader when used in your browser.', 'buddypress' ), 94 'io_error' => __( 'IO error.', 'buddypress' ), 95 'security_error' => __( 'Security error.', 'buddypress' ), 96 'file_cancelled' => __( 'File canceled.', 'buddypress' ), 97 'upload_stopped' => __( 'Upload stopped.', 'buddypress' ), 98 'dismiss' => __( 'Dismiss', 'buddypress' ), 99 'crunching' => __( 'Crunching…', 'buddypress' ), 100 'unique_file_warning' => __( 'Make sure to upload a unique file', 'buddypress' ), 101 'error_uploading' => __( '“%s” has failed to upload.', 'buddypress' ) 102 ) ); 103 } 104 105 /** 106 * Enqueues the script needed for the Uploader UI 107 * 108 * @see BP_Attachment::script_data() && BP_Attachment_Avatar::script_data() for examples showing how 109 * to set specific script data 110 * 111 * @since BuddyPress (2.3.0) 112 * 113 * @param string $class name of the class extending BP_Attachment (eg: BP_Attachment_Avatar) 114 */ 115 function bp_attachments_enqueue_scripts( $class = '' ) { 116 // Enqueue me just once per page, please. 117 if ( did_action( 'bp_attachments_enqueue_scripts' ) ) { 118 return; 119 } 120 121 if ( ! $class || ! class_exists( $class ) ) { 122 return new WP_Error( 'missing_parameter' ); 123 } 124 125 // Get an instance of the class and get the script data 126 $attachment = new $class; 127 $script_data = $attachment->script_data(); 128 129 $args = bp_parse_args( $script_data, array( 130 'action' => '', 131 'file_data_name' => '', 132 'max_file_size' => 0, 133 'browse_button' => 'bp-browse-button', 134 'container' => 'bp-upload-ui', 135 'drop_element' => 'drag-drop-area', 136 'bp_params' => array(), 137 'extra_css' => array(), 138 'extra_js' => array(), 139 'feedback_messages' => array(), 140 ), 'attachments_enqueue_scripts' ); 141 142 if ( empty( $args['action'] ) || empty( $args['file_data_name'] ) ) { 143 return new WP_Error( 'missing_parameter' ); 144 } 145 146 // Get the BuddyPress uploader strings 147 $strings = bp_attachments_get_plupload_l10n(); 148 149 // Get the BuddyPress uploader settings 150 $settings = bp_attachments_get_plupload_default_settings(); 151 152 // Set feedback messages 153 if ( ! empty( $args['feedback_messages'] ) ) { 154 $strings['feedback_messages'] = $args['feedback_messages']; 155 } 156 157 // Use a temporary var to ease manipulation 158 $defaults = $settings['defaults']; 159 160 // Set the upload action 161 $defaults['multipart_params']['action'] = $args['action']; 162 163 // Set BuddyPress upload parameters if provided 164 if ( ! empty( $args['bp_params'] ) ) { 165 $defaults['multipart_params']['bp_params'] = $args['bp_params']; 166 } 167 168 // Merge other arguments 169 $ui_args = array_intersect_key( $args, array( 170 'file_data_name' => true, 171 'browse_button' => true, 172 'container' => true, 173 'drop_element' => true, 174 ) ); 175 176 $defaults = array_merge( $defaults, $ui_args ); 177 178 if ( ! empty( $args['max_file_size'] ) ) { 179 $defaults['filters']['max_file_size'] = $args['max_file_size'] . 'b'; 180 } 181 182 // Specific to BuddyPress Avatars 183 if ( 'bp_avatar_upload' === $defaults['multipart_params']['action'] ) { 184 185 // Include the cropping informations for avatars 186 $settings['crop'] = array( 187 'full_h' => bp_core_avatar_full_height(), 188 'full_w' => bp_core_avatar_full_width(), 189 ); 190 191 // Avatar only need 1 file and 1 only! 192 $defaults['multi_selection'] = false; 193 194 // Does the object already has an avatar set 195 $has_avatar = $defaults['multipart_params']['bp_params']['has_avatar']; 196 197 // What is the object the avatar belongs to 198 $object = $defaults['multipart_params']['bp_params']['object']; 199 200 // Init the Avatar nav 201 $avatar_nav = array( 202 'upload' => array( 'id' => 'upload', 'caption' => __( 'Upload', 'buddypress' ), 'order' => 0 ), 203 204 // The delete view will only show if the object has an avatar 205 'delete' => array( 'id' => 'delete', 'caption' => __( 'Delete', 'buddypress' ), 'order' => 100, 'hide' => (int) ! $has_avatar ), 206 ); 207 208 // Use this filter to disable the Webcam Avatar feature 209 if ( false !== apply_filters( 'bp_attachment_avatar_use_webcam', true ) && 'user' === $object ) { 210 $avatar_nav['camera'] = array( 'id' => 'camera', 'caption' => __( 'Camera', 'buddypress' ), 'order' => 10 ); 211 212 // Set warning messages 213 $strings['camera_warnings'] = array( 214 'requesting' => __( 'Requesting video stream, please authorize this website to access to your camera.', 'buddypress'), 215 'loading' => __( 'Please wait for the video to load.', 'buddypress' ), 216 'loaded' => __( 'Video stream loaded. You can use the capture button to display the profile photo preview.', 'buddypress' ), 217 'noaccess' => __( 'You denied this website to access to your camera. Please use the upload form.', 'buddypress' ), 218 'errormsg' => __( 'Your browser is not supported. Please use the upload form.', 'buddypress' ), 219 'videoerror' => __( 'Video error. Please use the upload form.', 'buddypress' ), 220 'ready' => __( 'Your profile photo is ready, use the save button to validate.', 'buddypress' ), 221 'nocapture' => __( 'No profile photo was captured, please use the capture button first.', 'buddypress' ), 222 ); 223 } 224 225 /** 226 * Use this filter to add a navigation to a custom tool to set the object's avatar 227 * 228 * @since BuddyPress (2.3.0) 229 * 230 * @param array $avatar_nav An associative array of available nav items where each item is an array organized this way: 231 * $avatar_nav[ $nav_item_id ] { 232 * @type string $nav_item_id the nav item id in lower case without special characters or space 233 * @type string $caption the name of the item nav that will be displayed in the nav 234 * @type int $order An integer to specify the priority of the item nav, choose one 235 * between 1 and 99 to be after the uploader nav item and before the delete nav item 236 * @type int $hide if set to 1 the item nav will be hidden 237 * (only used for the delete nav item) 238 * } 239 * @param string $object the object the avatar belongs to (eg: user or group) 240 */ 241 $settings['nav'] = bp_sort_by_key( apply_filters( 'bp_attachments_avatar_nav', $avatar_nav, $object ), 'order', 'num' ); 242 } 243 244 // Set Plupload settings 245 $settings['defaults'] = $defaults; 246 247 /** 248 * Enqueue some extra styles if required 249 * 250 * Extra styles need to be registered. 251 */ 252 if ( ! empty( $args['extra_css'] ) ) { 253 foreach ( (array) $args['extra_css'] as $css ) { 254 if ( empty( $css ) ) { 255 continue; 256 } 257 258 wp_enqueue_style( $css ); 259 } 260 } 261 262 wp_enqueue_script ( 'bp-plupload' ); 263 wp_localize_script( 'bp-plupload', 'BP_Uploader', array( 'strings' => $strings, 'settings' => $settings ) ); 264 265 /** 266 * Enqueue some extra scripts if required 267 * 268 * Extra scripts need to be registered. 269 */ 270 if ( ! empty( $args['extra_js'] ) ) { 271 foreach ( (array) $args['extra_js'] as $js ) { 272 if ( empty( $js ) ) { 273 continue; 274 } 275 276 wp_enqueue_script( $js ); 277 } 278 } 279 280 /** 281 * Fires at the conclusion of bp_attachments_enqueue_scripts() 282 * to avoid the scripts to be loaded more than once. 283 * 284 * @since BuddyPress 2.3.0 285 */ 286 do_action( 'bp_attachments_enqueue_scripts' ); 287 } 288 289 /** 290 * Check the current user's capability to edit an avatar for a given object 291 * 292 * @since BuddyPress (2.3.0) 293 * 294 * @param string $capability the capability to check 295 * @param array $args an array containing the item_id and the object to check 296 */ 297 function bp_attachments_current_user_can( $capability, $args = array() ) { 298 $can = false; 299 300 if ( 'edit_avatar' === $capability ) { 301 /** 302 * Needed avatar arguments are set. 303 */ 304 if ( isset( $args['item_id'] ) && isset( $args['object'] ) ) { 305 // Group profile photo 306 if ( bp_is_active( 'groups' ) && 'group' === $args['object'] ) { 307 if ( bp_is_group_create() ) { 308 $can = (bool) groups_is_user_creator( bp_loggedin_user_id(), $args['item_id'] ) || bp_current_user_can( 'bp_moderate' ); 309 } else { 310 $can = (bool) groups_is_user_admin( bp_loggedin_user_id(), $args['item_id'] ) || bp_current_user_can( 'bp_moderate' ); 311 } 312 // User profile photo 313 } elseif ( bp_is_active( 'xprofile' ) && 'user' === $args['object'] ) { 314 $can = bp_loggedin_user_id() === (int) $args['item_id'] || bp_current_user_can( 'bp_moderate' ); 315 } 316 /** 317 * No avatar arguments, fallback to bp_user_can_create_groups() 318 * or bp_is_item_admin() 319 */ 320 } else { 321 if ( bp_is_group_create() ) { 322 $can = bp_user_can_create_groups(); 323 } else { 324 $can = bp_is_item_admin(); 325 } 326 } 327 } 328 329 return apply_filters( 'bp_attachments_current_user_can', $can, $capability, $args ); 330 } 331 332 /** 333 * Send a JSON response back to an Ajax upload request. 334 * 335 * @since BuddyPress (2.3.0) 336 * 337 * @param bool true for a success, false otherwise 338 * @param bool true if the Plupload runtime used is html4, false otherwise. 339 * @param mixed $data Data to encode as JSON, then print and die. 340 */ 341 function bp_attachments_json_response( $success, $is_html4 = false, $data = null ) { 342 $response = array( 'success' => $success ); 343 344 if ( isset( $data ) ) { 345 $response['data'] = $data; 346 } 347 348 // Send regular json response 349 if ( ! $is_html4 ) { 350 wp_send_json( $response ); 351 352 /** 353 * Send specific json response 354 * the html4 Plupload handler requires a text/html content-type for older IE. 355 * See https://core.trac.wordpress.org/ticket/31037 356 */ 357 } else { 358 echo wp_json_encode( $response ); 359 360 wp_die(); 361 } 362 } 363 364 /** 365 * Get an Attachment template part. 366 * 367 * @since BuddyPress (2.3.0) 368 * 369 * @param string Template part slug. eg 'uploader' for 'uploader.php'. 370 */ 371 function bp_attachments_get_template_part( $slug ) { 372 $attachment_template_part = 'assets/_attachments/' . $slug; 373 374 // Load the attachment template in WP Administratin screens 375 if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) { 376 $attachment_admin_template_part = buddypress()->themes_dir . '/bp-legacy/buddypress/' . $attachment_template_part . '.php'; 377 378 // Check the template part exists 379 if ( ! file_exists( $attachment_admin_template_part ) ) { 380 return false; 381 } 382 383 // load the template part 384 require( $attachment_admin_template_part ); 385 386 // Load the attachment template in WP_USE_THEMES env. 387 } else { 388 bp_get_template_part( $attachment_template_part ); 389 } 390 } -
src/bp-core/bp-core-avatars.php
diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php index 8c6ca3a..1bd919f 100644
function bp_core_delete_existing_avatar( $args = '' ) { 554 554 } 555 555 556 556 /** 557 * Ajax delete an avatar for a given object and item id 558 * 559 * @since BuddyPress (2.3.0) 560 * 561 * @return string a json object containing success data if the avatar was deleted 562 * error message otherwise 563 */ 564 function bp_avatar_ajax_delete() { 565 // Bail if not a POST action 566 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 567 wp_send_json_error(); 568 } 569 570 $avatar_data = $_POST; 571 572 if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) ) { 573 wp_send_json_error(); 574 } 575 576 $nonce = 'bp_delete_avatar_link'; 577 if ( 'group' === $avatar_data['object'] ) { 578 $nonce = 'bp_group_avatar_delete'; 579 } 580 581 // Check the nonce 582 check_admin_referer( $nonce, 'nonce' ); 583 584 // Capability check 585 if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) { 586 wp_send_json_error(); 587 } 588 589 // Handle delete 590 if ( bp_core_delete_existing_avatar( array( 'item_id' => $avatar_data['item_id'], 'object' => $avatar_data['object'] ) ) ) { 591 $return = array( 592 'avatar' => html_entity_decode( bp_core_fetch_avatar( array( 593 'object' => $avatar_data['object'], 594 'item_id' => $avatar_data['item_id'], 595 'html' => false, 596 'type' => 'full', 597 ) ) ), 598 'feedback_code' => 4, 599 'item_id' => $avatar_data['item_id'], 600 ); 601 602 wp_send_json_success( $return ); 603 } else { 604 wp_send_json_error( array( 605 'feedback_code' => 3, 606 ) ); 607 } 608 } 609 add_action( 'wp_ajax_bp_avatar_delete', 'bp_avatar_ajax_delete' ); 610 611 /** 557 612 * Handle avatar uploading. 558 613 * 559 614 * The functions starts off by checking that the file has been uploaded … … function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 626 681 } 627 682 628 683 /** 684 * Ajax upload an avatar 685 * 686 * @since BuddyPress (2.3.0) 687 * 688 * @return string a json object containing success data if the upload succeeded 689 * error message otherwise 690 */ 691 function bp_avatar_ajax_upload() { 692 // Bail if not a POST action 693 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 694 wp_die(); 695 } 696 697 /** 698 * Sending the json response will be different if 699 * the current Plupload runtime is html4 700 */ 701 $is_html4 = false; 702 if ( ! empty( $_POST['html4' ] ) ) { 703 $is_html4 = true; 704 } 705 706 // Check the nonce 707 check_admin_referer( 'bp-uploader' ); 708 709 // Init the BuddyPress parameters 710 $bp_params = array(); 711 712 // We need it to carry on 713 if ( ! empty( $_POST['bp_params' ] ) ) { 714 $bp_params = $_POST['bp_params' ]; 715 } else { 716 bp_attachments_json_response( false, $is_html4 ); 717 } 718 719 // We need the object to set the uploads dir filter 720 if ( empty( $bp_params['object'] ) ) { 721 bp_attachments_json_response( false, $is_html4 ); 722 } 723 724 // Capability check 725 if ( ! bp_attachments_current_user_can( 'edit_avatar', $bp_params ) ) { 726 bp_attachments_json_response( false, $is_html4 ); 727 } 728 729 $bp = buddypress(); 730 $bp_params['upload_dir_filter'] = ''; 731 $needs_reset = array(); 732 733 if ( 'user' === $bp_params['object'] && bp_is_active( 'xprofile' ) ) { 734 $bp_params['upload_dir_filter'] = 'xprofile_avatar_upload_dir'; 735 736 if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) { 737 $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user ); 738 $bp->displayed_user->id = $bp_params['item_id']; 739 } 740 } elseif ( 'group' === $bp_params['object'] && bp_is_active( 'groups' ) ) { 741 $bp_params['upload_dir_filter'] = 'groups_avatar_upload_dir'; 742 743 if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) { 744 $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group ); 745 $bp->groups->current_group = groups_get_group( array( 746 'group_id' => $bp_params['item_id'], 747 'populate_extras' => false, 748 ) ); 749 } 750 } else { 751 /** 752 * Filter here to deal with other components 753 * 754 * @since BuddyPress (2.3.0) 755 * 756 * @var array $bp_params the BuddyPress Ajax parameters 757 */ 758 $bp_params = apply_filters( 'bp_core_avatar_ajax_upload_params', $bp_params ); 759 } 760 761 if ( ! isset( $bp->avatar_admin ) ) { 762 $bp->avatar_admin = new stdClass(); 763 } 764 765 // Upload the avatar 766 $avatar = bp_core_avatar_handle_upload( $_FILES, $bp_params['upload_dir_filter'] ); 767 768 // Reset objects 769 if ( ! empty( $needs_reset ) ) { 770 if ( ! empty( $needs_reset['component'] ) ) { 771 $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value']; 772 } else { 773 $bp->{$needs_reset['key']} = $needs_reset['value']; 774 } 775 } 776 777 if ( empty( $avatar ) ) { 778 // Default upload error 779 $message = array(); 780 781 // Intercept the template message and remove it 782 if ( ! empty( $bp->template_message ) ) { 783 // Set the feedback message 784 $message = array( 785 'type' => 'upload_error', 786 'message' => $bp->template_message, 787 ); 788 789 // Remove template message. 790 $bp->template_message = false; 791 $bp->template_message_type = false; 792 @setcookie( 'bp-message', false, time() - 1000, COOKIEPATH ); 793 @setcookie( 'bp-message-type', false, time() - 1000, COOKIEPATH ); 794 } 795 796 bp_attachments_json_response( false, $is_html4, $message ); 797 } 798 799 if ( empty( $bp->avatar_admin->image->file ) ) { 800 bp_attachments_json_response( false, $is_html4 ); 801 } 802 803 $uploaded_image = @getimagesize( $bp->avatar_admin->image->file ); 804 805 // Set the name of the file 806 $name = $_FILES['file']['name']; 807 $name_parts = pathinfo( $name ); 808 $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) ); 809 810 if ( 'user' === $bp_params['object'] ) { 811 do_action( 'xprofile_avatar_uploaded' ); 812 } 813 814 // Finally return the avatar to the editor 815 bp_attachments_json_response( true, $is_html4, array( 816 'name' => $name, 817 'url' => $bp->avatar_admin->image->url, 818 'width' => $uploaded_image[0], 819 'height' => $uploaded_image[1], 820 ) ); 821 } 822 add_action( 'wp_ajax_bp_avatar_upload', 'bp_avatar_ajax_upload' ); 823 824 /** 825 * Handle avatar webcam capture. 826 * 827 * @since BuddyPress (2.3.0) 828 * 829 * @param string $data base64 encoded image. 830 * @param int $item_id. 831 * @return bool True on success, false on failure. 832 */ 833 function bp_avatar_handle_capture( $data = '', $item_id = 0 ) { 834 if ( empty( $data ) || empty( $item_id ) ) { 835 return false; 836 } 837 838 $avatar_dir = bp_core_avatar_upload_path() . '/avatars'; 839 840 // It's not a regular upload, we may need to create this folder 841 if ( ! file_exists( $avatar_dir ) ) { 842 if ( ! wp_mkdir_p( $avatar_dir ) ) { 843 return false; 844 } 845 } 846 847 $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $avatar_dir . '/' . $item_id, $item_id, 'user', 'avatars' ); 848 849 // It's not a regular upload, we may need to create this folder 850 if( ! is_dir( $avatar_folder_dir ) ) { 851 if ( ! wp_mkdir_p( $avatar_folder_dir ) ) { 852 return false; 853 } 854 } 855 856 $original_file = $avatar_folder_dir . '/webcam-capture-' . $item_id . '.png'; 857 858 if ( file_put_contents( $original_file, $data ) ) { 859 $avatar_to_crop = str_replace( bp_core_avatar_upload_path(), '', $original_file ); 860 861 // Crop to default values 862 $crop_args = array( 'item_id' => $item_id, 'original_file' => $avatar_to_crop, 'crop_x' => 0, 'crop_y' => 0 ); 863 864 do_action( 'xprofile_avatar_uploaded' ); 865 866 return bp_core_avatar_handle_crop( $crop_args ); 867 } else { 868 return false; 869 } 870 } 871 872 /** 629 873 * Crop an uploaded avatar. 630 874 * 631 875 * $args has the following parameters: … … function bp_core_avatar_handle_crop( $args = '' ) { 690 934 } 691 935 692 936 /** 937 * Ajax set an avatar for a given object and item id 938 * 939 * @since BuddyPress (2.3.0) 940 * 941 * @return string a json object containing success data if the crop/capture succeeded 942 * error message otherwise 943 */ 944 function bp_avatar_ajax_set() { 945 // Bail if not a POST action 946 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 947 wp_send_json_error(); 948 } 949 950 // Check the nonce 951 check_admin_referer( 'bp_avatar_cropstore', 'nonce' ); 952 953 $avatar_data = wp_parse_args( $_POST, array( 954 'crop_w' => bp_core_avatar_full_width(), 955 'crop_h' => bp_core_avatar_full_height(), 956 'crop_x' => 0, 957 'crop_y' => 0 958 ) ); 959 960 if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) || empty( $avatar_data['original_file'] ) ) { 961 wp_send_json_error(); 962 } 963 964 // Capability check 965 if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) { 966 wp_send_json_error(); 967 } 968 969 if ( ! empty( $avatar_data['type'] ) && 'camera' === $avatar_data['type'] && 'user' === $avatar_data['object'] ) { 970 $webcam_avatar = false; 971 972 if ( ! empty( $avatar_data['original_file'] ) ) { 973 $webcam_avatar = str_replace( array( 'data:image/png;base64,', ' ' ), array( '', '+' ), $avatar_data['original_file'] ); 974 $webcam_avatar = base64_decode( $webcam_avatar ); 975 } 976 977 if ( ! bp_avatar_handle_capture( $webcam_avatar, $avatar_data['item_id'] ) ) { 978 wp_send_json_error( array( 979 'feedback_code' => 1 980 ) ); 981 982 } else { 983 $return = array( 984 'avatar' => html_entity_decode( bp_core_fetch_avatar( array( 985 'object' => $avatar_data['object'], 986 'item_id' => $avatar_data['item_id'], 987 'html' => false, 988 'type' => 'full', 989 ) ) ), 990 'feedback_code' => 2, 991 'item_id' => $avatar_data['item_id'], 992 ); 993 994 do_action( 'xprofile_screen_change_avatar' ); 995 996 wp_send_json_success( $return ); 997 } 998 999 return; 1000 } 1001 1002 $original_file = str_replace( bp_core_avatar_url(), '', $avatar_data['original_file'] ); 1003 1004 // Set avatars dir & feedback part 1005 if ( 'user' === $avatar_data['object'] ) { 1006 $avatar_dir = 'avatars'; 1007 1008 // Defaults to object-avatars dir 1009 } else { 1010 $avatar_dir = sanitize_key( $avatar_data['object'] ) . '-avatars'; 1011 } 1012 1013 // Crop args 1014 $r = array( 1015 'item_id' => $avatar_data['item_id'], 1016 'object' => $avatar_data['object'], 1017 'avatar_dir' => $avatar_dir, 1018 'original_file' => $original_file, 1019 'crop_w' => $avatar_data['crop_w'], 1020 'crop_h' => $avatar_data['crop_h'], 1021 'crop_x' => $avatar_data['crop_x'], 1022 'crop_y' => $avatar_data['crop_y'] 1023 ); 1024 1025 // Handle crop 1026 if ( bp_core_avatar_handle_crop( $r ) ) { 1027 $return = array( 1028 'avatar' => html_entity_decode( bp_core_fetch_avatar( array( 1029 'object' => $avatar_data['object'], 1030 'item_id' => $avatar_data['item_id'], 1031 'html' => false, 1032 'type' => 'full', 1033 ) ) ), 1034 'feedback_code' => 2, 1035 'item_id' => $avatar_data['item_id'], 1036 ); 1037 1038 if ( 'user' === $avatar_data['object'] ) { 1039 do_action( 'xprofile_screen_change_avatar' ); 1040 } 1041 1042 wp_send_json_success( $return ); 1043 } else { 1044 wp_send_json_error( array( 1045 'feedback_code' => 1, 1046 ) ); 1047 } 1048 } 1049 add_action( 'wp_ajax_bp_avatar_set', 'bp_avatar_ajax_set' ); 1050 1051 /** 693 1052 * Replace default WordPress avatars with BP avatars, if available. 694 1053 * 695 1054 * Filters 'get_avatar'. … … function bp_core_avatar_reset_query( $posts_query = null ) { 1099 1458 } 1100 1459 } 1101 1460 add_action( 'bp_parse_query', 'bp_core_avatar_reset_query', 10, 1 ); 1461 1462 /** 1463 * Checks whether Avatar UI should be loaded 1464 * 1465 * @since BuddyPress (2.3.0) 1466 * 1467 * @return bool True if Avatar UI should load, false otherwise 1468 */ 1469 function bp_avatar_is_front_edit() { 1470 $retval = false; 1471 1472 if ( bp_is_user_change_avatar() && 'crop-image' !== bp_get_avatar_admin_step() ) { 1473 $retval = true; 1474 } 1475 1476 if ( bp_is_active( 'groups' ) ) { 1477 // Group creation 1478 if ( bp_is_group_create() && bp_is_group_creation_step( 'group-avatar' ) && 'crop-image' !== bp_get_avatar_admin_step() ) { 1479 $retval = true; 1480 1481 // Group Manage 1482 } elseif ( bp_is_group_admin_page() && bp_is_group_admin_screen( 'group-avatar' ) && 'crop-image' !== bp_get_avatar_admin_step() ) { 1483 $retval = true; 1484 } 1485 } 1486 1487 /** 1488 * Use this filter if you need to : 1489 * - Load the avatar UI for a component that is !groups or !user (return true regarding your conditions) 1490 * - Completely disable the avatar UI introduced in 2.3 (eg: __return_false()) 1491 * 1492 * @since BuddyPress (2.3.0) 1493 * 1494 * @var bool whether to load the Avatar UI 1495 */ 1496 return apply_filters( 'bp_avatar_is_front_edit', $retval ); 1497 } 1498 1499 /** 1500 * Template function to load the Avatar UI javascript templates 1501 * 1502 * @since BuddyPress (2.3.0) 1503 */ 1504 function bp_avatar_get_templates() { 1505 if ( ! bp_avatar_is_front_edit() ) { 1506 return; 1507 } 1508 1509 bp_attachments_get_template_part( 'avatars/index' ); 1510 } 1511 1512 /** 1513 * Trick to check if the theme's BuddyPress templates are up to date 1514 * 1515 * If the "avatar templates" are not including the new template tag, this will 1516 * help users to get the avatar UI and inform the most curious that their 1517 * templates are out of date. 1518 * 1519 * @since BuddyPress (2.3.0) 1520 */ 1521 function bp_avatar_template_check() { 1522 if ( ! bp_avatar_is_front_edit() ) { 1523 return; 1524 } 1525 1526 if ( ! did_action( 'bp_attachments_avatar_check_template' ) ) { 1527 bp_attachments_get_template_part( 'avatars/index' ); 1528 } 1529 } -
src/bp-core/bp-core-cssjs.php
diff --git src/bp-core/bp-core-cssjs.php src/bp-core/bp-core-cssjs.php index 8694f8a..ea25396 100644
function bp_core_register_common_scripts() { 28 28 $scripts = apply_filters( 'bp_core_register_common_scripts', array( 29 29 30 30 // Legacy 31 'bp-confirm' => array( 'file' => "{$url}confirm{$min}.js", 'dependencies' => array( 'jquery' ) ),32 'bp-widget-members' => array( 'file' => "{$url}widget-members{$min}.js", 'dependencies' => array( 'jquery' ) ),33 'bp-jquery-query' => array( 'file' => "{$url}jquery-query{$min}.js", 'dependencies' => array( 'jquery' ) ),34 'bp-jquery-cookie' => array( 'file' => "{$url}jquery-cookie{$min}.js", 'dependencies' => array( 'jquery' ) ),35 'bp-jquery-scroll-to' => array( 'file' => "{$url}jquery-scroll-to{$min}.js", 'dependencies' => array( 'jquery' ) ),31 'bp-confirm' => array( 'file' => "{$url}confirm{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ), 32 'bp-widget-members' => array( 'file' => "{$url}widget-members{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ), 33 'bp-jquery-query' => array( 'file' => "{$url}jquery-query{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ), 34 'bp-jquery-cookie' => array( 'file' => "{$url}jquery-cookie{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ), 35 'bp-jquery-scroll-to' => array( 'file' => "{$url}jquery-scroll-to{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ), 36 36 37 37 // 2.1 38 'jquery-caret' => array( 'file' => "{$url}jquery.caret{$min}.js", 'dependencies' => array( 'jquery' ) ), 39 'jquery-atwho' => array( 'file' => "{$url}jquery.atwho{$min}.js", 'dependencies' => array( 'jquery', 'jquery-caret' ) ), 38 'jquery-caret' => array( 'file' => "{$url}jquery.caret{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ), 39 'jquery-atwho' => array( 'file' => "{$url}jquery.atwho{$min}.js", 'dependencies' => array( 'jquery', 'jquery-caret' ), 'footer' => false ), 40 41 // 2.3 42 'bp-plupload' => array( 'file' => "{$url}bp-plupload{$min}.js", 'dependencies' => array( 'plupload', 'jquery', 'json2', 'wp-backbone' ), 'footer' => true ), 43 'bp-avatar' => array( 'file' => "{$url}avatar{$min}.js", 'dependencies' => array( 'jcrop' ), 'footer' => true ), 44 'bp-webcam' => array( 'file' => "{$url}webcam{$min}.js", 'dependencies' => array( 'bp-avatar' ), 'footer' => true ), 45 40 46 ) ); 41 47 42 48 $version = bp_get_version(); 43 49 foreach ( $scripts as $id => $script ) { 44 wp_register_script( $id, $script['file'], $script['dependencies'], $version );50 wp_register_script( $id, $script['file'], $script['dependencies'], $version, $script['footer'] ); 45 51 } 46 52 } 47 53 add_action( 'bp_enqueue_scripts', 'bp_core_register_common_scripts', 1 ); … … function bp_core_register_common_styles() { 76 82 'bp-admin-bar' => array( 77 83 'file' => $admin_bar_file, 78 84 'dependencies' => array( 'admin-bar' ) 79 ) 85 ), 86 'bp-avatar' => array( 87 'file' => "{$url}avatar{$min}.css", 88 'dependencies' => array( 'jcrop' ) 89 ), 80 90 ) ); 81 91 82 92 foreach ( $styles as $id => $style ) { … … add_action( 'bp_enqueue_scripts', 'bp_core_confirmation_js' ); 110 120 add_action( 'bp_admin_enqueue_scripts', 'bp_core_confirmation_js' ); 111 121 112 122 /** 123 * Enqueues the css and js required by the Avatar UI 124 * 125 * @since BuddyPress (2.3.0) 126 */ 127 function bp_core_avatar_scripts() { 128 if ( ! bp_avatar_is_front_edit() ) { 129 return false; 130 } 131 132 // Enqueue the Attachments scripts for the Avatar UI 133 bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' ); 134 135 // Add Some actions for Theme backcompat 136 add_action( 'bp_after_profile_avatar_upload_content', 'bp_avatar_template_check' ); 137 add_action( 'bp_after_group_admin_content', 'bp_avatar_template_check' ); 138 add_action( 'bp_after_group_avatar_creation_step', 'bp_avatar_template_check' ); 139 } 140 add_action( 'bp_enqueue_scripts', 'bp_core_avatar_scripts' ); 141 142 /** 113 143 * Enqueues jCrop library and hooks BP's custom cropper JS. 114 144 */ 115 145 function bp_core_add_jquery_cropper() { -
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 14e1f6c..8dd8edc 100644
class BP_Attachment_Avatar extends BP_Attachment { 256 256 // Return the full and thumb cropped avatars 257 257 return $avatar_types; 258 258 } 259 260 /** 261 * Get the user id to set its avatar 262 * 263 * @since BuddyPress (2.3.0) 264 * 265 * @return integer the user ID 266 */ 267 private function get_user_id() { 268 $bp = buddypress(); 269 $user_id = 0; 270 271 if ( bp_is_user() ) { 272 $user_id = bp_displayed_user_id(); 273 } 274 275 if ( ! empty( $bp->members->admin->user_id ) ) { 276 $user_id = $bp->members->admin->user_id; 277 } 278 279 return $user_id; 280 } 281 282 /** 283 * Get the group id to set its avatar 284 * 285 * @since BuddyPress (2.3.0) 286 * 287 * @return integer the group id 288 */ 289 private function get_group_id() { 290 $group_id = 0; 291 292 if ( bp_is_group() ) { 293 $group_id = bp_get_current_group_id(); 294 } 295 296 return $group_id; 297 } 298 299 /** 300 * Build script datas for the Uploader UI 301 * 302 * @since BuddyPress (2.3.0) 303 * 304 * @return array the javascript localization data 305 */ 306 public function script_data() { 307 // Get default script data 308 $script_data = parent::script_data(); 309 310 // Defaults to Avatar Backbone script 311 $js_scripts = array( 'bp-avatar' ); 312 313 // Default object 314 $object = ''; 315 316 // Get the possible item ids 317 $user_id = $this->get_user_id(); 318 $group_id = $this->get_group_id(); 319 320 if ( ! empty( $user_id ) ) { 321 // Use this filter to disable the Webcam Avatar feature 322 if ( false !== apply_filters( 'bp_attachment_avatar_use_webcam', true ) ) { 323 $js_scripts = array( 'bp-webcam' ); 324 } 325 326 $script_data['bp_params'] = array( 327 'object' => 'user', 328 'item_id' => $user_id, 329 'has_avatar' => bp_get_user_has_avatar( $user_id ), 330 'nonces' => array( 331 'set' => wp_create_nonce( 'bp_avatar_cropstore' ), 332 'remove' => wp_create_nonce( 'bp_delete_avatar_link' ), 333 ), 334 ); 335 336 // Set feedback messages 337 $script_data['feedback_messages'] = array( 338 1 => __( 'There was a problem cropping your profile photo.', 'buddypress' ), 339 2 => __( 'Your new profile photo was uploaded successfully.', 'buddypress' ), 340 3 => __( 'There was a problem deleting your profile photo. Please try again.', 'buddypress' ), 341 4 => __( 'Your profile photo was deleted successfully!', 'buddypress' ), 342 ); 343 } elseif ( ! empty( $group_id ) ) { 344 $script_data['bp_params'] = array( 345 'object' => 'group', 346 'item_id' => $group_id, 347 'has_avatar' => bp_get_group_has_avatar( $group_id ), 348 'nonces' => array( 349 'set' => wp_create_nonce( 'bp_avatar_cropstore' ), 350 'remove' => wp_create_nonce( 'bp_group_avatar_delete' ), 351 ), 352 ); 353 354 // Set feedback messages 355 $script_data['feedback_messages'] = array( 356 1 => __( 'There was a problem cropping the group profile photo.', 'buddypress' ), 357 2 => __( 'The group profile photo was uploaded successfully.', 'buddypress' ), 358 3 => __( 'There was a problem deleting the group profile photo. Please try again.', 'buddypress' ), 359 4 => __( 'The group profile photo was deleted successfully!', 'buddypress' ), 360 ); 361 } else { 362 /** 363 * Use this filter to include specific BuddyPress params for your object 364 * e.g. Blavatar 365 * 366 * @since BuddyPress (2.3.0) 367 * 368 * @param array the avatar specific BuddyPress parameters 369 */ 370 $script_data['bp_params'] = apply_filters( 'bp_attachment_avatar_params', array() ); 371 } 372 373 // Include the specific css 374 $script_data['extra_css'] = array( 'bp-avatar' ); 375 376 // Include the specific css 377 $script_data['extra_js'] = $js_scripts; 378 379 // Set the object to contextualize the filter 380 if ( isset( $script_data['bp_params']['object'] ) ) { 381 $object = $script_data['bp_params']['object']; 382 } 383 384 /** 385 * Use this filter to override/extend the avatar script data 386 * 387 * @since BuddyPress (2.3.0) 388 * 389 * @param array $script_data the avatar script data 390 * @param string $object the object the avatar belongs to (eg: user or group) 391 */ 392 return apply_filters( 'bp_attachment_avatar_script_data', $script_data, $object ); 393 } 259 394 } -
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 6a7d115..4d6365d 100644
abstract class BP_Attachment { 477 477 // Finally crop the image 478 478 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'] ); 479 479 } 480 481 /** 482 * Build script datas for the Uploader UI 483 * 484 * Override this method from your child class to build the script datas 485 * 486 * @since BuddyPress (2.3.0) 487 * 488 * @return array the javascript localization data 489 */ 490 public function script_data() { 491 $script_data = array( 492 'action' => $this->action, 493 'file_data_name' => $this->file_input, 494 'max_file_size' => $this->original_max_filesize, 495 'feedback_messages' => array( 496 1 => __( 'Sorry, uploading the file failed.', 'buddypress' ), 497 2 => __( 'File successfully uploaded.', 'buddypress' ), 498 ), 499 ); 500 501 return $script_data; 502 } 480 503 } -
src/bp-core/css/avatar.css
diff --git src/bp-core/css/avatar.css src/bp-core/css/avatar.css index e69de29..32dceaa 100644
1 div.bp-avatar-status { 2 clear:both; 3 margin:1em 0; 4 } 5 6 div.bp-avatar-status p.updated { 7 display: block; 8 padding: 10px 15px; 9 } 10 11 div.bp-avatar-status p.success { 12 background-color: #efc; 13 border: 1px solid #591; 14 color: #250; 15 } 16 17 div.bp-avatar-status p.error { 18 background-color: #fdc; 19 border: 1px solid #a00; 20 color: #800; 21 } 22 23 .progress { 24 float: right; 25 height: 22px; 26 margin: 6px 10px 0 0; 27 width: 200px; 28 line-height: 2em; 29 padding: 0; 30 overflow: hidden; 31 margin-bottom: 2px; 32 border: 1px solid #d1d1d1; 33 background: none; 34 } 35 36 .bar { 37 z-index: 9; 38 width: 0; 39 height: 100%; 40 background-color: #c3ff88; 41 } 42 43 .bp-uploader-progress div.error { 44 font-size: 90%; 45 display: block; 46 padding: 10px 15px; 47 background-color: #fdc; 48 border: 1px solid #a00; 49 color: #800; 50 } 51 52 #bp-uploader-warning, #bp-webcam-message p.warning { 53 margin:1em 0; 54 font-size: 90%; 55 display: block; 56 padding: 10px 15px; 57 background-color: #ffec8b; 58 border: 1px solid #fc0; 59 color: #440; 60 } 61 62 div.bp-avatar-nav { 63 clear:both; 64 background: transparent; 65 margin: 10px 0 10px; 66 overflow: hidden; 67 } 68 69 .avatar-nav-items { 70 margin: 0; 71 padding: 0; 72 } 73 74 .bp-avatar-nav .avatar-nav-items li.avatar-nav-item { 75 float: left; 76 margin: 0; 77 list-style: none; 78 } 79 80 .avatar-nav-items li a { 81 display: block; 82 padding: 5px 10px; 83 text-decoration: none; 84 } 85 86 .avatar-nav-items li.current a { 87 background-color: #eee; 88 color: #555; 89 opacity: .8; 90 font-weight: bold; 91 } 92 93 #drag-drop-area { 94 border: 4px dashed #bbb; 95 height: 200px; 96 } 97 98 .drag-drop.drag-over #drag-drop-area { 99 border-color: #83b4d8; 100 } 101 102 .drag-drop-inside p { 103 display:none; 104 } 105 106 .drag-drop-inside p.drag-drop-buttons { 107 margin-top:80px; 108 text-align: center; 109 } 110 .drag-drop .drag-drop-inside p.drag-drop-buttons { 111 margin:auto; 112 text-align: auto; 113 } 114 115 .drag-drop .drag-drop-inside { 116 margin: 70px auto 0; 117 width: 250px; 118 } 119 120 .drag-drop .drag-drop-inside p, .drag-drop-inside p.drag-drop-buttons { 121 display: block; 122 } 123 124 .drag-drop .drag-drop-inside p { 125 color: #aaa; 126 font-size: 110%; 127 margin: 5px 0; 128 text-align: center; 129 } 130 131 #avatar-to-crop { 132 float: left; 133 margin: 0 20px 20px 0; 134 text-align: left; 135 } 136 #avatar-crop-pane { 137 overflow: hidden; 138 } 139 140 #avatar-crop-actions { 141 margin: 20px 0; 142 } 143 144 #avatar-to-crop img, 145 #avatar-crop-pane img, 146 #avatar-crop-pane canvas, 147 #avatar-upload-form img, 148 #create-group-form img, 149 #group-settings-form img { 150 border: none !important; 151 max-width: none !important; 152 } 153 154 #bp-webcam-avatar video { 155 float:left; 156 width:450px; 157 } 158 159 #bp-webcam-avatar #avatar-crop-pane { 160 border: 2px dashed #bbb; 161 } 162 163 /** Admin Profile **/ 164 body.users_page_bp-profile-edit.modal-open #TB_ajaxContent, 165 body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent { 166 width:95%!important; 167 height:95%!important; 168 } 169 170 body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated, 171 body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning, 172 body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated, 173 body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning { 174 display: block; 175 padding: 10px 15px; 176 } -
src/bp-core/js/avatar.js
diff --git src/bp-core/js/avatar.js src/bp-core/js/avatar.js index e69de29..7d592f7 100644
1 /* globals bp, BP_Uploader, _, Backbone */ 2 3 window.bp = window.bp || {}; 4 5 ( function( exports, $ ) { 6 7 // Bail if not set 8 if ( typeof BP_Uploader === 'undefined' ) { 9 return; 10 } 11 12 bp.Models = bp.Models || {}; 13 bp.Collections = bp.Collections || {}; 14 bp.Views = bp.Views || {}; 15 16 bp.Avatar = { 17 start: function() { 18 /** 19 * Remove the bp-legacy UI 20 * 21 * bp.Avatar successfully loaded, we can now 22 * safely remove the Legacy UI. 23 */ 24 this.removeLegacyUI(); 25 26 // Init some vars 27 this.views = new Backbone.Collection(); 28 this.jcropapi = {}; 29 30 // Set up nav 31 this.setupNav(); 32 33 // Avatars are uploaded files 34 this.avatars = bp.Uploader.filesUploaded; 35 36 // Wait till the queue is reset 37 bp.Uploader.filesQueue.on( 'reset', this.cropView, this ); 38 39 /** 40 * In Administration screens we're using Thickbox 41 * We need to make sure to reset the views if it's closed 42 */ 43 $( 'body.wp-admin' ).on( 'tb_unload', '#TB_window', function() { 44 // Reset to the uploader view 45 bp.Avatar.nav.trigger( 'bp-avatar-view:changed', 'upload' ); 46 47 // Reset to the uploader nav 48 _.each( bp.Avatar.navItems.models, function( model ) { 49 if ( model.id === 'upload' ) { 50 model.set( { active: 1 } ); 51 } else { 52 model.set( { active: 0 } ); 53 } 54 } ); 55 } ); 56 }, 57 58 removeLegacyUI: function() { 59 // User 60 if ( $( '#avatar-upload-form' ).length ) { 61 $( '#avatar-upload' ).remove(); 62 $( '#avatar-upload-form p' ).remove(); 63 64 // Group Manage 65 } else if ( $( '#group-settings-form' ).length ) { 66 $( '#group-settings-form p' ).each( function( i ) { 67 if ( 0 !== i ) { 68 $( this ).remove(); 69 } 70 } ); 71 72 if ( $( '#delete-group-avatar-button' ).length ) { 73 $( '#delete-group-avatar-button' ).remove(); 74 } 75 76 // Group Create 77 } else if ( $( '#group-create-body' ).length ) { 78 $( '.main-column p #file' ).remove(); 79 $( '.main-column p #upload' ).remove(); 80 81 // Admin Extended Profile 82 } else if ( $( '#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin' ).length ) { 83 $( '#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin' ).remove(); 84 } 85 }, 86 87 setView: function( view ) { 88 // Clear views 89 if ( ! _.isUndefined( this.views.models ) ) { 90 _.each( this.views.models, function( model ) { 91 model.get( 'view' ).remove(); 92 }, this ); 93 } 94 95 // Reset Views 96 this.views.reset(); 97 98 // Reset Avatars (file uploaded) 99 if ( ! _.isUndefined( this.avatars ) ) { 100 this.avatars.reset(); 101 } 102 103 // Reset the Jcrop API 104 if ( ! _.isEmpty( this.jcropapi ) ) { 105 this.jcropapi.destroy(); 106 this.jcropapi = {}; 107 } 108 109 // Load the required view 110 switch ( view ) { 111 case 'upload': 112 this.uploaderView(); 113 break; 114 115 case 'delete': 116 this.deleteView(); 117 break; 118 } 119 }, 120 121 setupNav: function() { 122 var self = this, 123 initView, activeView; 124 125 this.navItems = new Backbone.Collection(); 126 127 _.each( BP_Uploader.settings.nav, function( item, index ) { 128 if ( ! _.isObject( item ) ) { 129 return; 130 } 131 132 // Reset active View 133 activeView = 0; 134 135 if ( 0 === index ) { 136 initView = item.id; 137 activeView = 1; 138 } 139 140 self.navItems.add( { 141 id : item.id, 142 name : item.caption, 143 href : '#', 144 active : activeView, 145 hide : _.isUndefined( item.hide ) ? 0 : item.hide 146 } ); 147 } ); 148 149 this.nav = new bp.Views.Nav( { collection: this.navItems } ); 150 this.nav.inject( '.bp-avatar-nav' ); 151 152 // Activate the initial view (uploader) 153 this.setView( initView ); 154 155 // Listen to nav changes (it's like a do_action!) 156 this.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) ); 157 }, 158 159 uploaderView: function() { 160 // Listen to the Queued uploads 161 bp.Uploader.filesQueue.on( 'add', this.uploadProgress, this ); 162 163 // Create the BuddyPress Uploader 164 var uploader = new bp.Views.Uploader(); 165 166 // Add it to views 167 this.views.add( { id: 'upload', view: uploader } ); 168 169 // Display it 170 uploader.inject( '.bp-avatar' ); 171 }, 172 173 uploadProgress: function() { 174 // Create the Uploader status view 175 var avatarStatus = new bp.Views.uploaderStatus( { collection: bp.Uploader.filesQueue } ); 176 177 if ( ! _.isUndefined( this.views.get( 'status' ) ) ) { 178 this.views.set( { id: 'status', view: avatarStatus } ); 179 } else { 180 this.views.add( { id: 'status', view: avatarStatus } ); 181 } 182 183 // Display it 184 avatarStatus.inject( '.bp-avatar-status' ); 185 }, 186 187 cropView: function() { 188 var status; 189 190 // Bail there was an error during the Upload 191 if ( _.isEmpty( this.avatars.models ) ) { 192 return; 193 } 194 195 // Make sure to remove the uploads status 196 if ( ! _.isUndefined( this.views.get( 'status' ) ) ) { 197 status = this.views.get( 'status' ); 198 status.get( 'view' ).remove(); 199 this.views.remove( { id: 'status', view: status } ); 200 } 201 202 // Create the Avatars view 203 var avatar = new bp.Views.Avatars( { collection: this.avatars } ); 204 this.views.add( { id: 'crop', view: avatar } ); 205 206 avatar.inject( '.bp-avatar' ); 207 }, 208 209 setAvatar: function( avatar ) { 210 var self = this, 211 crop; 212 213 // Remove the crop view 214 if ( ! _.isUndefined( this.views.get( 'crop' ) ) ) { 215 // Remove the JCrop API 216 if ( ! _.isEmpty( this.jcropapi ) ) { 217 this.jcropapi.destroy(); 218 this.jcropapi = {}; 219 } 220 crop = this.views.get( 'crop' ); 221 crop.get( 'view' ).remove(); 222 this.views.remove( { id: 'crop', view: crop } ); 223 } 224 225 // Set the avatar ! 226 bp.ajax.post( 'bp_avatar_set', { 227 json: true, 228 original_file: avatar.get( 'url' ), 229 crop_w: avatar.get( 'w' ), 230 crop_h: avatar.get( 'h' ), 231 crop_x: avatar.get( 'x' ), 232 crop_y: avatar.get( 'y' ), 233 item_id: avatar.get( 'item_id' ), 234 object: avatar.get( 'object' ), 235 type: _.isUndefined( avatar.get( 'type' ) ) ? 'crop' : avatar.get( 'type' ), 236 nonce: avatar.get( 'nonces' ).set 237 } ).done( function( response ) { 238 var avatarStatus = new bp.Views.AvatarStatus( { 239 value : BP_Uploader.strings.feedback_messages[ response.feedback_code ], 240 type : 'success' 241 } ); 242 243 self.views.add( { 244 id : 'status', 245 view : avatarStatus 246 } ); 247 248 avatarStatus.inject( '.bp-avatar-status' ); 249 250 // Update each avatars of the page 251 $( '.' + avatar.get( 'object' ) + '-' + response.item_id + '-avatar' ).each( function() { 252 $(this).prop( 'src', response.avatar ); 253 } ); 254 255 // Inject the Delete nav 256 bp.Avatar.navItems.get( 'delete' ).set( { hide: 0 } ); 257 258 } ).fail( function( response ) { 259 var feedback = BP_Uploader.strings.default_error; 260 if ( ! _.isUndefined( response ) ) { 261 feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ]; 262 } 263 264 var avatarStatus = new bp.Views.AvatarStatus( { 265 value : feedback, 266 type : 'error' 267 } ); 268 269 self.views.add( { 270 id : 'status', 271 view : avatarStatus 272 } ); 273 274 avatarStatus.inject( '.bp-avatar-status' ); 275 } ); 276 }, 277 278 deleteView:function() { 279 // Create the delete model 280 var delete_model = new Backbone.Model( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params, 281 'object', 282 'item_id', 283 'nonces' 284 ) ); 285 286 // Create the delete view 287 var deleteView = new bp.Views.DeleteAvatar( { model: delete_model } ); 288 289 // Add it to views 290 this.views.add( { id: 'delete', view: deleteView } ); 291 292 // Display it 293 deleteView.inject( '.bp-avatar' ); 294 }, 295 296 deleteAvatar: function( model ) { 297 var self = this, 298 deleteView; 299 300 // Remove the delete view 301 if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) { 302 deleteView = this.views.get( 'delete' ); 303 deleteView.get( 'view' ).remove(); 304 this.views.remove( { id: 'delete', view: deleteView } ); 305 } 306 307 // Remove the avatar ! 308 bp.ajax.post( 'bp_avatar_delete', { 309 json: true, 310 item_id: model.get( 'item_id' ), 311 object: model.get( 'object' ), 312 nonce: model.get( 'nonces' ).remove 313 } ).done( function( response ) { 314 var avatarStatus = new bp.Views.AvatarStatus( { 315 value : BP_Uploader.strings.feedback_messages[ response.feedback_code ], 316 type : 'success' 317 } ); 318 319 self.views.add( { 320 id : 'status', 321 view : avatarStatus 322 } ); 323 324 avatarStatus.inject( '.bp-avatar-status' ); 325 326 // Update each avatars of the page 327 $( '.' + model.get( 'object' ) + '-' + response.item_id + '-avatar').each( function() { 328 $( this ).prop( 'src', response.avatar ); 329 } ); 330 331 // Remove the Delete nav 332 bp.Avatar.navItems.get( 'delete' ).set( { active: 0, hide: 1 } ); 333 334 } ).fail( function( response ) { 335 var feedback = BP_Uploader.strings.default_error; 336 if ( ! _.isUndefined( response ) ) { 337 feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ]; 338 } 339 340 var avatarStatus = new bp.Views.AvatarStatus( { 341 value : feedback, 342 type : 'error' 343 } ); 344 345 self.views.add( { 346 id : 'status', 347 view : avatarStatus 348 } ); 349 350 avatarStatus.inject( '.bp-avatar-status' ); 351 } ); 352 } 353 }; 354 355 // Main Nav view 356 bp.Views.Nav = bp.View.extend( { 357 tagName: 'ul', 358 className: 'avatar-nav-items', 359 360 events: { 361 'click .bp-avatar-nav-item' : 'toggleView' 362 }, 363 364 initialize: function() { 365 _.each( this.collection.models, this.addNavItem, this ); 366 this.collection.on( 'change:hide', this.showHideNavItem, this ); 367 }, 368 369 addNavItem: function( item ) { 370 /** 371 * The delete nav is not added if no avatar 372 * is set for the object 373 */ 374 if ( 1 === item.get( 'hide' ) ) { 375 return; 376 } 377 378 this.views.add( new bp.Views.NavItem( { model: item } ) ); 379 }, 380 381 showHideNavItem: function( item ) { 382 var isRendered = null; 383 384 /** 385 * Loop in views to show/hide the nav item 386 * BuddyPress is only using this for the delete nav 387 */ 388 _.each( this.views._views[''], function( view ) { 389 if ( 1 === view.model.get( 'hide' ) ) { 390 view.remove(); 391 } 392 393 // Check to see if the nav is not already rendered 394 if ( item.get( 'id' ) === view.model.get( 'id' ) ) { 395 isRendered = true; 396 } 397 } ); 398 399 // Add the Delete nav if not rendered 400 if ( ! _.isBoolean( isRendered ) ) { 401 this.addNavItem( item ); 402 } 403 }, 404 405 toggleView: function( event ) { 406 event.preventDefault(); 407 408 var active = $( event.target ).data( 'nav' ); 409 410 _.each( this.collection.models, function( model ) { 411 if ( model.id === active ) { 412 model.set( { active: 1 } ); 413 this.trigger( 'bp-avatar-view:changed', model.id ); 414 } else { 415 model.set( { active: 0 } ); 416 } 417 }, this ); 418 } 419 } ); 420 421 // Nav item view 422 bp.Views.NavItem = bp.View.extend( { 423 tagName: 'li', 424 className: 'avatar-nav-item', 425 template: bp.template( 'bp-avatar-nav' ), 426 427 initialize: function() { 428 if ( 1 === this.model.get( 'active' ) ) { 429 this.el.className += ' current'; 430 } 431 this.el.id += 'bp-avatar-' + this.model.get( 'id' ); 432 433 this.model.on( 'change:active', this.setCurrentNav, this ); 434 }, 435 436 setCurrentNav: function( model ) { 437 if ( 1 === model.get( 'active' ) ) { 438 this.$el.addClass( 'current' ); 439 } else { 440 this.$el.removeClass( 'current' ); 441 } 442 } 443 } ); 444 445 // Avatars view 446 bp.Views.Avatars = bp.View.extend( { 447 className: 'items', 448 449 initialize: function() { 450 _.each( this.collection.models, this.addItemView, this ); 451 }, 452 453 addItemView: function( item ) { 454 // Defaults to 150 455 var full_d = { full_h: 150, full_w: 150 }; 456 457 // Make sure to take in account bp_core_avatar_full_height or bp_core_avatar_full_width php filters 458 if ( ! _.isUndefined( BP_Uploader.settings.crop.full_h ) && ! _.isUndefined( BP_Uploader.settings.crop.full_w ) ) { 459 full_d.full_h = BP_Uploader.settings.crop.full_h; 460 full_d.full_w = BP_Uploader.settings.crop.full_w; 461 } 462 463 // Set the avatar model 464 item.set( _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params, 465 'object', 466 'item_id', 467 'nonces' 468 ), full_d ) ); 469 470 // Add the view 471 this.views.add( new bp.Views.Avatar( { model: item } ) ); 472 } 473 } ); 474 475 // Avatar view 476 bp.Views.Avatar = bp.View.extend( { 477 className: 'item', 478 template: bp.template( 'bp-avatar-item' ), 479 480 events: { 481 'click .avatar-crop-submit': 'cropAvatar' 482 }, 483 484 initialize: function() { 485 _.defaults( this.options, { 486 full_h: BP_Uploader.settings.crop.full_h, 487 full_w: BP_Uploader.settings.crop.full_w, 488 aspectRatio : 1 489 } ); 490 491 this.on( 'ready', this.initCropper ); 492 }, 493 494 initCropper: function() { 495 var self = this, 496 tocrop = this.$el.find( '#avatar-to-crop img' ), 497 selection = {}, crop_top, crop_bottom, crop_left, crop_right, nh, nw; 498 499 if ( ! _.isUndefined( this.options.full_h ) && ! _.isUndefined( this.options.full_w ) ) { 500 this.options.aspectRatio = this.options.full_h / this.options.full_w; 501 } 502 503 selection.w = this.model.get( 'width' ); 504 selection.h = this.model.get( 'height' ); 505 506 if ( selection.h <= selection.w ) { 507 crop_top = Math.round( selection.h / 4 ); 508 nh = nw = Math.round( selection.h / 2 ); 509 crop_bottom = nh + crop_top; 510 crop_left = ( selection.w - nw ) / 2; 511 crop_right = nw + crop_left; 512 } else { 513 crop_left = Math.round( selection.w / 4 ); 514 nh = nw = Math.round( selection.w / 2 ); 515 crop_right = nw + crop_left; 516 crop_top = ( selection.h - nh ) / 2; 517 crop_bottom = nh + crop_top; 518 } 519 520 // Add the cropping interface 521 tocrop.Jcrop( { 522 onChange: _.bind( self.showPreview, self ), 523 onSelect: _.bind( self.showPreview, self ), 524 aspectRatio: self.options.aspectRatio, 525 setSelect: [ crop_left, crop_top, crop_right, crop_bottom ] 526 }, function() { 527 // Get the Jcrop API 528 bp.Avatar.jcropapi = this; 529 } ); 530 }, 531 532 cropAvatar: function( event ) { 533 event.preventDefault(); 534 535 bp.Avatar.setAvatar( this.model ); 536 }, 537 538 showPreview: function( coords ) { 539 if ( ! coords.w || ! coords.h ) { 540 return; 541 } 542 543 if ( parseInt( coords.w, 10 ) > 0 ) { 544 var fw = this.options.full_w; 545 var fh = this.options.full_h; 546 var rx = fw / coords.w; 547 var ry = fh / coords.h; 548 549 // Update the model 550 this.model.set( { x: coords.x, y: coords.y, w: coords.w, h: coords.h } ); 551 552 $( '#avatar-crop-preview' ).css( { 553 maxWidth:'none', 554 width: Math.round( rx * this.model.get( 'width' ) )+ 'px', 555 height: Math.round( ry * this.model.get( 'height' ) )+ 'px', 556 marginLeft: '-' + Math.round( rx * this.model.get( 'x' ) ) + 'px', 557 marginTop: '-' + Math.round( ry * this.model.get( 'y' ) ) + 'px' 558 } ); 559 } 560 } 561 } ); 562 563 // BuddyPress Avatar Feedback view 564 bp.Views.AvatarStatus = bp.View.extend( { 565 tagName: 'p', 566 className: 'updated', 567 id: 'bp-avatar-feedback', 568 569 initialize: function() { 570 this.el.className += ' ' + this.options.type; 571 this.value = this.options.value; 572 }, 573 574 render: function() { 575 this.$el.html( this.value ); 576 return this; 577 } 578 } ); 579 580 // BuddyPress Avatar Delete view 581 bp.Views.DeleteAvatar = bp.View.extend( { 582 tagName: 'div', 583 id: 'bp-delete-avatar', 584 template: bp.template( 'bp-avatar-delete' ), 585 586 events: { 587 'click #bp-delete-avatar': 'deleteAvatar' 588 }, 589 590 deleteAvatar: function( event ) { 591 event.preventDefault(); 592 593 bp.Avatar.deleteAvatar( this.model ); 594 } 595 } ); 596 597 bp.Avatar.start(); 598 599 })( bp, jQuery ); -
src/bp-core/js/bp-plupload.js
diff --git src/bp-core/js/bp-plupload.js src/bp-core/js/bp-plupload.js index e69de29..ce22622 100644
1 /* globals bp, plupload, BP_Uploader, _, JSON, Backbone */ 2 3 window.wp = window.wp || {}; 4 window.bp = window.bp || window.wp; 5 6 ( function( exports, $ ) { 7 8 // Bail if not set 9 if ( typeof BP_Uploader === 'undefined' ) { 10 return; 11 } 12 13 bp.Models = bp.Models || {}; 14 bp.Collections = bp.Collections || {}; 15 bp.Views = bp.Views || {}; 16 bp.Uploader = {}; 17 18 /** 19 * BuddyPress Uploader. 20 * 21 * This is an adapted version of wp.Uploader 22 */ 23 bp.Uploader.uploader = function() { 24 var self = this, 25 isIE = navigator.userAgent.indexOf('Trident/') !== -1 || navigator.userAgent.indexOf('MSIE ') !== -1; 26 27 this.params = BP_Uploader.settings; 28 this.strings = BP_Uploader.strings; 29 30 this.supports = { 31 upload: this.params.browser.supported 32 }; 33 34 this.supported = this.supports.upload; 35 36 if ( ! this.supported ) { 37 /*jshint -W020 */ 38 BP_Uploader = undefined; 39 return; 40 } 41 42 // Make sure flash sends cookies (seems in IE it does without switching to urlstream mode) 43 if ( ! isIE && 'flash' === plupload.predictRuntime( this.params.defaults ) && 44 ( ! this.params.defaults.required_features || ! this.params.defaults.required_features.hasOwnProperty( 'send_binary_string' ) ) ) { 45 46 this.params.defaults.required_features = this.params.defaults.required_features || {}; 47 this.params.defaults.required_features.send_binary_string = true; 48 } 49 50 this.uploader = new plupload.Uploader( this.params.defaults ); 51 52 /** 53 * After the Uploader has been initialized, initialize some behaviors for the dropzone. 54 * 55 * @event Init 56 * @param {plupload.Uploader} uploader Uploader instance. 57 */ 58 this.uploader.bind( 'Init', function( uploader ) { 59 var container = $( '#' + self.params.defaults.container ), 60 drop_element = $( '#' + self.params.defaults.drop_element ); 61 62 if ( 'html4' === uploader.runtime ) { 63 uploader.settings.multipart_params.html4 = true; 64 } 65 66 if ( uploader.features.dragdrop && ! self.params.browser.mobile ) { 67 container.addClass( 'drag-drop' ); 68 drop_element.bind( 'dragover.wp-uploader', function() { 69 container.addClass( 'drag-over' ); 70 } ).bind( 'dragleave.wp-uploader, drop.wp-uploader', function() { 71 container.removeClass( 'drag-over' ); 72 } ); 73 } else { 74 container.removeClass( 'drag-drop' ); 75 drop_element.unbind( '.wp-uploader' ); 76 } 77 78 } ); 79 80 // Init BuddyPress Uploader 81 this.uploader.init(); 82 83 /** 84 * Feedback callback. 85 * 86 * Add a new message to the errors collection, so it's possible 87 * to give some feedback to the user 88 * 89 * @param {string} message 90 * @param {object} data 91 * @param {plupload.File} file File that was uploaded. 92 */ 93 this.feedback = function( message, data, file ) { 94 if ( ! _.isNull( file ) && file.item ) { 95 file.item.clear(); 96 } 97 98 bp.Uploader.filesError.unshift( { 99 message: message, 100 data: data, 101 file: file 102 } ); 103 }; 104 105 /** 106 * After files were filtered and added to the queue, create a model for each. 107 * 108 * @event FilesAdded 109 * @param {plupload.Uploader} uploader Uploader instance. 110 * @param {Array} files Array of file objects that were added to queue by the user. 111 */ 112 this.uploader.bind( 'FilesAdded', function( uploader, files ) { 113 var hundredmb = 100 * 1024 * 1024, max = parseInt( uploader.settings.max_file_size, 10 ), 114 _this = this; 115 116 /** 117 * In case the multiple selection is false (eg: avatar) stop the process and send 118 * and event containing a warning 119 */ 120 if ( ! uploader.settings.multi_selection && files.length > 1 ) { 121 for ( var i in files ) { 122 uploader.removeFile( files[i] ); 123 } 124 125 $( self ).trigger( 'bp-uploader-warning', self.strings.unique_file_warning ); 126 return; 127 } 128 129 _.each( files, function( file ) { 130 var attributes; 131 132 // Ignore failed uploads. 133 if ( plupload.FAILED === file.status ) { 134 return; 135 } 136 137 if ( max > hundredmb && file.size > hundredmb && uploader.runtime !== 'html5' ) { 138 _this.uploadSizeError( uploader, file, true ); 139 } else { 140 attributes = _.extend( { 141 id: file.id, 142 file: file, 143 uploading: true, 144 date: new Date(), 145 filename: file.name 146 }, _.pick( file, 'loaded', 'size', 'percent' ) ); 147 148 file.item = new bp.Models.File( attributes ); 149 bp.Uploader.filesQueue.add( file.item ); 150 } 151 152 } ); 153 154 uploader.refresh(); 155 uploader.start(); 156 } ); 157 158 /** 159 * Update each file item on progress 160 * 161 * @event UploadProgress 162 * @param {plupload.Uploader} uploader Uploader instance. 163 * @param {Object} file 164 */ 165 this.uploader.bind( 'UploadProgress', function( uploader, file ) { 166 file.item.set( _.pick( file, 'loaded', 'percent' ) ); 167 } ); 168 169 /** 170 * After a file is successfully uploaded, update its model. 171 * 172 * @event FileUploaded 173 * @param {plupload.Uploader} uploader Uploader instance. 174 * @param {plupload.File} file File that was uploaded. 175 * @param {Object} response Object with response properties. 176 * @return {mixed} 177 */ 178 this.uploader.bind( 'FileUploaded', function( uploader, file, response ) { 179 var message = self.strings.default_error; 180 181 try { 182 response = JSON.parse( response.response ); 183 } catch ( e ) { 184 return self.feedback( message, e, file ); 185 } 186 187 if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) { 188 return self.feedback( message, null, file ); 189 } else if ( ! response.success ) { 190 if ( response.data && response.data.message ) { 191 message = response.data.message; 192 } 193 194 return self.feedback( message, response.data, file ); 195 } 196 197 _.each(['file','loaded','size','percent'], function( key ) { 198 file.item.unset( key ); 199 } ); 200 201 file.item.set( _.extend( response.data, { uploading: false } ) ); 202 203 // Add the file to the Uploaded ones 204 bp.Uploader.filesUploaded.add( file.item ); 205 206 } ); 207 208 /** 209 * Trigger an event to inform a new upload is being processed 210 * 211 * Mainly used to remove an eventual warning 212 * 213 * @event BeforeUpload 214 * @param {plupload.Uploader} uploader Uploader instance. 215 * @param {Array} files Array of file objects that were added to queue by the user. 216 */ 217 this.uploader.bind( 'BeforeUpload', function( uploader, files ) { 218 $( self ).trigger( 'bp-uploader-new-upload', uploader, files ); 219 } ); 220 221 /** 222 * Reset the filesQueue once the upload is complete 223 * 224 * @event BeforeUpload 225 * @param {plupload.Uploader} uploader Uploader instance. 226 * @param {Array} files Array of file objects that were added to queue by the user. 227 */ 228 this.uploader.bind( 'UploadComplete', function( uploader, files ) { 229 $( self ).trigger( 'bp-uploader-upload-complete', uploader, files ); 230 bp.Uploader.filesQueue.reset(); 231 } ); 232 233 /** 234 * Map Plupload errors & Create a warning when plupload failed 235 * 236 * @event Error 237 * @param {plupload.Uploader} uploader Uploader instance. 238 * @param {Object} pluploadError Plupload error 239 */ 240 this.uploader.bind( 'Error', function( uploader, pluploadError ) { 241 var message = self.strings.default_error, 242 key, 243 errors = { 244 'FAILED': self.strings.upload_failed, 245 'FILE_EXTENSION_ERROR': self.strings.invalid_filetype, 246 'IMAGE_FORMAT_ERROR': self.strings.not_an_image, 247 'IMAGE_MEMORY_ERROR': self.strings.image_memory_exceeded, 248 'IMAGE_DIMENSIONS_ERROR': self.strings.image_dimensions_exceeded, 249 'GENERIC_ERROR': self.strings.upload_failed, 250 'IO_ERROR': self.strings.io_error, 251 'HTTP_ERROR': self.strings.http_error, 252 'SECURITY_ERROR': self.strings.security_error, 253 'FILE_SIZE_ERROR': self.strings.file_exceeds_size_limit.replace( '%s' , pluploadError.file.name ) 254 }; 255 256 // Check for plupload errors. 257 for ( key in errors ) { 258 if ( pluploadError.code === plupload[ key ] ) { 259 message = errors[ key ]; 260 break; 261 } 262 } 263 264 $( self ).trigger( 'bp-uploader-warning', message ); 265 uploader.refresh(); 266 } ); 267 }; 268 269 // Create a very generic Model for files 270 bp.Models.File = Backbone.Model.extend( { 271 file: {} 272 } ); 273 274 // Add Collections to store queue, uploaded files and errors 275 $.extend( bp.Uploader, { 276 filesQueue : new Backbone.Collection(), 277 filesUploaded : new Backbone.Collection(), 278 filesError : new Backbone.Collection() 279 } ); 280 281 // Extend wp.Backbone.View with .prepare() and .inject() 282 bp.View = bp.Backbone.View.extend( { 283 inject: function( selector ) { 284 this.render(); 285 $(selector).html( this.el ); 286 this.views.ready(); 287 }, 288 289 prepare: function() { 290 if ( ! _.isUndefined( this.model ) && _.isFunction( this.model.toJSON ) ) { 291 return this.model.toJSON(); 292 } else { 293 return {}; 294 } 295 } 296 } ); 297 298 // BuddyPress Uploader main view 299 bp.Views.Uploader = bp.View.extend( { 300 className: 'bp-uploader-window', 301 template: bp.template( 'upload-window' ), 302 303 defaults: _.pick( BP_Uploader.settings.defaults, 'container', 'drop_element', 'browse_button' ), 304 305 initialize: function() { 306 this.warning = null; 307 this.model = new Backbone.Model( this.defaults ); 308 this.on( 'ready', this.initUploader ); 309 }, 310 311 initUploader: function() { 312 this.uploader = new bp.Uploader.uploader(); 313 $( this.uploader ).on( 'bp-uploader-warning', _.bind( this.setWarning, this ) ); 314 $( this.uploader ).on( 'bp-uploader-new-upload', _.bind( this.resetWarning, this ) ); 315 }, 316 317 setWarning: function( event, message ) { 318 if ( _.isUndefined( message ) ) { 319 return; 320 } 321 322 this.warning = new bp.Views.uploaderWarning( { 323 value: message 324 } ).render(); 325 326 this.$el.after( this.warning.el ); 327 }, 328 329 resetWarning: function() { 330 if ( _.isNull( this.warning ) ) { 331 return; 332 } 333 334 this.warning.remove(); 335 this.warning = null; 336 } 337 } ); 338 339 // BuddyPress Uploader warning view 340 bp.Views.uploaderWarning = bp.View.extend( { 341 tagName: 'p', 342 className: 'warning', 343 id: 'bp-uploader-warning', 344 345 initialize: function() { 346 this.value = this.options.value; 347 }, 348 349 render: function() { 350 this.$el.html( this.value ); 351 return this; 352 } 353 } ); 354 355 // BuddyPress Uploader Files view 356 bp.Views.uploaderStatus = bp.View.extend( { 357 className: 'files', 358 359 initialize: function() { 360 _.each( this.collection.models, this.addFile, this ); 361 this.collection.on( 'change:percent', this.progress, this ); 362 bp.Uploader.filesError.on( 'add', this.feedback, this ); 363 }, 364 365 addFile: function( file ) { 366 this.views.add( new bp.Views.uploaderProgress( { model: file } ) ); 367 }, 368 369 progress:function( model ) { 370 if ( ! _.isUndefined( model.get( 'percent' ) ) ) { 371 $( '#' + model.get('id') + ' .progress .bar' ).css( 'width', model.get('percent') + '%' ); 372 } 373 }, 374 375 feedback: function( model ) { 376 if ( ! _.isUndefined( model.get( 'message' ) ) && ! _.isUndefined( model.get( 'file' ) ) ) { 377 $( '#' + model.get( 'file' ).id ).html( model.get( 'message' ) ).addClass( 'error' ); 378 } 379 } 380 } ); 381 382 // BuddyPress Uploader File progress view 383 bp.Views.uploaderProgress = bp.View.extend( { 384 className: 'bp-uploader-progress', 385 template: bp.template( 'progress-window' ) 386 } ); 387 388 })( bp, jQuery ); -
src/bp-core/js/webcam.js
diff --git src/bp-core/js/webcam.js src/bp-core/js/webcam.js index e69de29..3d5f1e7 100644
1 /* globals bp, BP_Uploader, _, Backbone */ 2 3 window.bp = window.bp || {}; 4 5 ( function() { 6 7 // Bail if not set 8 if ( typeof BP_Uploader === 'undefined' ) { 9 return; 10 } 11 12 bp.Models = bp.Models || {}; 13 bp.Collections = bp.Collections || {}; 14 bp.Views = bp.Views || {}; 15 16 bp.WebCam = { 17 start: function() { 18 this.params = { 19 video: null, 20 videoStream: null, 21 capture_enable: false, 22 capture: null, 23 canvas: null, 24 warning: null 25 }; 26 27 bp.Avatar.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) ); 28 }, 29 30 setView: function( view ) { 31 if ( 'camera' !== view ) { 32 // Stop the camera if needed 33 if ( ! _.isNull( this.params.video ) ) { 34 this.stop(); 35 36 // Remove all warnings as we're changing the view 37 this.removeWarning(); 38 } 39 40 // Stop as this is not Camera area 41 return; 42 } 43 44 // Create the WebCam view 45 var cameraView = new bp.Views.WebCamAvatar( { model: new Backbone.Model( { user_media: false } ) } ); 46 47 // Add it to views 48 bp.Avatar.views.add( { id: 'camera', view: cameraView } ); 49 50 // Display it 51 cameraView.inject( '.bp-avatar' ); 52 }, 53 54 removeView: function() { 55 var camera; 56 57 if ( ! _.isUndefined( bp.Avatar.views.get( 'camera' ) ) ) { 58 camera = bp.Avatar.views.get( 'camera' ); 59 camera.get( 'view' ).remove(); 60 bp.Avatar.views.remove( { id: 'camera', view: camera } ); 61 } 62 }, 63 64 gotStream: function( stream ) { 65 var video = bp.WebCam.params.video; 66 bp.WebCam.params.videoStream = stream; 67 68 // User Feedback 69 bp.WebCam.displayWarning( 'loaded' ); 70 71 video.onerror = function () { 72 // User Feedback 73 bp.WebCam.displayWarning( 'videoerror' ); 74 75 if ( video ) { 76 bp.WebCam.stop(); 77 } 78 }; 79 80 stream.onended = bp.WebCam.noStream(); 81 82 if ( video.mozSrcObject !== undefined ) { 83 video.mozSrcObject = stream; 84 video.play(); 85 } else if ( navigator.mozGetUserMedia ) { 86 video.src = stream; 87 video.play(); 88 } else if ( window.URL ) { 89 video.src = window.URL.createObjectURL( stream ); 90 } else { 91 video.src = stream; 92 } 93 94 bp.WebCam.params.capture_enable = true; 95 }, 96 97 stop: function() { 98 bp.WebCam.params.capture_enable = false; 99 if ( bp.WebCam.params.videoStream ) { 100 if ( bp.WebCam.params.videoStream.stop ) { 101 bp.WebCam.params.videoStream.stop(); 102 } else if ( bp.WebCam.params.videoStream.msStop ) { 103 bp.WebCam.params.videoStream.msStop(); 104 } 105 bp.WebCam.params.videoStream.onended = null; 106 bp.WebCam.params.videoStream = null; 107 } 108 if ( bp.WebCam.params.video ) { 109 bp.WebCam.params.video.onerror = null; 110 bp.WebCam.params.video.pause(); 111 if ( bp.WebCam.params.video.mozSrcObject ) { 112 bp.WebCam.params.video.mozSrcObject = null; 113 } 114 bp.WebCam.params.video.src = ''; 115 } 116 }, 117 118 noStream: function() { 119 if ( _.isNull( bp.WebCam.params.videoStream ) ) { 120 // User Feedback 121 bp.WebCam.displayWarning( 'noaccess' ); 122 123 bp.WebCam.removeView(); 124 } 125 }, 126 127 setAvatar: function( avatar ) { 128 if ( ! avatar.get( 'url' ) ) { 129 bp.WebCam.displayWarning( 'nocapture' ); 130 } 131 132 // Remove the view 133 bp.WebCam.removeView(); 134 135 bp.Avatar.setAvatar( avatar ); 136 }, 137 138 removeWarning: function() { 139 if ( ! _.isNull( this.params.warning ) ) { 140 this.params.warning.remove(); 141 } 142 }, 143 144 displayWarning: function( code ) { 145 this.removeWarning(); 146 147 this.params.warning = new bp.Views.uploaderWarning( { 148 value: BP_Uploader.strings.camera_warnings[code] 149 } ); 150 151 this.params.warning.inject( '.bp-avatar-status' ); 152 } 153 }; 154 155 // BuddyPress WebCam view 156 bp.Views.WebCamAvatar = bp.View.extend( { 157 tagName: 'div', 158 id: 'bp-webcam-avatar', 159 template: bp.template( 'bp-avatar-webcam' ), 160 161 events: { 162 'click .avatar-webcam-capture': 'captureStream', 163 'click .avatar-webcam-save': 'saveCapture' 164 }, 165 166 initialize: function() { 167 var params; 168 169 if ( navigator.getUserMedia || navigator.oGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia ) { 170 171 // We need to add some cropping stuff to use bp.Avatar.setAvatar() 172 params = _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params, 173 'object', 174 'item_id', 175 'nonces' 176 ), { 177 user_media: true, 178 w: BP_Uploader.settings.crop.full_w, 179 h: BP_Uploader.settings.crop.full_h, 180 x: 0, 181 y: 0, 182 type: 'camera' 183 } 184 ); 185 186 this.model.set( params ); 187 } 188 189 this.on( 'ready', this.useStream, this ); 190 }, 191 192 useStream:function() { 193 // No support for user media... Stop! 194 if ( ! this.model.get( 'user_media' ) ) { 195 return; 196 } 197 198 this.options.video = new bp.Views.WebCamVideo(); 199 this.options.canvas = new bp.Views.WebCamCanvas(); 200 201 this.$el.find( '#avatar-to-crop' ).append( this.options.video.el ); 202 this.$el.find( '#avatar-crop-pane' ).append( this.options.canvas.el ); 203 204 bp.WebCam.params.video = this.options.video.el; 205 bp.WebCam.params.canvas = this.options.canvas.el; 206 207 // User Feedback 208 bp.WebCam.displayWarning( 'requesting' ); 209 210 if ( navigator.getUserMedia ) { 211 navigator.getUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCams.noStream ); 212 } else if ( navigator.oGetUserMedia ) { 213 navigator.oGetUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream ); 214 } else if ( navigator.mozGetUserMedia ) { 215 navigator.mozGetUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream ); 216 } else if ( navigator.webkitGetUserMedia ) { 217 navigator.webkitGetUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream ); 218 } else if (navigator.msGetUserMedia) { 219 navigator.msGetUserMedia( { video:true, audio:false }, bp.WebCams.gotStream, bp.WebCam.noStream ); 220 } else { 221 // User Feedback 222 bp.WebCam.displayWarning( 'errormsg' ); 223 } 224 }, 225 226 captureStream: function( event ) { 227 var sx, sc; 228 event.preventDefault(); 229 230 if ( ! bp.WebCam.params.capture_enable ) { 231 // User Feedback 232 bp.WebCam.displayWarning( 'loading' ); 233 return; 234 } 235 236 if ( this.model.get( 'h' ) > this.options.video.el.videoHeight || this.model.get( 'w' ) > this.options.video.el.videoWidth ) { 237 bp.WebCam.displayWarning( 'videoerror' ); 238 return; 239 } 240 241 // Set the offset 242 sc = this.options.video.el.videoHeight; 243 sx = ( this.options.video.el.videoWidth - sc ) / 2; 244 245 this.options.canvas.el.getContext( '2d' ).drawImage( this.options.video.el, sx, 0, sc, sc, 0, 0, this.model.get( 'w' ), this.model.get( 'h' ) ); 246 bp.WebCam.params.capture = this.options.canvas.el.toDataURL( 'image/png' ); 247 this.model.set( 'url', bp.WebCam.params.capture ); 248 249 // User Feedback 250 bp.WebCam.displayWarning( 'ready' ); 251 }, 252 253 saveCapture: function( event ) { 254 event.preventDefault(); 255 256 if ( ! bp.WebCam.params.capture ) { 257 // User Feedback 258 bp.WebCam.displayWarning( 'nocapture' ); 259 return; 260 } 261 262 bp.WebCam.stop(); 263 bp.WebCam.setAvatar( this.model ); 264 } 265 } ); 266 267 // BuddyPress Video stream view 268 bp.Views.WebCamVideo = bp.View.extend( { 269 tagName: 'video', 270 id: 'bp-webcam-video', 271 attributes: { 272 autoplay: 'autoplay' 273 } 274 } ); 275 276 // BuddyPress Canvas (capture) view 277 bp.Views.WebCamCanvas = bp.View.extend( { 278 tagName: 'canvas', 279 id: 'bp-webcam-canvas', 280 attributes: { 281 width: 150, 282 height: 150 283 }, 284 285 initialize: function() { 286 // Make sure to take in account bp_core_avatar_full_height or bp_core_avatar_full_width php filters 287 if ( ! _.isUndefined( BP_Uploader.settings.crop.full_h ) && ! _.isUndefined( BP_Uploader.settings.crop.full_w ) ) { 288 this.el.attributes.width.value = BP_Uploader.settings.crop.full_w; 289 this.el.attributes.height.value = BP_Uploader.settings.crop.full_h; 290 } 291 } 292 } ); 293 294 bp.WebCam.start(); 295 296 })( bp, jQuery ); -
src/bp-loader.php
diff --git src/bp-loader.php src/bp-loader.php index a4795df..86e7a11 100644
class BuddyPress { 437 437 require( $this->plugin_dir . 'bp-core/bp-core-theme-compatibility.php' ); 438 438 439 439 // Require all of the BuddyPress core libraries 440 require( $this->plugin_dir . 'bp-core/bp-core-dependency.php' ); 441 require( $this->plugin_dir . 'bp-core/bp-core-actions.php' ); 442 require( $this->plugin_dir . 'bp-core/bp-core-caps.php' ); 443 require( $this->plugin_dir . 'bp-core/bp-core-cache.php' ); 444 require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php' ); 445 require( $this->plugin_dir . 'bp-core/bp-core-update.php' ); 446 require( $this->plugin_dir . 'bp-core/bp-core-options.php' ); 447 require( $this->plugin_dir . 'bp-core/bp-core-classes.php' ); 448 require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php' ); 449 require( $this->plugin_dir . 'bp-core/bp-core-filters.php' ); 450 require( $this->plugin_dir . 'bp-core/bp-core-avatars.php' ); 451 require( $this->plugin_dir . 'bp-core/bp-core-widgets.php' ); 452 require( $this->plugin_dir . 'bp-core/bp-core-template.php' ); 453 require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php' ); 454 require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php' ); 455 require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php' ); 456 require( $this->plugin_dir . 'bp-core/bp-core-component.php' ); 457 require( $this->plugin_dir . 'bp-core/bp-core-functions.php' ); 458 require( $this->plugin_dir . 'bp-core/bp-core-moderation.php' ); 459 require( $this->plugin_dir . 'bp-core/bp-core-loader.php' ); 440 require( $this->plugin_dir . 'bp-core/bp-core-dependency.php' ); 441 require( $this->plugin_dir . 'bp-core/bp-core-actions.php' ); 442 require( $this->plugin_dir . 'bp-core/bp-core-caps.php' ); 443 require( $this->plugin_dir . 'bp-core/bp-core-cache.php' ); 444 require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php' ); 445 require( $this->plugin_dir . 'bp-core/bp-core-update.php' ); 446 require( $this->plugin_dir . 'bp-core/bp-core-options.php' ); 447 require( $this->plugin_dir . 'bp-core/bp-core-classes.php' ); 448 require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php' ); 449 require( $this->plugin_dir . 'bp-core/bp-core-filters.php' ); 450 require( $this->plugin_dir . 'bp-core/bp-core-attachments.php' ); 451 require( $this->plugin_dir . 'bp-core/bp-core-avatars.php' ); 452 require( $this->plugin_dir . 'bp-core/bp-core-widgets.php' ); 453 require( $this->plugin_dir . 'bp-core/bp-core-template.php' ); 454 require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php' ); 455 require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php' ); 456 require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php' ); 457 require( $this->plugin_dir . 'bp-core/bp-core-component.php' ); 458 require( $this->plugin_dir . 'bp-core/bp-core-functions.php' ); 459 require( $this->plugin_dir . 'bp-core/bp-core-moderation.php' ); 460 require( $this->plugin_dir . 'bp-core/bp-core-loader.php' ); 460 461 461 462 // Skip or load deprecated content 462 463 if ( false !== $this->load_deprecated ) { -
src/bp-members/admin/css/admin.css
diff --git src/bp-members/admin/css/admin.css src/bp-members/admin/css/admin.css index e4599f7..c780cf9 100644
div#community-profile-page li.bp-members-profile-stats:before, 25 25 div#community-profile-page li.bp-friends-profile-stats:before, 26 26 div#community-profile-page li.bp-groups-profile-stats:before, 27 27 div#community-profile-page li.bp-blogs-profile-stats:before, 28 div#community-profile-page a.bp-xprofile-avatar-user-admin:before { 28 div#community-profile-page a.bp-xprofile-avatar-user-admin:before, 29 div#community-profile-page a.bp-xprofile-avatar-user-edit:before { 29 30 font: normal 20px/1 'dashicons'; 30 31 speak: none; 31 32 display: inline-block; … … div#community-profile-page a.bp-xprofile-avatar-user-admin:before { 60 61 content:"\f182"; 61 62 } 62 63 64 div#community-profile-page a.bp-xprofile-avatar-user-edit:before { 65 content: "\f107"; 66 } 67 63 68 div#community-profile-page div#bp_xprofile_user_admin_avatar div.avatar { 64 69 width:150px; 65 70 margin:0 auto; -
src/bp-members/bp-members-admin.php
diff --git src/bp-members/bp-members-admin.php src/bp-members/bp-members-admin.php index 1226659..fbf807d 100644
class BP_Members_Admin { 217 217 * @return int 218 218 */ 219 219 private function get_user_id() { 220 $user_id = get_current_user_id(); 220 if ( ! empty( $this->user_id ) ) { 221 return $this->user_id; 222 } 223 224 $this->user_id = (int) get_current_user_id(); 221 225 222 // We'll need a user ID when not on the user admin226 // We'll need a user ID when not on self profile 223 227 if ( ! empty( $_GET['user_id'] ) ) { 224 $ user_id =$_GET['user_id'];228 $this->user_id = (int) $_GET['user_id']; 225 229 } 226 230 227 return intval( $user_id );231 return $this->user_id; 228 232 } 229 233 230 234 /** -
src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/camera.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/camera.php src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/camera.php index e69de29..267d433 100644
1 <?php 2 /** 3 * BuddyPress Avatars camera template 4 * 5 * This template is used to create the camera Backbone views 6 * 7 * @since 2.3 8 * 9 * @package BuddyPress 10 * @subpackage bp-attachments 11 */ 12 ?> 13 <script id="tmpl-bp-avatar-webcam" type="text/html"> 14 <# if ( ! data.user_media ) { #> 15 <div id="bp-webcam-message"> 16 <p class="warning"><?php esc_html_e( 'Your browser does not support the camera feature', 'buddypress' );?></p> 17 </div> 18 <# } else { #> 19 <div id="avatar-to-crop"></div> 20 <div id="avatar-crop-pane" class="avatar" style="width:{{data.w}}px; height:{{data.h}}px"></div> 21 <div id="avatar-crop-actions"> 22 <a class="button avatar-webcam-capture" href="#"><?php esc_html_e( 'Capture', 'buddypress' );?></a> 23 <a class="button avatar-webcam-save hide" href="#"><?php esc_html_e( 'Save', 'buddypress' );?></a> 24 </div> 25 <# } #> 26 </script> -
src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/crop.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/crop.php src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/crop.php index e69de29..086632c 100644
1 <?php 2 /** 3 * BuddyPress Avatars crop template 4 * 5 * This template is used to create the crop Backbone views 6 * 7 * @since 2.3 8 * 9 * @package BuddyPress 10 * @subpackage bp-attachments 11 */ 12 ?> 13 <script id="tmpl-bp-avatar-item" type="text/html"> 14 <div id="avatar-to-crop"> 15 <img src="{{data.url}}"/> 16 </div> 17 <div id="avatar-crop-pane" class="avatar" style="width:{{data.full_w}}px; height:{{data.full_h}}px"> 18 <img src="{{data.url}}" id="avatar-crop-preview"/> 19 </div> 20 <div id="avatar-crop-actions"> 21 <a class="button avatar-crop-submit" href="#"><?php esc_html_e( 'Crop Image', 'buddypress' ); ?></a> 22 </div> 23 </script> -
src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/index.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/index.php src/bp-templates/bp-legacy/buddypress/assets/_attachments/avatars/index.php index e69de29..82c401f 100644
1 <?php 2 /** 3 * BuddyPress Avatars main template 4 * 5 * This template is used to inject the BuddyPress Backbone views 6 * dealing with avatars. 7 * It's also used to create the common Backbone views 8 * 9 * @since 2.3 10 * 11 * @package BuddyPress 12 * @subpackage bp-attachments 13 */ 14 15 16 /** 17 * This action is for internal use, please do not use it 18 */ 19 do_action( 'bp_attachments_avatar_check_template' ); 20 ?> 21 <div class="bp-avatar-nav"></div> 22 <div class="bp-avatar"></div> 23 <div class="bp-avatar-status"></div> 24 25 <script type="text/html" id="tmpl-bp-avatar-nav"> 26 <a href="{{data.href}}" class="bp-avatar-nav-item" data-nav="{{data.id}}">{{data.name}}</a> 27 </script> 28 29 <?php bp_attachments_get_template_part( 'uploader' ); ?> 30 31 <?php bp_attachments_get_template_part( 'avatars/crop' ); ?> 32 33 <?php bp_attachments_get_template_part( 'avatars/camera' ); ?> 34 35 <script id="tmpl-bp-avatar-delete" type="text/html"> 36 <# if ( 'user' === data.object ) { #> 37 <p><?php _e( "If you'd like to delete your current profile photo but not upload a new one, please use the delete profile photo button.", 'buddypress' ); ?></p> 38 <p><a class="button edit" id="bp-delete-avatar" href="#" title="<?php esc_attr_e( 'Delete Profile Photo', 'buddypress' ); ?>"><?php esc_html_e( 'Delete My Profile Photo', 'buddypress' ); ?></a></p> 39 <# } else if ( 'group' === data.object ) { #> 40 <p><?php _e( "If you'd like to remove the existing group profile photo but not upload a new one, please use the delete group profile photo button.", 'buddypress' ); ?></p> 41 <p><a class="button edit" id="bp-delete-avatar" href="#" title="<?php esc_attr_e( 'Delete Group Profile Photo', 'buddypress' ); ?>"><?php esc_html_e( 'Delete Group Profile Photo', 'buddypress' ); ?></a></p> 42 <# } else { #> 43 <?php do_action( 'bp_attachments_avatar_delete_template' ); ?> 44 <# } #> 45 </script> 46 47 <?php do_action( 'bp_attachments_avatar_main_template' ); ?> -
src/bp-templates/bp-legacy/buddypress/assets/_attachments/uploader.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/_attachments/uploader.php src/bp-templates/bp-legacy/buddypress/assets/_attachments/uploader.php index e69de29..ebbc90f 100644
1 <?php 2 /** 3 * BuddyPress Uploader templates 4 * 5 * This template is used to create the BuddyPress Uploader Backbone views 6 * 7 * @since 2.3 8 * 9 * @package BuddyPress 10 * @subpackage bp-attachments 11 */ 12 ?> 13 <script type="text/html" id="tmpl-upload-window"> 14 <?php if ( ! _device_can_upload() ) : ?> 15 <h3 class="upload-instructions"><?php esc_html_e( 'The web browser on your device cannot be used to upload files.', 'buddypress' ); ?></h3> 16 <?php elseif ( is_multisite() && ! is_upload_space_available() ) : ?> 17 <h3 class="upload-instructions"><?php esc_html_e( 'Upload Limit Exceeded', 'buddypress' ); ?></h3> 18 <?php else : ?> 19 <div id="{{data.container}}"> 20 <div id="{{data.drop_element}}"> 21 <div class="drag-drop-inside"> 22 <p class="drag-drop-info"><?php esc_html_e( 'Drop your file here', 'buddypress' ); ?></p> 23 <p><?php _ex( 'or', 'Uploader: Drop your file here - or - Select your File', 'buddypress' ); ?></p> 24 <p class="drag-drop-buttons"><input id="{{data.browse_button}}" type="button" value="<?php esc_attr_e( 'Select your File', 'buddypress' ); ?>" class="button" /></p> 25 </div> 26 </div> 27 </div> 28 <?php endif; ?> 29 </script> 30 31 <script type="text/html" id="tmpl-progress-window"> 32 <div id="{{data.id}}"> 33 <div class="progress"> 34 <div class="bar"></div> 35 </div> 36 <div class="filename">{{data.filename}}</div> 37 </div> 38 </script> -
src/bp-templates/bp-legacy/buddypress/groups/create.php
diff --git src/bp-templates/bp-legacy/buddypress/groups/create.php src/bp-templates/bp-legacy/buddypress/groups/create.php index 5741f10..fd2f31e 100644
60 60 61 61 62 62 <label> 63 <input type="radio" name="group-status" value="private"<?php if ( 'private' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> /> 63 <input type="radio" name="group-status" value="private"<?php if ( 'private' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> /> 64 64 <strong><?php _e( 'This is a private group', 'buddypress' ); ?></strong> 65 65 </label> 66 66 <ul> … … 71 71 72 72 73 73 <label> 74 <input type="radio" name="group-status" value="hidden"<?php if ( 'hidden' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> /> 74 <input type="radio" name="group-status" value="hidden"<?php if ( 'hidden' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> /> 75 75 <strong><?php _e('This is a hidden group', 'buddypress' ); ?></strong> 76 76 </label> 77 77 <ul> … … 153 153 <p><?php _e( 'To skip the group profile photo upload process, hit the "Next Step" button.', 'buddypress' ); ?></p> 154 154 </div><!-- .main-column --> 155 155 156 <?php 157 /** 158 * Load the Avatar UI templates 159 * 160 * @since BuddyPress (2.3.0) 161 */ 162 bp_avatar_get_templates(); ?> 163 156 164 <?php endif; ?> 157 165 158 166 <?php if ( 'crop-image' == bp_get_avatar_admin_step() ) : ?> … … 306 314 307 315 </div> 308 316 309 <?php do_action( 'bp_after_create_group_page' ); ?> 310 No newline at end of file 317 <?php do_action( 'bp_after_create_group_page' ); ?> -
src/bp-templates/bp-legacy/buddypress/groups/single/admin.php
diff --git src/bp-templates/bp-legacy/buddypress/groups/single/admin.php src/bp-templates/bp-legacy/buddypress/groups/single/admin.php index a5811ff..316f9f7 100644
140 140 141 141 <?php endif; ?> 142 142 143 <?php 144 /** 145 * Load the Avatar UI templates 146 * 147 * @since BuddyPress (2.3.0) 148 */ 149 bp_avatar_get_templates(); ?> 150 143 151 <?php wp_nonce_field( 'bp_avatar_upload' ); ?> 144 152 145 153 <?php endif; ?> -
src/bp-templates/bp-legacy/buddypress/members/single/profile/change-avatar.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/profile/change-avatar.php src/bp-templates/bp-legacy/buddypress/members/single/profile/change-avatar.php index f2a3060..71b1563 100644
50 50 51 51 </form> 52 52 53 <?php 54 /** 55 * Load the Avatar UI templates 56 * 57 * @since BuddyPress (2.3.0) 58 */ 59 bp_avatar_get_templates(); ?> 60 53 61 <?php else : ?> 54 62 55 63 <p><?php _e( 'Your profile photo will be used on your profile and throughout the site. To change your profile photo, please create an account with <a href="http://gravatar.com">Gravatar</a> using the same email address as you used to register with this site.', 'buddypress' ); ?></p> -
src/bp-xprofile/bp-xprofile-admin.php
diff --git src/bp-xprofile/bp-xprofile-admin.php src/bp-xprofile/bp-xprofile-admin.php index 8f2ff63..a816b69 100644
class BP_XProfile_User_Admin { 673 673 * @since BuddyPress (2.0.0) 674 674 */ 675 675 private function setup_actions() { 676 // Enqueue scripts 677 add_action( 'bp_members_admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10, 1 ); 676 678 677 679 // Register the metabox in Member's community admin profile 678 680 add_action( 'bp_members_admin_xprofile_metabox', array( $this, 'register_metaboxes' ), 10, 3 ); … … class BP_XProfile_User_Admin { 682 684 } 683 685 684 686 /** 687 * Enqueue needed scripts. 688 * 689 * @access public 690 * @since BuddyPress (2.3.0) 691 */ 692 public function enqueue_scripts( $screen_id ) { 693 if ( false === strpos( $screen_id, 'users_page_bp-profile-edit' ) && false === strpos( $screen_id, 'profile_page_bp-profile-edit' ) ) { 694 return; 695 } 696 697 /** 698 * Get Thickbox 699 * 700 * We cannot simply use add_thickbox() here as WordPress is not playing 701 * nice with Thickbox width/height see https://core.trac.wordpress.org/ticket/17249 702 * Using media-upload might be interesting in the future for the send to editor stuff 703 * and we make sure the tb_window is wide enougth 704 */ 705 wp_enqueue_style ( 'thickbox' ); 706 wp_enqueue_script( 'media-upload' ); 707 708 // Get Avatar Uploader 709 bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' ); 710 } 711 712 /** 685 713 * Register the xProfile metabox on Community Profile admin page. 686 714 * 687 715 * @access public … … class BP_XProfile_User_Admin { 1039 1067 1040 1068 <?php endif; ?> 1041 1069 1070 <?php // Avatar Editor ;?> 1071 <a href="#TB_inline?width=800px&height=400px&inlineId=bp-xprofile-avatar-editor" title="<?php esc_attr_e( 'Edit Profile Photo', 'buddypress' );?>" class="thickbox bp-xprofile-avatar-user-edit"><?php esc_html_e( 'Edit Profile Photo', 'buddypress' ); ?></a> 1072 <div id="bp-xprofile-avatar-editor" style="display:none;"> 1073 <?php bp_attachments_get_template_part( 'avatars/index' ); ?> 1074 </div> 1075 1042 1076 </div> 1043 1077 <?php 1044 1078 }