Skip to:
Content

BuddyPress.org

Ticket #6290: 6290.03.patch

File 6290.03.patch, 85.4 KB (added by imath, 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..2fbbbdf 100644
     
     1<?php
     2/**
     3 * BuddyPress Attachments functions.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Attachments
     7 */
     8
     9// Exit if accessed directly
     10defined( 'ABSPATH' ) || exit;
     11
     12/**
     13 * Get the BuddyPress Plupload settings
     14 *
     15 * @since  BuddyPress (2.3.0)
     16 *
     17 * @uses  apply_filters() call 'bp_attachments_get_plupload_default_settings' to override the settings
     18 * @return array list of BuddyPress Plupload settings
     19 */
     20function bp_attachments_get_plupload_default_settings() {
     21
     22        $max_upload_size = wp_max_upload_size();
     23
     24        if ( ! $max_upload_size ) {
     25                $max_upload_size = 0;
     26        }
     27
     28        $defaults = array(
     29                'runtimes'            => 'html5,flash,silverlight,html4',
     30                'file_data_name'      => 'file',
     31                'multipart_params'    => array(
     32                        'action'          => 'bp_upload_attachment',
     33                        '_wpnonce'        => wp_create_nonce( 'bp-uploader' ),
     34                ),
     35                'url'                 => admin_url( 'admin-ajax.php', 'relative' ),
     36                'flash_swf_url'       => includes_url( 'js/plupload/plupload.flash.swf' ),
     37                'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
     38                'filters' => array(
     39                        'max_file_size'   => $max_upload_size . 'b',
     40                ),
     41                'multipart'           => true,
     42                'urlstream_upload'    => true,
     43        );
     44
     45        // WordPress is not allowing multi selection for iOs 7 device.. See #29602.
     46        if ( wp_is_mobile() && strpos( $_SERVER['HTTP_USER_AGENT'], 'OS 7_' ) !== false &&
     47                strpos( $_SERVER['HTTP_USER_AGENT'], 'like Mac OS X' ) !== false ) {
     48
     49                $defaults['multi_selection'] = false;
     50        }
     51
     52        $settings = array(
     53                'defaults' => $defaults,
     54                'browser'  => array(
     55                        'mobile'    => wp_is_mobile(),
     56                        'supported' => _device_can_upload(),
     57                ),
     58                'limitExceeded' => is_multisite() && ! is_upload_space_available(),
     59        );
     60
     61        /**
     62         * Filter the BuddyPress Plupload default settings.
     63         *
     64         * @since 2.3.0
     65         *
     66         * @param array $params Default Plupload parameters array.
     67         */
     68        return apply_filters( 'bp_attachments_get_plupload_default_settings', $settings );
     69}
     70
     71/**
     72 * Builds localization strings for the BuddyPress Uploader scripts
     73 *
     74 * @since  BuddyPress (2.3.0)
     75 *
     76 * @uses  apply_filters() call 'bp_attachments_get_plupload_l10n' to override the settings
     77 * @return array Plupload default localization strings
     78 */
     79function bp_attachments_get_plupload_l10n() {
     80        // Localization strings
     81        return apply_filters( 'bp_attachments_get_plupload_l10n', array(
     82                        'queue_limit_exceeded'      => __( 'You have attempted to queue too many files.', 'buddypress' ),
     83                        'file_exceeds_size_limit'   => __( '%s exceeds the maximum upload size for this site.', 'buddypress' ),
     84                        'zero_byte_file'            => __( 'This file is empty. Please try another.', 'buddypress' ),
     85                        'invalid_filetype'          => __( 'This file type is not allowed. Please try another.', 'buddypress' ),
     86                        'not_an_image'              => __( 'This file is not an image. Please try another.', 'buddypress' ),
     87                        'image_memory_exceeded'     => __( 'Memory exceeded. Please try another smaller file.', 'buddypress' ),
     88                        'image_dimensions_exceeded' => __( 'This is larger than the maximum size. Please try another.', 'buddypress' ),
     89                        'default_error'             => __( 'An error occurred. Please try again later.', 'buddypress' ),
     90                        'missing_upload_url'        => __( 'There was a configuration error. Please contact the server administrator.', 'buddypress' ),
     91                        'upload_limit_exceeded'     => __( 'You may only upload 1 file.', 'buddypress' ),
     92                        'http_error'                => __( 'HTTP error.', 'buddypress' ),
     93                        'upload_failed'             => __( 'Upload failed.', 'buddypress' ),
     94                        'big_upload_failed'         => __( 'Please try uploading this file with the %1$sbrowser uploader%2$s.', 'buddypress' ),
     95                        'big_upload_queued'         => __( '%s exceeds the maximum upload size for the multi-file uploader when used in your browser.', 'buddypress' ),
     96                        'io_error'                  => __( 'IO error.', 'buddypress' ),
     97                        'security_error'            => __( 'Security error.', 'buddypress' ),
     98                        'file_cancelled'            => __( 'File canceled.', 'buddypress' ),
     99                        'upload_stopped'            => __( 'Upload stopped.', 'buddypress' ),
     100                        'dismiss'                   => __( 'Dismiss', 'buddypress' ),
     101                        'crunching'                 => __( 'Crunching&hellip;', 'buddypress' ),
     102                        'unique_file_warning'       => __( 'Make sure to upload a unique file', 'buddypress' ),
     103                        'error_uploading'           => __( '&#8220;%s&#8221; has failed to upload.', 'buddypress' )
     104        ) );
     105}
     106
     107/**
     108 * Enqueues the script needed for the Uploader UI
     109 *
     110 * @see  BP_Attachment::script_data() && BP_Attachment_Avatar::script_data() for examples showing how
     111 * to set specific script data
     112 *
     113 * @since  BuddyPress (2.3.0)
     114 *
     115 * @param  string $class name of the class extending BP_Attachment (eg: BP_Attachment_Avatar)
     116 */
     117function bp_attachments_enqueue_scripts( $class = '' ) {
     118        // Enqueue me just once per page, please.
     119        if ( did_action( 'bp_attachments_enqueue_scripts' ) ) {
     120                return;
     121        }
     122
     123        if ( empty( $class ) || ! class_exists( $class ) ) {
     124                return new WP_Error( 'missing_parameter' );
     125        }
     126
     127        // Get an instance of the class and get the script data
     128        $attachment = new $class;
     129        $script_data  = $attachment->script_data();
     130
     131        $args = bp_parse_args( $script_data, array(
     132                'action'            => '',
     133                'file_data_name'    => '',
     134                'max_file_size'     => 0,
     135                'browse_button'     => 'bp-browse-button',
     136                'container'         => 'bp-upload-ui',
     137                'drop_element'      => 'drag-drop-area',
     138                'bp_params'         => array(),
     139                'extra_css'         => array(),
     140                'extra_js'          => array(),
     141                'feedback_messages' => array(),
     142        ), 'attachments_enqueue_scripts' );
     143
     144        if ( empty( $args['action'] ) || empty( $args['file_data_name'] ) ) {
     145                return new WP_Error( 'missing_parameter' );
     146        }
     147
     148        // Get the BuddyPress uploader strings
     149        $strings = bp_attachments_get_plupload_l10n();
     150
     151        // Get the BuddyPress uploader settings
     152        $settings = bp_attachments_get_plupload_default_settings();
     153
     154        // Set feedback messages
     155        if ( ! empty( $args['feedback_messages'] ) ) {
     156                $strings['feedback_messages'] = $args['feedback_messages'];
     157        }
     158
     159        // Use a temporary var to ease manipulation
     160        $defaults = $settings['defaults'];
     161
     162        // Set the upload action
     163        $defaults['multipart_params']['action'] = $args['action'];
     164
     165        // Set BuddyPress upload parameters if provided
     166        if ( ! empty( $args['bp_params'] ) ) {
     167                $defaults['multipart_params']['bp_params'] = $args['bp_params'];
     168        }
     169
     170        // Merge other arguments
     171        $ui_args = array_intersect_key( $args, array(
     172                'file_data_name' => true,
     173                'browse_button'  => true,
     174                'container'      => true,
     175                'drop_element'   => true,
     176        ) );
     177
     178        $defaults = array_merge( $defaults, $ui_args );
     179
     180        if ( ! empty( $args['max_file_size'] ) ) {
     181                $defaults['filters']['max_file_size'] = $args['max_file_size'] . 'b';
     182        }
     183
     184        // Specific to BuddyPress Avatars
     185        if ( 'bp_avatar_upload' == $defaults['multipart_params']['action'] ) {
     186
     187                // Include the cropping informations for avatars
     188                $settings['crop'] = array(
     189                        'full_h'  => bp_core_avatar_full_height(),
     190                        'full_w'  => bp_core_avatar_full_width(),
     191                );
     192
     193                // Avatar only need 1 file and 1 only!
     194                $defaults['multi_selection'] = false;
     195
     196                // Init the Avatar nav
     197                $avatar_nav = array( 'upload' => array( 'id' => 'upload', 'caption' => __( 'Upload', 'buddypress' ), 'order' => 0  ) );
     198
     199                // Use this filter to disable the Webcam Avatar feature
     200                if ( false !== apply_filters( 'bp_attachment_avatar_use_webcam', true ) && 'user' == $defaults['multipart_params']['bp_params']['object'] ) {
     201                        $avatar_nav['camera'] = array( 'id' => 'camera', 'caption' => __( 'Camera', 'buddypress' ), 'order' => 10 );
     202
     203                        // Set warning messages
     204                        $strings['camera_warnings'] = array(
     205                                'requesting'  => __( 'Requesting video stream, please authorize this website to access to your camera.', 'buddypress'),
     206                                'loading'     => __( 'Please wait for the video to load.', 'buddypress' ),
     207                                'loaded'      => __( 'Video stream loaded. You can use the capture button to display the avatar preview.', 'buddypress' ),
     208                                'noaccess'    => __( 'You denied this website to access to your camera. Please use the upload form.', 'buddypress' ),
     209                                'errormsg'    => __( 'Your browser is not supported. Please use the upload form.', 'buddypress' ),
     210                                'videoerror'  => __( 'Video error. Please use the upload form.', 'buddypress' ),
     211                                'ready'       => __( 'Avatar ready, use the save button to validate.', 'buddypress' ),
     212                                'nocapture'   => __( 'No avatar was captured, please use the capture button first.', 'buddypress' ),
     213                        );
     214                }
     215
     216                if ( ! empty( $defaults['multipart_params']['bp_params']['has_avatar'] ) ) {
     217                        $avatar_nav['delete'] = array( 'id' => 'delete', 'caption' => __( 'Delete', 'buddypress' ), 'order' => 100  );
     218                }
     219
     220                $settings['nav'] = bp_sort_by_key( apply_filters( 'bp_attachments_avatar_nav', $avatar_nav ), 'order', 'num' );
     221        }
     222
     223        // Set Plupload settings
     224        $settings['defaults'] = $defaults;
     225
     226        /**
     227         * Enqueue some extra styles if required
     228         *
     229         * Extra styles need to be registered.
     230         */
     231        if ( ! empty( $args['extra_css'] ) ) {
     232                foreach ( (array) $args['extra_css'] as $css ) {
     233                        if ( empty( $css ) ) {
     234                                continue;
     235                        }
     236
     237                        wp_enqueue_style( $css );
     238                }
     239        }
     240
     241        wp_enqueue_script ( 'bp-plupload' );
     242        wp_localize_script( 'bp-plupload', 'BP_Uploader', array( 'strings' => $strings, 'settings' => $settings ) );
     243
     244        /**
     245         * Enqueue some extra scripts if required
     246         *
     247         * Extra scripts need to be registered.
     248         */
     249        if ( ! empty( $args['extra_js'] ) ) {
     250                foreach ( (array) $args['extra_js'] as $js ) {
     251                        if ( empty( $js ) ) {
     252                                continue;
     253                        }
     254
     255                        wp_enqueue_script( $js );
     256                }
     257        }
     258
     259        /**
     260         * Fires at the conclusion of bp_attachments_enqueue_scripts()
     261         * to avoid the scripts to be loaded more than once.
     262         *
     263         * @since BuddyPress 2.3.0
     264         */
     265        do_action( 'bp_attachments_enqueue_scripts' );
     266}
  • src/bp-core/bp-core-avatars.php

    diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php
    index 44fe3c3..13d09de 100644
    function bp_core_delete_existing_avatar( $args = '' ) { 
    553553}
    554554
    555555/**
     556 * Ajax delete an avatar for a given object and item id
     557 *
     558 * @since  BuddyPress (2.3.0)
     559 *
     560 * @uses    bp_core_delete_existing_avatar()
     561 * @return  string a json object containing success data if the avatar was deleted
     562 *                 error message otherwise
     563 */
     564function bp_core_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_is_item_admin() && ! bp_current_user_can( 'bp_moderate' ) ) {
     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' => 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}
     609add_action( 'wp_ajax_bp_avatar_delete', 'bp_core_avatar_ajax_delete' );
     610
     611/**
    556612 * Handle avatar uploading.
    557613 *
    558614 * The functions starts off by checking that the file has been uploaded
    function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
    625681}
    626682
    627683/**
     684 * Ajax upload an avatar
     685 *
     686 * @since BuddyPress (2.3.0)
     687 *
     688 * @uses  bp_core_avatar_handle_upload()
     689 * @uses  apply_filters() call 'bp_core_avatar_ajax_upload_params' if you need to ajax set
     690 *                        avatars for another component (eg: blavatar)
     691 * @return  string a json object containing success data if the upload succeeded
     692 *                 error message otherwise
     693 */
     694function bp_core_avatar_ajax_upload() {
     695        // Bail if not a POST action
     696        if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
     697                wp_send_json_error();
     698        }
     699
     700        // Check the nonce
     701        check_admin_referer( 'bp-uploader' );
     702
     703        // Capability check
     704        if ( ! bp_is_item_admin() && ! bp_current_user_can( 'bp_moderate' ) && ! bp_is_group_create() ) {
     705                wp_send_json_error();
     706        }
     707
     708        // Init the BuddyPress parameters
     709        $bp_params = array();
     710
     711        // We need it to carry on
     712        if ( ! empty( $_POST['bp_params' ] ) ) {
     713                $bp_params = $_POST['bp_params' ];
     714        } else {
     715                wp_send_json_error();
     716        }
     717
     718        // We need the object to set the uploads dir filter
     719        if ( empty( $bp_params['object'] ) ) {
     720                wp_send_json_error();
     721        }
     722
     723        $bp = buddypress();
     724        $bp_params['upload_dir_filter'] = '';
     725        $needs_reset = array();
     726
     727        if ( 'user' == $bp_params['object'] && bp_is_active( 'xprofile' ) ) {
     728                $bp_params['upload_dir_filter'] = 'xprofile_avatar_upload_dir';
     729
     730                if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) {
     731                        $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user );
     732                        $bp->displayed_user->id = $bp_params['item_id'];
     733                }
     734        } else if ( 'group' == $bp_params['object'] && bp_is_active( 'groups' ) ) {
     735                $bp_params['upload_dir_filter'] = 'groups_avatar_upload_dir';
     736
     737                if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
     738                        $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
     739                        $bp->groups->current_group = groups_get_group( array(
     740                                'group_id'        => $bp_params['item_id'],
     741                                'populate_extras' => false,
     742                        ) );
     743                }
     744        } else {
     745                /**
     746                 * Filter here to deal with other components
     747                 *
     748                 * @since BuddyPress (2.3.0)
     749                 *
     750                 * @var array $bp_params the BuddyPress Ajax parameters
     751                 */
     752                $bp_params = apply_filters( 'bp_core_avatar_ajax_upload_params', $bp_params );
     753        }
     754
     755        if ( ! isset( $bp->avatar_admin ) ) {
     756                $bp->avatar_admin = new stdClass();
     757        }
     758
     759        // Upload the avatar
     760        $avatar = bp_core_avatar_handle_upload( $_FILES, $bp_params['upload_dir_filter'] );
     761
     762        // Reset objects
     763        if ( ! empty( $needs_reset ) ) {
     764                if ( ! empty( $needs_reset['component'] ) ) {
     765                        $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value'];
     766                } else {
     767                        $bp->{$needs_reset['key']} = $needs_reset['value'];
     768                }
     769        }
     770
     771        // Intercept the template message and remove it
     772        if ( empty( $avatar ) ) {
     773                $message = $bp->template_message;
     774
     775                // Remove template message.
     776                $bp->template_message      = false;
     777                $bp->template_message_type = false;
     778                @setcookie( 'bp-message', false, time() - 1000, COOKIEPATH );
     779                @setcookie( 'bp-message-type', false, time() - 1000, COOKIEPATH );
     780
     781                wp_send_json_error(array(
     782                        'type' => 'upload_error',
     783                        'message' => $message,
     784                ) );
     785        }
     786
     787        if ( empty( $bp->avatar_admin->image->file ) ) {
     788                wp_send_json_error();
     789        }
     790
     791        $uploaded_image = @getimagesize( $bp->avatar_admin->image->file );
     792
     793        // Set the name of the file
     794        $name = $_FILES['file']['name'];
     795        $name_parts = pathinfo( $name );
     796        $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) );
     797
     798        if ( 'user' == $bp_params['object'] ) {
     799                do_action( 'xprofile_avatar_uploaded' );
     800        }
     801
     802        // Finally return the avatar to the editor
     803        wp_send_json_success( array(
     804                'name'      => $name,
     805                'url'       => $bp->avatar_admin->image->url,
     806                'width'     => $uploaded_image[0],
     807                'height'    => $uploaded_image[1],
     808        ) );
     809}
     810add_action( 'wp_ajax_bp_avatar_upload', 'bp_core_avatar_ajax_upload' );
     811
     812 /**
     813 * Handle avatar webcam capture.
     814 *
     815 * @since BuddyPress (2.3.0)
     816 *
     817 * @param string $data base64 encoded image.
     818 * @param int $item_id.
     819 * @return bool True on success, false on failure.
     820 */
     821function bp_core_avatar_handle_capture( $data = '', $item_id = 0 ) {
     822        if ( empty( $data ) || empty( $item_id ) ) {
     823                return false;
     824        }
     825
     826        $avatar_dir = bp_core_avatar_upload_path() . '/avatars';
     827
     828        // It's not a regular upload, we may need to create this folder
     829        if ( ! file_exists( $avatar_dir ) ) {
     830                if ( ! wp_mkdir_p( $avatar_dir ) ) {
     831                        return false;
     832                }
     833        }
     834
     835        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $avatar_dir . '/' . $item_id, $item_id, 'user', 'avatars' );
     836
     837        // It's not a regular upload, we may need to create this folder
     838        if( ! file_exists( $avatar_folder_dir ) ) {
     839                if ( ! wp_mkdir_p( $avatar_folder_dir ) ) {
     840                        return false;
     841                }
     842        }
     843
     844        $original_file = $avatar_folder_dir . '/webcam-capture-' . $item_id . '.png';
     845
     846        if ( file_put_contents( $original_file, $data ) ) {
     847                $avatar_to_crop = str_replace( bp_core_avatar_upload_path(), '', $original_file );
     848
     849                // Crop to default values
     850                $crop_args = array( 'item_id' => $item_id, 'original_file' => $avatar_to_crop, 'crop_x' => 0, 'crop_y' => 0 );
     851
     852                do_action( 'xprofile_avatar_uploaded' );
     853
     854                return bp_core_avatar_handle_crop( $crop_args );
     855        } else {
     856                return false;
     857        }
     858}
     859
     860/**
    628861 * Crop an uploaded avatar.
    629862 *
    630863 * $args has the following parameters:
    function bp_core_avatar_handle_crop( $args = '' ) { 
    689922}
    690923
    691924/**
     925 * Ajax set an avatar for a given object and item id
     926 *
     927 * @since BuddyPress (2.3.0)
     928 *
     929 * @uses  bp_core_avatar_handle_capture()
     930 * @uses  bp_core_avatar_handle_crop()
     931 * @return  string a json object containing success data if the crop/capture succeeded
     932 *                 error message otherwise
     933 */
     934function bp_core_avatar_ajax_set() {
     935        // Bail if not a POST action
     936        if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
     937                wp_send_json_error();
     938        }
     939
     940        // Check the nonce
     941        check_admin_referer( 'bp_avatar_cropstore', 'nonce' );
     942
     943        // Capability check
     944        if ( ! bp_is_item_admin() && ! bp_current_user_can( 'bp_moderate' ) && ! bp_is_group_create() ) {
     945                wp_send_json_error();
     946        }
     947
     948        $avatar_data = wp_parse_args( $_POST, array(
     949                'crop_w' => bp_core_avatar_full_width(),
     950                'crop_h' => bp_core_avatar_full_height(),
     951                'crop_x' => 0,
     952                'crop_y' => 0
     953        ) );
     954
     955        if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) || empty( $avatar_data['original_file'] ) ) {
     956                wp_send_json_error();
     957        }
     958
     959        if ( ! empty( $avatar_data['type'] ) && 'camera' == $avatar_data['type'] && 'user' == $avatar_data['object'] ) {
     960                $webcam_avatar = false;
     961
     962                if ( ! empty( $avatar_data['original_file'] ) ) {
     963                        $webcam_avatar = str_replace( array( 'data:image/png;base64,', ' ' ), array( '', '+' ), $avatar_data['original_file'] );
     964                        $webcam_avatar = base64_decode( $webcam_avatar );
     965                }
     966
     967                if ( ! bp_core_avatar_handle_capture( $webcam_avatar, $avatar_data['item_id'] ) ) {
     968                        wp_send_json_error( array(
     969                                'feedback_code' => 1
     970                        ) );
     971
     972                } else {
     973                        $return = array(
     974                                'avatar' => bp_core_fetch_avatar( array(
     975                                        'object'  => $avatar_data['object'],
     976                                        'item_id' => $avatar_data['item_id'],
     977                                        'html'    => false,
     978                                        'type'    => 'full',
     979                                ) ),
     980                                'feedback_code' => 2,
     981                                'item_id'       => $avatar_data['item_id'],
     982                        );
     983
     984                        do_action( 'xprofile_screen_change_avatar' );
     985
     986                        wp_send_json_success( $return );
     987                }
     988
     989                return;
     990        }
     991
     992        $original_file = str_replace( bp_core_avatar_url(), '', $avatar_data['original_file'] );
     993
     994        // Set avatars dir & feedback part
     995        if ( 'user' == $avatar_data['object'] ) {
     996                $avatar_dir = 'avatars';
     997
     998        // Defaults to object-avatars dir
     999        } else {
     1000                $avatar_dir = sanitize_key( $avatar_data['object'] ) . '-avatars';
     1001        }
     1002
     1003        // Crop args
     1004        $r = array(
     1005                'item_id'       => $avatar_data['item_id'],
     1006                'object'        => $avatar_data['object'],
     1007                'avatar_dir'    => $avatar_dir,
     1008                'original_file' => $original_file,
     1009                'crop_w'        => $avatar_data['crop_w'],
     1010                'crop_h'        => $avatar_data['crop_h'],
     1011                'crop_x'        => $avatar_data['crop_x'],
     1012                'crop_y'        => $avatar_data['crop_y']
     1013        );
     1014
     1015        // Handle crop
     1016        if ( bp_core_avatar_handle_crop( $r ) ) {
     1017                $return = array(
     1018                        'avatar' => bp_core_fetch_avatar( array(
     1019                                'object'  => $avatar_data['object'],
     1020                                'item_id' => $avatar_data['item_id'],
     1021                                'html'    => false,
     1022                                'type'    => 'full',
     1023                        ) ),
     1024                        'feedback_code' => 2,
     1025                        'item_id'       => $avatar_data['item_id'],
     1026                );
     1027
     1028                if ( 'user' == $avatar_data['object'] ) {
     1029                        do_action( 'xprofile_screen_change_avatar' );
     1030                }
     1031
     1032                wp_send_json_success( $return );
     1033        } else {
     1034                wp_send_json_error( array(
     1035                        'feedback_code' => 1,
     1036                ) );
     1037        }
     1038}
     1039add_action( 'wp_ajax_bp_avatar_set', 'bp_core_avatar_ajax_set' );
     1040
     1041/**
    6921042 * Replace default WordPress avatars with BP avatars, if available.
    6931043 *
    6941044 * Filters 'get_avatar'.
    function bp_core_avatar_reset_query( $posts_query = null ) { 
    10981448        }
    10991449}
    11001450add_action( 'bp_parse_query', 'bp_core_avatar_reset_query', 10, 1 );
     1451
     1452/**
     1453 * Checks whether Avatar UI should be loaded
     1454 *
     1455 * @since  BuddyPress (2.3.0)
     1456 *
     1457 * @uses   bp_is_user_change_avatar()
     1458 * @uses   bp_get_avatar_admin_step()
     1459 * @uses   bp_is_active()
     1460 * @uses   bp_is_group_create()
     1461 * @uses   bp_is_group_creation_step()
     1462 * @uses   bp_is_group_admin_page()
     1463 * @uses   bp_is_group_admin_screen()
     1464 * @return bool True if Avatar UI should load, false otherwise
     1465 */
     1466function bp_core_avatar_is_front_edit_avatar() {
     1467        $retval = false;
     1468
     1469        if ( bp_is_user_change_avatar() && 'crop-image' != bp_get_avatar_admin_step() ) {
     1470                $retval = true;
     1471        }
     1472
     1473        if ( bp_is_active( 'groups' ) ) {
     1474                // Group creation
     1475                if ( bp_is_group_create() && bp_is_group_creation_step( 'group-avatar' ) && 'crop-image' != bp_get_avatar_admin_step() ) {
     1476                        $retval = true;
     1477
     1478                // Group Manage
     1479                } else if ( bp_is_group_admin_page() && bp_is_group_admin_screen( 'group-avatar' ) && 'crop-image' != bp_get_avatar_admin_step() ) {
     1480                        $retval = true;
     1481                }
     1482        }
     1483
     1484        /**
     1485         * Use this filter if you need to :
     1486         * - Load the avatar UI for a component that is !groups or !user (return true regarding your conditions)
     1487         * - Completely disable the avatar UI introduced in 2.3 (eg: __return_false())
     1488         *
     1489         * @since  BuddyPress (2.3.0)
     1490         *
     1491         * @var  bool whether to load the Avatar UI
     1492         */
     1493        return apply_filters( 'bp_core_avatar_is_front_edit_avatar', $retval );
     1494}
     1495
     1496/**
     1497 * Template function to load the Avatar UI javascript templates
     1498 *
     1499 * @since  BuddyPress (2.3.0)
     1500 *
     1501 * @uses  bp_core_avatar_is_front_edit_avatar() to check whether javascript templates should be loaded
     1502 * @uses  bp_get_template_part() to load the template part
     1503 */
     1504function bp_core_avatar_get_template_part() {
     1505        if ( ! bp_core_avatar_is_front_edit_avatar() ) {
     1506                return;
     1507        }
     1508
     1509        bp_get_template_part( 'attachments/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 * @uses  bp_core_avatar_is_front_edit_avatar() to check whether javascript templates should be loaded
     1522 * @uses  did_action() to check if the javascript template was loaded
     1523 * @uses  bp_get_template_part() to load the template part
     1524 */
     1525function bp_core_avatar_template_check() {
     1526        if ( ! bp_core_avatar_is_front_edit_avatar() ) {
     1527                return;
     1528        }
     1529
     1530        if ( ! did_action( 'bp_attachments_avatar_check_template' ) ) {
     1531                _doing_it_wrong( 'Theme Compatibility', __( "The templates of your theme should be updated", 'buddypress' ), '2.3' );
     1532                bp_get_template_part( 'attachments/avatars/index' );
     1533        }
     1534}
  • src/bp-core/bp-core-cssjs.php

    diff --git src/bp-core/bp-core-cssjs.php src/bp-core/bp-core-cssjs.php
    index e97748b..79bae82 100644
    function bp_core_register_common_scripts() { 
    2828        $scripts = apply_filters( 'bp_core_register_common_scripts', array(
    2929
    3030                // 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 ),
    3636
    3737                // 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( 'imgareaselect' ), 'footer' => true ),
     44                'bp-webcam'   => array( 'file' => "{$url}webcam{$min}.js", 'dependencies' => array( 'bp-avatar' ), 'footer' => true ),
     45
    4046        ) );
    4147
    4248        $version = bp_get_version();
    4349        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'] );
    4551        }
    4652}
    4753add_action( 'bp_enqueue_scripts',       'bp_core_register_common_scripts', 1 );
    function bp_core_register_common_styles() { 
    7682                'bp-admin-bar' => array(
    7783                        'file'         => $admin_bar_file,
    7884                        'dependencies' => array( 'admin-bar' )
    79                 )
     85                ),
     86                'bp-avatar' => array(
     87                        'file'         => "{$url}avatar{$min}.css",
     88                        'dependencies' => array( 'imgareaselect' )
     89                ),
    8090        ) );
    8191
    8292        foreach ( $styles as $id => $style ) {
    add_action( 'bp_enqueue_scripts', 'bp_core_confirmation_js' ); 
    110120add_action( 'bp_admin_enqueue_scripts', 'bp_core_confirmation_js' );
    111121
    112122/**
     123 * Enqueues the css and js required by the Avatar UI
     124 *
     125 * @since  BuddyPress (2.3.0)
     126 *
     127 * @uses bp_core_avatar_is_front_edit_avatar() to check if the Avatar scripts should be loaded
     128 * @uses bp_attachments_enqueue_scripts() to enqueue the css and js required by the Avatar UI
     129 * @uses add_action() to eventually load the javascript template files if templates are outdated
     130 */
     131function bp_core_avatar_scripts() {
     132        if ( ! bp_core_avatar_is_front_edit_avatar() ) {
     133                return false;
     134        }
     135
     136        // Enqueue the Attachments scripts for the Avatar UI
     137        bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' );
     138
     139        // Add Some actions for Theme backcompat
     140        add_action( 'bp_after_profile_avatar_upload_content', 'bp_core_avatar_template_check' );
     141        add_action( 'bp_after_group_admin_content',           'bp_core_avatar_template_check' );
     142        add_action( 'bp_after_group_avatar_creation_step',    'bp_core_avatar_template_check' );
     143}
     144add_action( 'bp_enqueue_scripts', 'bp_core_avatar_scripts' );
     145
     146/**
    113147 * Enqueues jCrop library and hooks BP's custom cropper JS.
    114148 */
    115149function bp_core_add_jquery_cropper() {
  • src/bp-core/bp-core-template.php

    diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
    index 857a25f..0b8a606 100644
    function bp_get_name_from_root_slug( $root_slug = '' ) { 
    11201120}
    11211121
    11221122function bp_user_has_access() {
    1123         $has_access = ( bp_current_user_can( 'bp_moderate' ) || bp_is_my_profile() )
     1123        $has_access = ( bp_current_user_can( 'bp_moderate' ) || bp_is_my_profile() || bp_is_my_admin_profile() )
    11241124                ? true
    11251125                : false;
    11261126
    function bp_is_my_profile() { 
    17171717}
    17181718
    17191719/**
     1720 * Is the current page part of the admin profile of the logged-in user?
     1721 *
     1722 * @since  BuddyPress (2.3.0)
     1723 *
     1724 * @return True if the current admin screen is logged-in user self profile, false otherwise.
     1725 */
     1726function bp_is_my_admin_profile() {
     1727        $bp = buddypress();
     1728
     1729        if ( ! is_user_logged_in() || array_diff( array( 'wp-admin', 'users.php' ), $bp->unfiltered_uri ) ) {
     1730                return false;
     1731        }
     1732
     1733        // Defaults to no user displayed
     1734        $displayed_admin_user_id = 0;
     1735
     1736        if ( ! empty( $bp->members->admin->user_id ) ) {
     1737                $displayed_admin_user_id = $bp->members->admin->user_id;
     1738        } else if ( ! empty( $_GET['page'] ) && 'bp-profile-edit' == $_GET['page'] && ! empty( $_GET['user_id'] ) ) {
     1739                $displayed_admin_user_id = (int) $_GET['user_id'];
     1740        } else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
     1741                $user_data = $_POST;
     1742                if ( ! empty( $user_data['bp_params'] ) ) {
     1743                        $user_data = $user_data['bp_params'];
     1744                }
     1745                if ( ! empty( $user_data['item_id'] ) && ! empty( $user_data['object'] ) && 'user' == $user_data['object'] ) {
     1746                        $displayed_admin_user_id = (int) $user_data['item_id'];
     1747                }
     1748        }
     1749
     1750        return apply_filters( 'bp_is_my_admin_profile', $displayed_admin_user_id === bp_loggedin_user_id() );
     1751}
     1752
     1753/**
    17201754 * Is the current page a user page?
    17211755 *
    17221756 * Will return true anytime there is a displayed user.
  • 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 8940954..06a7758 100644
    class BP_Attachment_Avatar extends BP_Attachment { 
    252252                // Return the full and thumb cropped avatars
    253253                return $avatar_types;
    254254        }
     255
     256        /**
     257         * Checks if viewing a user's profile (admin or front end)
     258         *
     259         * @since BuddyPress (2.3.0)
     260         *
     261         * @return integer the user ID
     262         */
     263        private function is_user_avatar() {
     264                $bp = buddypress();
     265                $user_item_id = 0;
     266
     267                if ( bp_is_user() ) {
     268                        $user_item_id = bp_displayed_user_id();
     269                }
     270
     271                if ( ! empty( $bp->members->admin->user_id ) ) {
     272                        $user_item_id = $bp->members->admin->user_id;
     273                }
     274
     275                return $user_item_id;
     276        }
     277
     278        /**
     279         * Build script datas for the Uploader UI
     280         *
     281         * @since BuddyPress (2.3.0)
     282         *
     283         * @uses BP_Attachment::script_data()
     284         */
     285        public function script_data() {
     286                // Get default script data
     287                $script_data = parent::script_data();
     288
     289                // Defaults to Avatar Backbone script
     290                $js_scripts = array( 'bp-avatar' );
     291
     292                $user_id = $this->is_user_avatar();
     293
     294                if ( ! empty( $user_id ) ) {
     295                        // Use this filter to disable the Webcam Avatar feature
     296                        if ( false !== apply_filters( 'bp_attachment_avatar_use_webcam', true ) ) {
     297                                $js_scripts = array( 'bp-webcam' );
     298                        }
     299
     300                        $script_data['bp_params'] = array(
     301                                'object'     => 'user',
     302                                'item_id'    => $user_id,
     303                                'has_avatar' => bp_get_user_has_avatar( $user_id ),
     304                                'nonces'  => array(
     305                                        'set'    => wp_create_nonce( 'bp_avatar_cropstore' ),
     306                                        'delete' => wp_create_nonce( 'bp_delete_avatar_link' ),
     307                                ),
     308                        );
     309
     310                        // Set feedback messages
     311                        $script_data['feedback_messages'] = array(
     312                                1 => __( 'There was a problem cropping your profile photo.', 'buddypress' ),
     313                                2 => __( 'Your new profile photo was uploaded successfully.', 'buddypress' ),
     314                                3 => __( 'There was a problem deleting your profile photo. Please try again.', 'buddypress'),
     315                                4 => __( 'Your profile photo was deleted successfully!', 'buddypress'),
     316                        );
     317                } else if ( bp_is_group() ) {
     318                        $script_data['bp_params'] = array(
     319                                'object'     => 'group',
     320                                'item_id'    => bp_get_current_group_id(),
     321                                'has_avatar' => bp_get_group_has_avatar(),
     322                                'nonces'     => array(
     323                                        'set'    => wp_create_nonce( 'bp_avatar_cropstore' ),
     324                                        'delete' => wp_create_nonce( 'bp_group_avatar_delete' ),
     325                                ),
     326                        );
     327
     328                        // Set feedback messages
     329                        $script_data['feedback_messages'] = array(
     330                                1 => __( 'There was a problem cropping the group profile photo.', 'buddypress' ),
     331                                2 => __( 'The group profile photo was uploaded successfully.', 'buddypress' ),
     332                                3 => __( 'There was a problem deleting the group profile photo. Please try again.', 'buddypress'),
     333                                4 => __( 'The group profile photo was deleted successfully!', 'buddypress'),
     334                        );
     335                } else {
     336                        // Blavatar ?
     337                        $script_data['bp_params'] = apply_filters( 'bp_attachment_avatar_params', array() );
     338                }
     339
     340                // Include the specific css
     341                $script_data['extra_css'] = array( 'bp-avatar' );
     342
     343                // Include the specific css
     344                $script_data['extra_js']  = $js_scripts;
     345
     346                return $script_data;
     347        }
    255348}
  • 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 337c27f..8e63e0b 100644
    class BP_Attachment { 
    505505                // Finally crop the image
    506506                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'] );
    507507        }
     508
     509        /**
     510         * Build script datas for the Uploader UI
     511         *
     512         * @since BuddyPress (2.3.0)
     513         *
     514         * Override this method from your child class to build the script datas
     515         */
     516        public function script_data() {
     517                $script_data = array(
     518                        'action'            => $this->action,
     519                        'file_data_name'    => $this->file_input,
     520                        'max_file_size'     => $this->original_max_filesize,
     521                        'feedback_messages' => array(
     522                                1 => __( 'Sorry, uploading the file failed.', 'buddypress' ),
     523                                2 => __( 'File successfully uploaded.', 'buddypress' ),
     524                        ),
     525                );
     526
     527                return $script_data;
     528        }
    508529}
  • src/bp-core/css/avatar.css

    diff --git src/bp-core/css/avatar.css src/bp-core/css/avatar.css
    index e69de29..af3a6be 100644
     
     1div.bp-avatar-status {
     2        clear:both;
     3        margin:1em 0;
     4}
     5
     6div.bp-avatar-status p.updated {
     7        display: block;
     8        padding: 10px 15px;
     9}
     10
     11div.bp-avatar-status p.success {
     12        background-color: #efc;
     13        border: 1px solid #591;
     14        color: #250;
     15}
     16
     17div.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
     62div.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 .drag-drop-inside {
     103        margin: 70px auto 0;
     104        width: 250px;
     105}
     106
     107.drag-drop .drag-drop-inside p, .drag-drop-inside p.drag-drop-buttons {
     108        display: block;
     109}
     110
     111.drag-drop .drag-drop-inside p {
     112        text-align: center;
     113        color: #aaa;
     114        font-size: 110%;
     115        margin: 5px 0;
     116}
     117
     118#avatar-to-crop {
     119        float: left;
     120        margin: 0 20px 20px 0;
     121        text-align: left;
     122}
     123#avatar-crop-pane {
     124        width: 150px;
     125        height: 150px;
     126        overflow: hidden;
     127}
     128
     129#avatar-crop-actions {
     130        margin: 20px 0;
     131}
     132
     133#avatar-to-crop img,
     134#avatar-crop-pane img,
     135#avatar-crop-pane canvas,
     136#avatar-upload-form img,
     137#create-group-form img,
     138#group-settings-form img {
     139        border: none !important;
     140        max-width: none !important;
     141}
     142
     143#bp-webcam-avatar video {
     144        float:left;
     145        width:450px;
     146}
     147
     148#bp-webcam-avatar #avatar-crop-pane {
     149        border: 2px dashed #bbb;
     150}
     151
     152/** Admin Profile **/
     153body.users_page_bp-profile-edit.modal-open #TB_ajaxContent,
     154body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent {
     155        width:95%!important;
     156        height:95%!important;
     157}
     158
     159body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,
     160body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,
     161body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,
     162body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
     163        display: block;
     164        padding: 10px 15px;
     165}
  • src/bp-core/js/avatar.js

    diff --git src/bp-core/js/avatar.js src/bp-core/js/avatar.js
    index e69de29..f37a115 100644
     
     1window.bp = window.bp || {};
     2
     3( function( exports, $ ) {
     4
     5        // Bail if not set
     6        if ( typeof BP_Uploader === 'undefined' ) {
     7                return;
     8        }
     9
     10        bp.Models      = bp.Models || {};
     11        bp.Collections = bp.Collections || {};
     12        bp.Views       = bp.Views || {};
     13
     14        bp.Avatar = {
     15                start: function() {
     16                        /**
     17                         * Remove the bp-legacy UI
     18                         *
     19                         * If for some reason javascript is disabled
     20                         * or broken, this is a way to keep the legacy UI
     21                         * as nothing will happen..
     22                         */
     23                        // User
     24                        if ( $( '#avatar-upload-form' ).length ) {
     25                                $( '#avatar-upload' ).remove();
     26                                $( '#avatar-upload-form p' ).remove();
     27
     28                        // Group Manage
     29                        } else if ( $( '#group-settings-form' ).length ) {
     30                                $( '#group-settings-form p' ).each( function( i ) {
     31                                        if ( 0 !== i ) {
     32                                                $( this ).remove();
     33                                        }
     34                                } );
     35
     36                                if ( $( '#delete-group-avatar-button' ).length ) {
     37                                        $( '#delete-group-avatar-button' ).remove();
     38                                }
     39
     40                        // Group Create
     41                        } else if ( $( '#group-create-body' ).length ) {
     42                                $( '.main-column p #file' ).remove();
     43                                $( '.main-column p #upload' ).remove();
     44
     45                        // Admin Extended Profile
     46                        } else if ( $( '#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin' ).length ) {
     47                                $( '#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin' ).remove();
     48                        }
     49
     50                        // Init some vars
     51                        this.views      = new Backbone.Collection();
     52                        this.activeView = 'upload';
     53                        this.iasapi     = {};
     54
     55                        // Set up nav
     56                        this.setupNav();
     57
     58                        // Create the uploader view by default
     59                        this.uploaderView();
     60
     61                        // Avatars are uploaded files
     62                        this.avatars = bp.Uploader.filesUploaded;
     63                        this.avatars.on( 'add', this.cropView, this );
     64                },
     65
     66                setView: function( view ) {
     67                        // Clear views
     68                        if ( ! _.isUndefined( this.views.models ) ) {
     69                                _.each( this.views.models, function( model ) {
     70                                        model.get( 'view' ).remove();
     71                                }, this );
     72                        }
     73
     74                        // Reset objects
     75                        this.views.reset();
     76                        this.avatars.reset();
     77
     78                        if ( ! _.isEmpty( this.iasapi ) ) {
     79                                this.iasapi.remove();
     80                                this.iasapi = {};
     81                        }
     82
     83                        // Load the required view
     84                        switch ( view ) {
     85                                case 'upload':
     86                                        this.uploaderView();
     87                                        break;
     88
     89                                case 'delete':
     90                                        this.deleteView();
     91                                        break;
     92                        }
     93                },
     94
     95                setupNav: function() {
     96                        var nav = new Backbone.Collection(),
     97                            self = this;
     98
     99                        _.each( BP_Uploader.settings.nav, function( item ) {
     100                                if ( ! _.isObject( item ) ) {
     101                                        return;
     102                                }
     103
     104                                nav.add( {
     105                                        id: item.id,
     106                                        name: item.caption,
     107                                        href: '#',
     108                                        active: ( self.activeView == item.id ) ? 1 : 0,
     109                                } );
     110                        } );
     111
     112                        this.nav = new bp.Views.Nav( { collection: nav } );
     113                        this.nav.inject( '.bp-avatar-nav' );
     114
     115                        // Listen to nav changes (it's like a do_action!)
     116                        this.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) );
     117                },
     118
     119                uploaderView: function() {
     120                        // Listen to the Queued uploads
     121                        bp.Uploader.filesQueue.on( 'add', this.uploadProgress, this );
     122
     123                        // Create the BuddyPress Uploader
     124                        uploader = new bp.Views.Uploader();
     125
     126                        // Add it to views
     127                        this.views.add( { id: 'upload', view: uploader } );
     128
     129                        // Display it
     130                        uploader.inject( '.bp-avatar' );
     131                },
     132
     133                uploadProgress: function( model ) {
     134                        // Create the Uploader status view
     135                        avatarStatus = new bp.Views.uploaderStatus( { collection: bp.Uploader.filesQueue } );
     136
     137                        if ( ! _.isUndefined( this.views.get( 'status' ) ) ) {
     138                                this.views.set( { id: 'status', view: avatarStatus } );
     139                        } else {
     140                                this.views.add( { id: 'status', view: avatarStatus } );
     141                        }
     142
     143                        // Display it
     144                        avatarStatus.inject( '.bp-avatar-status' );
     145                },
     146
     147                cropView: function() {
     148                        var status;
     149
     150                        // Make sure to remove the uploads status
     151                        if ( ! _.isUndefined( this.views.get( 'status' ) ) ) {
     152                                status = this.views.get( 'status' );
     153                                status.get( 'view' ).remove();
     154                                this.views.remove( { id: 'status', view: status } );
     155                        }
     156
     157                        // Create the Avatars view
     158                        avatar = new bp.Views.Avatars( { collection: this.avatars } );
     159                        this.views.add( { id: 'crop', view: avatar } );
     160
     161                        avatar.inject( '.bp-avatar' );
     162                },
     163
     164                setAvatar: function( avatar ) {
     165                        var self = this,
     166                                crop;
     167
     168                        // Remove the crop view
     169                        if ( ! _.isUndefined( this.views.get( 'crop' ) ) ) {
     170                                // Remove the imgAreaSelect API
     171                                if ( ! _.isEmpty( this.iasapi ) ) {
     172                                        this.iasapi.remove();
     173                                        this.iasapi = {};
     174                                }
     175                                crop = this.views.get( 'crop' );
     176                                crop.get( 'view' ).remove();
     177                                this.views.remove( { id: 'crop', view: crop } );
     178                        }
     179
     180                        // Set the avatar !
     181                        bp.ajax.post( 'bp_avatar_set', {
     182                                json:          true,
     183                                original_file: avatar.get( 'url' ),
     184                                crop_w:        avatar.get( 'w' ),
     185                                crop_h:        avatar.get( 'h' ),
     186                                crop_x:        avatar.get( 'x' ),
     187                                crop_y:        avatar.get( 'y' ),
     188                                item_id:       avatar.get( 'item_id' ),
     189                                object:        avatar.get( 'object' ),
     190                                type:          _.isUndefined( avatar.get( 'type' ) ) ? 'crop' : avatar.get( 'type' ),
     191                                nonce:         avatar.get( 'nonces' ).set,
     192                        } ).done( function( response ) {
     193                                avatarStatus = new bp.Views.AvatarStatus( {
     194                                        value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
     195                                        type : 'success',
     196                                } );
     197
     198                                self.views.add( {
     199                                        id   : 'status',
     200                                        view : avatarStatus
     201                                } );
     202
     203                                avatarStatus.inject( '.bp-avatar-status' );
     204
     205                                // Update each avatars of the page
     206                                $( '.' + avatar.get( 'object' ) + '-' + response.item_id + '-avatar' ).each( function() {
     207                                        $(this).prop( 'src', response.avatar );
     208                                } );
     209                        } ).fail( function( response ) {
     210                                feedback = BP_Uploader.strings.default_error;
     211                                if ( ! _.isUndefined( response ) ) {
     212                                        feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ]
     213                                }
     214
     215                                avatarStatus = new bp.Views.AvatarStatus( {
     216                                        value : feedback,
     217                                        type : 'error',
     218                                } );
     219
     220                                self.views.add( {
     221                                        id   : 'status',
     222                                        view : avatarStatus
     223                                } );
     224
     225                                avatarStatus.inject( '.bp-avatar-status' );
     226                        } );
     227                },
     228
     229                deleteView:function() {
     230                        // Create the delete model
     231                        delete_model = new Backbone.Model( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
     232                                'object',
     233                                'item_id',
     234                                'nonces'
     235                        ) );
     236
     237                        // Create the delete view
     238                        deleteView = new bp.Views.DeleteAvatar( { model: delete_model } );
     239
     240                        // Add it to views
     241                        this.views.add( { id: 'delete', view: deleteView } );
     242
     243                        // Display it
     244                        deleteView.inject( '.bp-avatar' );
     245                },
     246
     247                deleteAvatar: function( model ) {
     248                        var self = this,
     249                                deleteView;
     250
     251                        // Remove the delete view
     252                        if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) {
     253                                deleteView = this.views.get( 'delete' );
     254                                deleteView.get( 'view' ).remove();
     255                                this.views.remove( { id: 'delete', view: deleteView } );
     256                        }
     257
     258                        // Remove the avatar !
     259                        bp.ajax.post( 'bp_avatar_delete', {
     260                                json:          true,
     261                                item_id:       model.get( 'item_id' ),
     262                                object:        model.get( 'object' ),
     263                                nonce:         model.get( 'nonces' ).delete,
     264                        } ).done( function( response ) {
     265                                avatarStatus = new bp.Views.AvatarStatus( {
     266                                        value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
     267                                        type : 'success',
     268                                } );
     269
     270                                self.views.add( {
     271                                        id   : 'status',
     272                                        view : avatarStatus
     273                                } );
     274
     275                                avatarStatus.inject( '.bp-avatar-status' );
     276
     277                                // Update each avatars of the page
     278                                $( '.' + model.get( 'object' ) + '-' + response.item_id + '-avatar').each( function() {
     279                                        $(this).prop( 'src', response.avatar );
     280                                } );
     281
     282                                /**
     283                                 * Remove the delete tab
     284                                 * @todo this should be more dynamic using model.set()
     285                                 * - create the delete tab when new avatar is set
     286                                 * - remove the delete tab when avatar is deleted.
     287                                 *
     288                                 * For now, let's just remove the nav
     289                                 */
     290                                 $( '#bp-avatar-delete' ).remove();
     291
     292                        } ).fail( function( response ) {
     293                                feedback = BP_Uploader.strings.default_error;
     294                                if ( ! _.isUndefined( response ) ) {
     295                                        feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ]
     296                                }
     297
     298                                avatarStatus = new bp.Views.AvatarStatus( {
     299                                        value : feedback,
     300                                        type : 'error',
     301                                } );
     302
     303                                self.views.add( {
     304                                        id   : 'status',
     305                                        view : avatarStatus
     306                                } );
     307
     308                                avatarStatus.inject( '.bp-avatar-status' );
     309                        } );
     310                }
     311        };
     312
     313        // Main Nav view
     314        bp.Views.Nav = bp.View.extend( {
     315                tagName:    'ul',
     316                className:  'avatar-nav-items',
     317
     318                events: {
     319                        'click .bp-avatar-nav-item' : 'toggleView',
     320                },
     321
     322                initialize: function() {
     323                        _.each( this.collection.models, this.addNavItem, this );
     324                },
     325
     326                addNavItem: function( item ) {
     327                        this.views.add( new bp.Views.NavItem( { model: item } ) );
     328                },
     329
     330                toggleView: function( event ) {
     331                        event.preventDefault();
     332
     333                        var active = $( event.target ).data( 'nav' );
     334
     335                        _.each( this.collection.models, function( model ) {
     336                                if ( model.id == active ) {
     337                                        model.set( { active: 1 } );
     338                                        this.trigger( 'bp-avatar-view:changed', model.id )
     339                                } else {
     340                                        model.set( { active: 0 } );
     341                                }
     342                        }, this );
     343                },
     344        } );
     345
     346        // Nav item view
     347        bp.Views.NavItem = bp.View.extend( {
     348                tagName:    'li',
     349                className:  'avatar-nav-item',
     350                template: bp.template( 'bp-avatar-nav' ),
     351
     352                initialize: function() {
     353                        if ( 1 == this.model.get( 'active' ) ) {
     354                                this.el.className += ' current';
     355                        }
     356                        this.el.id += 'bp-avatar-' + this.model.get( 'id' );
     357
     358                        this.model.on( 'change:active', this.setCurrentNav, this );
     359                },
     360
     361                setCurrentNav: function( model ) {
     362                        if ( 1 == model.get( 'active' ) ) {
     363                                this.$el.addClass( 'current' );
     364                        } else {
     365                                this.$el.removeClass( 'current' );
     366                        }
     367                },
     368        } );
     369
     370        // Avatars view
     371        bp.Views.Avatars = bp.View.extend( {
     372                className: "items",
     373
     374                initialize: function() {
     375                        _.each( this.collection.models, this.addItemView, this );
     376                },
     377
     378                addItemView: function( item ) {
     379                        item.set( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
     380                                'object',
     381                                'item_id',
     382                                'nonces'
     383                        ) );
     384                        this.views.add( new bp.Views.Avatar( { model: item } ) );
     385                }
     386        } );
     387
     388        // Avatar view
     389        bp.Views.Avatar = bp.View.extend( {
     390                className: "item",
     391                template: bp.template( 'bp-avatar-item' ),
     392
     393                events: {
     394                        'click .avatar-crop-submit': 'cropAvatar',
     395                },
     396
     397                initialize: function() {
     398                        _.defaults( this.options, {
     399                                full_h:  BP_Uploader.settings.crop.full_h,
     400                                full_w:  BP_Uploader.settings.crop.full_w,
     401                                aspectRatio : '150:150'
     402                        } );
     403
     404                        this.on( 'ready', this.initCropper );
     405                },
     406
     407                initCropper: function() {
     408                        var self = this,
     409                                tocrop = this.$el.find( '#avatar-to-crop img' ),
     410                                selection = {};
     411
     412                        if ( ! _.isUndefined( this.options.full_h ) && ! _.isUndefined( this.options.full_w ) ) {
     413                                this.options.aspectRatio = this.options.full_h + ':' + this.options.full_w;
     414                        }
     415
     416                        selection.w = this.model.get( 'width' );
     417                        selection.h = this.model.get( 'height' );
     418
     419                        if ( selection.h <= selection.w ) {
     420                                crop_top    = Math.round( selection.h / 4 );
     421                                nh = nw     = Math.round( selection.h / 2 );
     422                                crop_bottom = nh + crop_top;
     423                                crop_left   = ( selection.w - nw ) / 2;
     424                                crop_right  = nw + crop_left;
     425                        } else {
     426                                crop_left   = Math.round( selection.w / 4 );
     427                                nh = nw     = Math.round( selection.w / 2 );
     428                                crop_right  = nw + crop_left;
     429                                crop_top    = ( selection.h - nh ) / 2;;
     430                                crop_bottom = nh + crop_top;
     431                        }
     432
     433                        /**
     434                         * Add the cropping interface
     435                         * We're not specifying the parent option of the imgAreaSelect API
     436                         * as it can be problematic with some themes (eg: twentyfifteen)
     437                         */
     438                        bp.Avatar.iasapi = tocrop.imgAreaSelect( {
     439                                instance: true,
     440                                aspectRatio: self.options.aspectRatio,
     441                                handles:true,
     442                                x1: crop_left,
     443                                y1: crop_top,
     444                                x2: crop_right,
     445                                y2: crop_bottom,
     446                                onInit: function () {
     447                                        self.model.set( { x: crop_left, y: crop_top, w: nw, h: nh } );
     448                                        self.showPreview( self.model, self.options );
     449                                },
     450                                onSelectChange: function( img, c ) {
     451                                        self.model.set( { x: c.x1, y: c.y1, w: c.width, h: c.height } );
     452                                        self.showPreview( self.model, self.options );
     453                                }
     454                        } );
     455                },
     456
     457                cropAvatar: function( event ) {
     458                        event.preventDefault();
     459
     460                        bp.Avatar.setAvatar( this.model );
     461                },
     462
     463                showPreview: function( model, options ) {
     464                        if ( ! model.get( 'w' ) || ! model.get( 'h' ) ) {
     465                                return;
     466                        }
     467
     468                        if ( parseInt( model.get( 'w' ) ) > 0 ) {
     469                                var fw = options.full_w;
     470                                var fh = options.full_h;
     471                                var rx = fw / model.get( 'w' );
     472                                var ry = fh / model.get( 'h' );
     473
     474                                $( '#avatar-crop-preview' ).css( {
     475                                        maxWidth:'none',
     476                                        width: Math.round( rx *  model.get( 'width' ) )+ 'px',
     477                                        height: Math.round( ry * model.get( 'height' ) )+ 'px',
     478                                        marginLeft: '-' + Math.round( rx * model.get( 'x' ) ) + 'px',
     479                                        marginTop: '-' + Math.round( ry * model.get( 'y' ) ) + 'px'
     480                                } );
     481                        }
     482                },
     483
     484        } );
     485
     486        // BuddyPress Avatar Feedback view
     487        bp.Views.AvatarStatus = bp.View.extend( {
     488                tagName: 'p',
     489                className: 'updated',
     490                id: 'bp-avatar-feedback',
     491
     492                initialize: function() {
     493                        this.el.className += ' ' + this.options.type;
     494                        this.value = this.options.value;
     495                },
     496
     497                render: function() {
     498                        this.$el.html( this.value );
     499                        return this;
     500                }
     501        } );
     502
     503        // BuddyPress Avatar Delete view
     504        bp.Views.DeleteAvatar = bp.View.extend( {
     505                tagName: 'div',
     506                id: 'bp-delete-avatar',
     507                template: bp.template( 'bp-avatar-delete' ),
     508
     509                events: {
     510                        'click #bp-delete-avatar': 'deleteAvatar',
     511                },
     512
     513                deleteAvatar: function( event ) {
     514                        event.preventDefault();
     515
     516                        bp.Avatar.deleteAvatar( this.model );
     517                }
     518        } );
     519
     520        bp.Avatar.start();
     521
     522})( 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..07f0959 100644
     
     1window.wp = window.wp || {};
     2window.bp = window.bp || window.wp;
     3
     4( function( exports, $ ) {
     5
     6        // Bail if not set
     7        if ( typeof BP_Uploader === 'undefined' ) {
     8                return;
     9        }
     10
     11        bp.Models      = bp.Models || {};
     12        bp.Collections = bp.Collections || {};
     13        bp.Views       = bp.Views || {};
     14        bp.Uploader    = {};
     15
     16        /**
     17         * BuddyPress Uploader.
     18         *
     19         * This is an adapted version of wp.Uploader
     20         */
     21        bp.Uploader.uploader = function() {
     22                var self = this;
     23                this.params  = BP_Uploader.settings;
     24                this.strings = BP_Uploader.strings;
     25
     26                this.uploader    = new plupload.Uploader( this.params.defaults );
     27                multipart_origin = this.uploader.settings.multipart_params;
     28
     29                /**
     30                 * After the Uploader has been initialized, initialize some behaviors for the dropzone.
     31                 *
     32                 * @event Init
     33                 * @param {plupload.Uploader} uploader Uploader instance.
     34                 */
     35                this.uploader.bind( 'Init', function( uplaoder ) {
     36                        var container = $( '#' + self.params.defaults.container ),
     37                            drop_element = $( '#' + self.params.defaults.drop_element );
     38
     39                        if ( uplaoder.features.dragdrop && ! $( document.body ).hasClass( 'mobile' ) ) {
     40                                container.addClass( 'drag-drop' );
     41                                drop_element.bind( 'dragover.wp-uploader', function() {
     42                                        container.addClass( 'drag-over' );
     43                                } ).bind( 'dragleave.wp-uploader, drop.wp-uploader', function() {
     44                                        container.removeClass( 'drag-over' );
     45                                } );
     46                        } else {
     47                                container.removeClass( 'drag-drop' );
     48                                drop_element.unbind( '.wp-uploader' );
     49                        }
     50
     51                        if ( uplaoder.runtime == 'html4' ) {
     52                                $('.upload-flash-bypass').hide();
     53                        }
     54
     55                } );
     56
     57                // Init BuddyPress Uploader
     58                this.uploader.init();
     59
     60                /**
     61                 * Feedback callback.
     62                 *
     63                 * Add a new message to the errors collection, so it's possible
     64                 * to give some feedback to the user
     65                 *
     66                 * @param  {string}        message
     67                 * @param  {object}        data
     68                 * @param  {plupload.File} file     File that was uploaded.
     69                 */
     70                feedback = function( message, data, file ) {
     71                        if ( ! _.isNull( file ) && file.item ) {
     72                                file.item.clear();
     73                        }
     74
     75                        bp.Uploader.filesError.unshift( {
     76                                message: message,
     77                                data:    data,
     78                                file:    file
     79                        } );
     80                };
     81
     82                /**
     83                 * After files were filtered and added to the queue, create a model for each.
     84                 *
     85                 * @event FilesAdded
     86                 * @param {plupload.Uploader} uploader Uploader instance.
     87                 * @param {Array}             files    Array of file objects that were added to queue by the user.
     88                 */
     89                this.uploader.bind( 'FilesAdded', function( uploader, files ) {
     90                        hundredmb = 100 * 1024 * 1024, max = parseInt( uploader.settings.max_file_size, 10 );
     91
     92                        /**
     93                         * In case the multiple selection is false (eg: avatar) stop the process and send
     94                         * and event containing a warning
     95                         */
     96                        if ( ! uploader.settings.multi_selection && files.length > 1 ) {
     97                                for ( i in files ) {
     98                                        uploader.removeFile( files[i] );
     99                                }
     100
     101                                $(self).trigger( 'bp-uploader-warning', self.strings.unique_file_warning );
     102                                return;
     103                        }
     104
     105                        _.each( files, function( file ) {
     106                                var attributes;
     107
     108                                // Ignore failed uploads.
     109                                if ( plupload.FAILED === file.status ) {
     110                                        return;
     111                                }
     112
     113                                if ( max > hundredmb && file.size > hundredmb && up.runtime != 'html5' ) {
     114                                        _this.uploadSizeError( uploader, file, true );
     115                                } else {
     116                                        attributes = _.extend( {
     117                                                id:        file.id,
     118                                                file:      file,
     119                                                uploading: true,
     120                                                date:      new Date(),
     121                                                filename:  file.name,
     122                                        }, _.pick( file, 'loaded', 'size', 'percent' ) );
     123
     124                                        file.item = new bp.Models.File( attributes );
     125                                        bp.Uploader.filesQueue.add( file.item );
     126                                }
     127
     128                        } );
     129
     130                        uploader.refresh();
     131                        uploader.start();
     132                } );
     133
     134                /**
     135                 * Update each file item on progress
     136                 *
     137                 * @event UploadProgress
     138                 * @param {plupload.Uploader} uploader Uploader instance.
     139                 * @param {Object}            file
     140                 */
     141                this.uploader.bind( 'UploadProgress', function( uploader, file ) {
     142                        file.item.set( _.pick( file, 'loaded', 'percent' ) );
     143                } );
     144
     145                /**
     146                 * After a file is successfully uploaded, update its model.
     147                 *
     148                 * @event FileUploaded
     149                 * @param {plupload.Uploader} uploader Uploader instance.
     150                 * @param {plupload.File}     file     File that was uploaded.
     151                 * @param {Object}            response Object with response properties.
     152                 * @return {mixed}
     153                 */
     154                this.uploader.bind( 'FileUploaded', function( uploader, file, response ) {
     155                        var complete,
     156                                message = self.strings.default_error;
     157
     158                        try {
     159                                response = JSON.parse( response.response );
     160                        } catch ( e ) {
     161                                return feedback( message, e, file );
     162                        }
     163
     164                        if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) {
     165                                return feedback( message, null, file );
     166                        } else if ( ! response.success ) {
     167                                if ( response.data && response.data.message ) {
     168                                        message = response.data.message;
     169                                }
     170
     171                                return feedback( message, response.data, file );
     172                        }
     173
     174                        _.each(['file','loaded','size','percent'], function( key ) {
     175                                file.item.unset( key );
     176                        });
     177
     178                        file.item.set( _.extend( response.data, { uploading: false } ) );
     179
     180                        //  Add the file to the Uploaded ones
     181                        item = new bp.Models.File( response.data )
     182                        bp.Uploader.filesUploaded.add( item );
     183                } );
     184
     185                /**
     186                 * Trigger an event to inform a new upload is being processed
     187                 *
     188                 * Mainly used to remove an eventual warning
     189                 *
     190                 * @event BeforeUpload
     191                 * @param {plupload.Uploader} uploader Uploader instance.
     192                 * @param {Array}             files    Array of file objects that were added to queue by the user.
     193                 */
     194                this.uploader.bind( 'BeforeUpload', function( uploader, files ) {
     195                        $(self).trigger( 'bp-uploader-new-upload' );
     196                } );
     197
     198                /**
     199                 * Reset the filesQueue once the upload is complete
     200                 *
     201                 * @event BeforeUpload
     202                 * @param {plupload.Uploader} uploader Uploader instance.
     203                 * @param {Array}             files    Array of file objects that were added to queue by the user.
     204                 */
     205                this.uploader.bind( 'UploadComplete', function( uploader, files ) {
     206                        bp.Uploader.filesQueue.reset();
     207                } );
     208
     209                /**
     210                 * Map Plupload errors & Create a warning when plupload failed
     211                 *
     212                 * @event Error
     213                 * @param {plupload.Uploader} uploader Uploader instance.
     214                 * @param {Object}            pluploadError Plupload error
     215                 */
     216                this.uploader.bind( 'Error', function( uploader, pluploadError ) {
     217                        var message = self.strings.default_error,
     218                                key,
     219                                errors = {
     220                                        'FAILED':                 self.strings.upload_failed,
     221                                        'FILE_EXTENSION_ERROR':   self.strings.invalid_filetype,
     222                                        'IMAGE_FORMAT_ERROR':     self.strings.not_an_image,
     223                                        'IMAGE_MEMORY_ERROR':     self.strings.image_memory_exceeded,
     224                                        'IMAGE_DIMENSIONS_ERROR': self.strings.image_dimensions_exceeded,
     225                                        'GENERIC_ERROR':          self.strings.upload_failed,
     226                                        'IO_ERROR':               self.strings.io_error,
     227                                        'HTTP_ERROR':             self.strings.http_error,
     228                                        'SECURITY_ERROR':         self.strings.security_error,
     229                                        'FILE_SIZE_ERROR':        self.strings.file_exceeds_size_limit.replace( '%s' , pluploadError.file.name )
     230                                };
     231
     232                        // Check for plupload errors.
     233                        for ( key in errors ) {
     234                                if ( pluploadError.code === plupload[ key ] ) {
     235                                        message = errors[ key ];
     236                                        break;
     237                                }
     238                        }
     239
     240                        $(self).trigger( 'bp-uploader-warning', message );
     241                        uploader.refresh();
     242                } );
     243        }
     244
     245        // Create a very generic Model for files
     246        bp.Models.File = Backbone.Model.extend( {
     247                file: {},
     248        } );
     249
     250        // Add Collections to store queue, uploaded files and errors
     251        $.extend( bp.Uploader, {
     252                filesQueue    : new Backbone.Collection(),
     253                filesUploaded : new Backbone.Collection(),
     254                filesError    : new Backbone.Collection()
     255        } );
     256
     257        // Extend wp.Backbone.View with .prepare() and .inject()
     258        bp.View = bp.Backbone.View.extend( {
     259                inject: function( selector ) {
     260                        this.render();
     261                        $(selector).html( this.el );
     262                        this.views.ready();
     263                },
     264
     265                prepare: function() {
     266                        if ( ! _.isUndefined( this.model ) && _.isFunction( this.model.toJSON ) ) {
     267                                return this.model.toJSON();
     268                        } else {
     269                                return {};
     270                        }
     271                }
     272        } );
     273
     274        // BuddyPress Uploader main view
     275        bp.Views.Uploader = bp.View.extend( {
     276                className: "bp-uploader-window",
     277                template: bp.template( "upload-window" ),
     278
     279                defaults: _.pick( BP_Uploader.settings.defaults, 'container', 'drop_element', 'browse_button' ),
     280
     281                initialize: function() {
     282                        this.warning = null;
     283                        this.model = new Backbone.Model( this.defaults );
     284                        this.on( 'ready', this.initUploader );
     285                },
     286
     287                initUploader: function() {
     288                        this.uploader = new bp.Uploader.uploader();
     289                        $( this.uploader ).on( 'bp-uploader-warning', _.bind( this.setWarning, this ) );
     290                        $( this.uploader ).on( 'bp-uploader-new-upload', _.bind( this.resetWarning, this ) );
     291                },
     292
     293                setWarning: function( event, message ) {
     294                        if ( _.isUndefined( message ) ) {
     295                                return;
     296                        }
     297
     298                        this.warning = new bp.Views.uploaderWarning( {
     299                                value: message
     300                        } ).render();
     301
     302                        this.$el.after( this.warning.el );
     303                },
     304
     305                resetWarning: function( event ) {
     306                        if ( _.isNull( this.warning ) ) {
     307                                return;
     308                        }
     309
     310                        this.warning.remove();
     311                        this.warning = null;
     312                }
     313        } );
     314
     315        // BuddyPress Uploader warning view
     316        bp.Views.uploaderWarning = bp.View.extend( {
     317                tagName: 'p',
     318                className: 'warning',
     319                id: 'bp-uploader-warning',
     320
     321                initialize: function() {
     322                        this.value = this.options.value;
     323                },
     324
     325                render: function() {
     326                        this.$el.html( this.value );
     327                        return this;
     328                }
     329        } );
     330
     331        // BuddyPress Uploader Files view
     332        bp.Views.uploaderStatus = bp.View.extend( {
     333                className: "files",
     334
     335                initialize: function() {
     336                        _.each( this.collection.models, this.addFile, this );
     337                        this.collection.on( 'change:percent', this.progress, this );
     338                        bp.Uploader.filesError.on( 'add', this.feedback, this );
     339                },
     340
     341                addFile: function( file ) {
     342                        this.views.add( new bp.Views.uploaderProgress( { model: file } ) );
     343                },
     344
     345                progress:function( model ) {
     346                        if ( ! _.isUndefined( model.get( 'percent' ) ) ) {
     347                                $( '#' + model.get('id') + ' .progress .bar' ).css( 'width', model.get('percent') + '%' );
     348                        }
     349                },
     350
     351                feedback: function( model ) {
     352                        if ( ! _.isUndefined( model.get( 'message' ) ) && ! _.isUndefined( model.get( 'file' ) ) ) {
     353                                $( '#' + model.get( 'file' ).id ).html( model.get( 'message' ) ).addClass( 'error' );
     354                        }
     355                }
     356        } );
     357
     358        // BuddyPress Uploader File progress view
     359        bp.Views.uploaderProgress = bp.View.extend( {
     360                className: "bp-uploader-progress",
     361                template: bp.template( "progress-window" ),
     362        } );
     363
     364})( bp, jQuery );
  • src/bp-core/js/webcam.js

    diff --git src/bp-core/js/webcam.js src/bp-core/js/webcam.js
    index e69de29..11b5fbc 100644
     
     1window.bp = window.bp || {};
     2
     3( function( exports, $ ) {
     4
     5        // Bail if not set
     6        if ( typeof BP_Uploader === 'undefined' ) {
     7                return;
     8        }
     9
     10        bp.Models      = bp.Models || {};
     11        bp.Collections = bp.Collections || {};
     12        bp.Views       = bp.Views || {};
     13
     14        bp.WebCam = {
     15                start: function() {
     16                        this.params = {
     17                                video:          null,
     18                                videoStream:    null,
     19                                capture_enable: false,
     20                                capture:        null,
     21                                canvas:         null,
     22                                warning:        null,
     23                        }
     24
     25                        bp.Avatar.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) );
     26                },
     27
     28                setView: function( view ) {
     29                        if ( 'camera' != view ) {
     30                                // Stop the camera if needed
     31                                if ( ! _.isNull( this.params.video ) ) {
     32                                        this.stop();
     33
     34                                        // Remove all warnings as we're changing the view
     35                                        this.removeWarning();
     36                                }
     37
     38                                // Stop as this is not Camera area
     39                                return;
     40                        }
     41
     42                        // Create the WebCam view
     43                        cameraView = new bp.Views.WebCamAvatar( { model: new Backbone.Model( { user_media: false } ) } );
     44
     45                        // Add it to views
     46                        bp.Avatar.views.add( { id: 'camera', view: cameraView } );
     47
     48                        // Display it
     49                cameraView.inject( '.bp-avatar' );
     50                },
     51
     52                removeView: function() {
     53                        var camera;
     54
     55                        if ( ! _.isUndefined( bp.Avatar.views.get( 'camera' ) ) ) {
     56                                camera = bp.Avatar.views.get( 'camera' );
     57                                camera.get( 'view' ).remove();
     58                                bp.Avatar.views.remove( { id: 'camera', view: camera } );
     59                        }
     60                },
     61
     62                gotStream: function( stream ) {
     63                        var video = bp.WebCam.params.video;
     64                        bp.WebCam.params.videoStream = stream;
     65
     66                        // User Feedback
     67                        bp.WebCam.displayWarning( 'loaded' );
     68
     69                        video.onerror = function () {
     70                                // User Feedback
     71                                bp.WebCam.displayWarning( 'videoerror' );
     72
     73                                if ( video ) {
     74                                        bp.WebCam.stop();
     75                                }
     76                        };
     77
     78                        stream.onended = bp.WebCam.noStream();
     79
     80                        if ( video.mozSrcObject !== undefined ) {
     81                                video.mozSrcObject = stream;
     82                                video.play();
     83                        } else if ( navigator.mozGetUserMedia ) {
     84                                video.src = stream;
     85                                video.play();
     86                        } else if ( window.URL ) {
     87                                video.src = window.URL.createObjectURL( stream );
     88                        } else {
     89                                video.src = stream;
     90                        }
     91
     92                        bp.WebCam.params.capture_enable = true;
     93                },
     94
     95                stop: function() {
     96                        bp.WebCam.params.capture_enable = false;
     97                        if ( bp.WebCam.params.videoStream ) {
     98                                if ( bp.WebCam.params.videoStream.stop ) {
     99                                        bp.WebCam.params.videoStream.stop();
     100                                } else if ( bp.WebCam.params.videoStream.msStop ) {
     101                                        bp.WebCam.params.videoStream.msStop();
     102                                }
     103                                bp.WebCam.params.videoStream.onended = null;
     104                                bp.WebCam.params.videoStream = null;
     105                        }
     106                        if ( bp.WebCam.params.video ) {
     107                                bp.WebCam.params.video.onerror = null;
     108                                bp.WebCam.params.video.pause();
     109                                if ( bp.WebCam.params.video.mozSrcObject ) {
     110                                        bp.WebCam.params.video.mozSrcObject = null;
     111                                }
     112                                bp.WebCam.params.video.src = "";
     113                        }
     114                },
     115
     116                noStream: function() {
     117                        if ( _.isNull( bp.WebCam.params.videoStream ) ) {
     118                                // User Feedback
     119                                bp.WebCam.displayWarning( 'noaccess' );
     120
     121                                bp.WebCam.removeView();
     122                        }
     123                },
     124
     125                setAvatar: function( avatar ) {
     126                        if ( ! avatar.get( 'url' ) ) {
     127                                bp.WebCam.displayWarning( 'nocapture' );
     128                        }
     129
     130                        // Remove the view
     131                        bp.WebCam.removeView();
     132
     133                        bp.Avatar.setAvatar( avatar );
     134                },
     135
     136                removeWarning: function() {
     137                        if ( ! _.isNull( this.params.warning ) ) {
     138                                this.params.warning.remove();
     139                        }
     140                },
     141
     142                displayWarning: function( code ) {
     143                        this.removeWarning();
     144
     145                        this.params.warning = new bp.Views.uploaderWarning( {
     146                                value: BP_Uploader.strings.camera_warnings[code]
     147                        } );
     148
     149                        this.params.warning.inject( '.bp-avatar-status' );
     150                },
     151        };
     152
     153        // BuddyPress WebCam view
     154        bp.Views.WebCamAvatar = bp.View.extend( {
     155                tagName: 'div',
     156                id: 'bp-webcam-avatar',
     157                template: bp.template( 'bp-avatar-webcam' ),
     158
     159                events: {
     160                        'click .avatar-webcam-capture': 'captureStream',
     161                        'click .avatar-webcam-save': 'saveCapture',
     162                },
     163
     164                initialize: function() {
     165                        var params;
     166
     167                        if ( navigator.getUserMedia
     168                                || navigator.oGetUserMedia
     169                                || navigator.mozGetUserMedia
     170                                || navigator.webkitGetUserMedia
     171                                || navigator.msGetUserMedia ) {
     172
     173                                // We need to add some cropping stuff to use bp.Avatar.setAvatar()
     174                                params = _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
     175                                        'object',
     176                                        'item_id',
     177                                        'nonces'
     178                                        ), {
     179                                                user_media:  true,
     180                                                w: BP_Uploader.settings.crop.full_w,
     181                                                h: BP_Uploader.settings.crop.full_h,
     182                                                x: 0,
     183                                                y: 0,
     184                                                type: 'camera',
     185                                        }
     186                                );
     187
     188                                this.model.set( params );
     189                        }
     190
     191                        this.on( 'ready', this.useStream, this );
     192                },
     193
     194                useStream:function() {
     195                        // No support for user media... Stop!
     196                        if ( ! this.model.get( 'user_media' ) ) {
     197                                return;
     198                        }
     199
     200                        this.options.video = new bp.Views.WebCamVideo();
     201                        this.options.canvas = new bp.Views.WebCamCanvas();
     202
     203                        this.$el.find( '#avatar-to-crop' ).append( this.options.video.el );
     204                        this.$el.find( '#avatar-crop-pane' ).append( this.options.canvas.el );
     205
     206                        bp.WebCam.params.video = this.options.video.el;
     207                        bp.WebCam.params.canvas = this.options.canvas.el;
     208
     209                        // User Feedback
     210                        bp.WebCam.displayWarning( 'requesting' );
     211
     212                        if ( navigator.getUserMedia ) {
     213                                navigator.getUserMedia( {video:true}, bp.WebCam.gotStream, bp.WebCams.noStream );
     214                        }  else if ( navigator.oGetUserMedia ) {
     215                                navigator.oGetUserMedia( {video:true}, bp.WebCam.gotStream, bp.WebCam.noStream );
     216                        } else if ( navigator.mozGetUserMedia ) {
     217                                navigator.mozGetUserMedia( {video:true}, bp.WebCam.gotStream, bp.WebCam.noStream );
     218                        } else if ( navigator.webkitGetUserMedia ) {
     219                                navigator.webkitGetUserMedia( {video:true}, bp.WebCam.gotStream, bp.WebCam.noStream );
     220                        } else if (navigator.msGetUserMedia) {
     221                                navigator.msGetUserMedia( {video:true, audio:false}, bp.WebCams.gotStream, bp.WebCam.noStream );
     222                        } else {
     223                                // User Feedback
     224                                bp.WebCam.displayWarning( 'errormsg' );
     225                        }
     226                },
     227
     228                captureStream: function( event ) {
     229                        var sx, sc;
     230                        event.preventDefault();
     231
     232                        if ( ! bp.WebCam.params.capture_enable ) {
     233                                // User Feedback
     234                                bp.WebCam.displayWarning( 'loading' );
     235                                return;
     236                        }
     237
     238                        if ( 150 > this.options.video.el.videoHeight || 150 > this.options.video.el.videoWidth ) {
     239                                bp.WebCam.displayWarning( 'videoerror' );
     240                                return;
     241                        }
     242
     243                        // Set the offset
     244                        sc = this.options.video.el.videoHeight;
     245                        sx = ( this.options.video.el.videoWidth - sc ) / 2;
     246
     247                        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' ) );
     248                        bp.WebCam.params.capture = this.options.canvas.el.toDataURL( "image/png" );
     249                        this.model.set( 'url', bp.WebCam.params.capture );
     250
     251                        // User Feedback
     252                        bp.WebCam.displayWarning( 'ready' );
     253                },
     254
     255                saveCapture: function( event ) {
     256                        event.preventDefault();
     257
     258                        if ( ! bp.WebCam.params.capture ) {
     259                                // User Feedback
     260                                bp.WebCam.displayWarning( 'nocapture' );
     261                                return;
     262                        }
     263
     264                        bp.WebCam.stop();
     265                        bp.WebCam.setAvatar( this.model );
     266                },
     267        } );
     268
     269        // BuddyPress Video stream view
     270        bp.Views.WebCamVideo = bp.View.extend( {
     271                tagName: 'video',
     272                id: 'bp-webcam-video',
     273                attributes: {
     274                        autoplay: 'autoplay',
     275                }
     276        } );
     277
     278        // BuddyPress Canvas (capture) view
     279        bp.Views.WebCamCanvas = bp.View.extend( {
     280                tagName: 'canvas',
     281                id: 'bp-webcam-canvas',
     282        } );
     283
     284        bp.WebCam.start();
     285
     286})( bp, jQuery );
  • src/bp-loader.php

    diff --git src/bp-loader.php src/bp-loader.php
    index 4ee261c..94df639 100644
    class BuddyPress { 
    430430                require( $this->plugin_dir . 'bp-core/bp-core-theme-compatibility.php' );
    431431
    432432                // Require all of the BuddyPress core libraries
    433                 require( $this->plugin_dir . 'bp-core/bp-core-dependency.php' );
    434                 require( $this->plugin_dir . 'bp-core/bp-core-actions.php'    );
    435                 require( $this->plugin_dir . 'bp-core/bp-core-caps.php'       );
    436                 require( $this->plugin_dir . 'bp-core/bp-core-cache.php'      );
    437                 require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php'      );
    438                 require( $this->plugin_dir . 'bp-core/bp-core-update.php'     );
    439                 require( $this->plugin_dir . 'bp-core/bp-core-options.php'    );
    440                 require( $this->plugin_dir . 'bp-core/bp-core-classes.php'    );
    441                 require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php'   );
    442                 require( $this->plugin_dir . 'bp-core/bp-core-filters.php'    );
    443                 require( $this->plugin_dir . 'bp-core/bp-core-avatars.php'    );
    444                 require( $this->plugin_dir . 'bp-core/bp-core-widgets.php'    );
    445                 require( $this->plugin_dir . 'bp-core/bp-core-template.php'   );
    446                 require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php'   );
    447                 require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php'   );
    448                 require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php'   );
    449                 require( $this->plugin_dir . 'bp-core/bp-core-component.php'  );
    450                 require( $this->plugin_dir . 'bp-core/bp-core-functions.php'  );
    451                 require( $this->plugin_dir . 'bp-core/bp-core-moderation.php' );
    452                 require( $this->plugin_dir . 'bp-core/bp-core-loader.php'     );
     433                require( $this->plugin_dir . 'bp-core/bp-core-dependency.php'  );
     434                require( $this->plugin_dir . 'bp-core/bp-core-actions.php'     );
     435                require( $this->plugin_dir . 'bp-core/bp-core-caps.php'        );
     436                require( $this->plugin_dir . 'bp-core/bp-core-cache.php'       );
     437                require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php'       );
     438                require( $this->plugin_dir . 'bp-core/bp-core-update.php'      );
     439                require( $this->plugin_dir . 'bp-core/bp-core-options.php'     );
     440                require( $this->plugin_dir . 'bp-core/bp-core-classes.php'     );
     441                require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php'    );
     442                require( $this->plugin_dir . 'bp-core/bp-core-filters.php'     );
     443                require( $this->plugin_dir . 'bp-core/bp-core-attachments.php' );
     444                require( $this->plugin_dir . 'bp-core/bp-core-avatars.php'     );
     445                require( $this->plugin_dir . 'bp-core/bp-core-widgets.php'     );
     446                require( $this->plugin_dir . 'bp-core/bp-core-template.php'    );
     447                require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php'    );
     448                require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php'    );
     449                require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php'    );
     450                require( $this->plugin_dir . 'bp-core/bp-core-component.php'   );
     451                require( $this->plugin_dir . 'bp-core/bp-core-functions.php'   );
     452                require( $this->plugin_dir . 'bp-core/bp-core-moderation.php'  );
     453                require( $this->plugin_dir . 'bp-core/bp-core-loader.php'      );
    453454
    454455                // Skip or load deprecated content
    455456                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, 
    2525div#community-profile-page li.bp-friends-profile-stats:before,
    2626div#community-profile-page li.bp-groups-profile-stats:before,
    2727div#community-profile-page li.bp-blogs-profile-stats:before,
    28 div#community-profile-page a.bp-xprofile-avatar-user-admin:before {
     28div#community-profile-page a.bp-xprofile-avatar-user-admin:before,
     29div#community-profile-page a.bp-xprofile-avatar-user-edit:before {
    2930        font: normal 20px/1 'dashicons';
    3031        speak: none;
    3132        display: inline-block;
    div#community-profile-page a.bp-xprofile-avatar-user-admin:before { 
    6061        content:"\f182";
    6162}
    6263
     64div#community-profile-page a.bp-xprofile-avatar-user-edit:before {
     65        content: "\f107";
     66}
     67
    6368div#community-profile-page div#bp_xprofile_user_admin_avatar div.avatar {
    6469        width:150px;
    6570        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 116a371..d33e961 100644
    class BP_Members_Admin { 
    217217         * @return int
    218218         */
    219219        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();
    221225
    222226                // We'll need a user ID when not on the user admin
    223227                if ( ! empty( $_GET['user_id'] ) ) {
    224                         $user_id = $_GET['user_id'];
     228                        $this->user_id = (int) $_GET['user_id'];
    225229                }
    226230
    227                 return intval( $user_id );
     231                return $this->user_id;
    228232        }
    229233
    230234        /**
  • src/bp-templates/bp-legacy/buddypress/attachments/avatars/camera.php

    diff --git src/bp-templates/bp-legacy/buddypress/attachments/avatars/camera.php src/bp-templates/bp-legacy/buddypress/attachments/avatars/camera.php
    index e69de29..79659c6 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"></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/attachments/avatars/crop.php

    diff --git src/bp-templates/bp-legacy/buddypress/attachments/avatars/crop.php src/bp-templates/bp-legacy/buddypress/attachments/avatars/crop.php
    index e69de29..3f573c3 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">
     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/attachments/avatars/index.php

    diff --git src/bp-templates/bp-legacy/buddypress/attachments/avatars/index.php src/bp-templates/bp-legacy/buddypress/attachments/avatars/index.php
    index e69de29..45a0be8 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 */
     19do_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_get_template_part( 'attachments/uploader' ); ?>
     30
     31<?php bp_get_template_part( 'attachments/avatars/crop' ); ?>
     32
     33<?php bp_get_template_part( 'attachments/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/attachments/uploader.php

    diff --git src/bp-templates/bp-legacy/buddypress/attachments/uploader.php src/bp-templates/bp-legacy/buddypress/attachments/uploader.php
    index e69de29..4c2b15b 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' ); ?></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..f9cc672 100644
     
    6060
    6161
    6262                                        <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 } ?> />
    6464                                                <strong><?php _e( 'This is a private group', 'buddypress' ); ?></strong>
    6565                                        </label>
    6666                                        <ul>
     
    7171
    7272
    7373                                        <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 } ?> />
    7575                                                <strong><?php _e('This is a hidden group', 'buddypress' ); ?></strong>
    7676                                        </label>
    7777                                        <ul>
     
    153153                                                <p><?php _e( 'To skip the group profile photo upload process, hit the "Next Step" button.', 'buddypress' ); ?></p>
    154154                                        </div><!-- .main-column -->
    155155
     156                                        <?php
     157                                        /**
     158                                         * Load the Avatar UI templates
     159                                         *
     160                                         * @since  BuddyPress (2.3.0)
     161                                         */
     162                                        bp_core_avatar_get_template_part(); ?>
     163
    156164                                <?php endif; ?>
    157165
    158166                                <?php if ( 'crop-image' == bp_get_avatar_admin_step() ) : ?>
     
    306314
    307315</div>
    308316
    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..1655959 100644
     
    140140
    141141                        <?php endif; ?>
    142142
     143                        <?php
     144                        /**
     145                         * Load the Avatar UI templates
     146                         *
     147                         * @since  BuddyPress (2.3.0)
     148                         */
     149                        bp_core_avatar_get_template_part(); ?>
     150
    143151                        <?php wp_nonce_field( 'bp_avatar_upload' ); ?>
    144152
    145153        <?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..32cb0ba 100644
     
    5050
    5151        </form>
    5252
     53        <?php
     54        /**
     55         * Load the Avatar UI templates
     56         *
     57         * @since  BuddyPress (2.3.0)
     58         */
     59        bp_core_avatar_get_template_part(); ?>
     60
    5361<?php else : ?>
    5462
    5563        <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 97904d4..c51571b 100644
    class BP_XProfile_User_Admin { 
    620620         * @since BuddyPress (2.0.0)
    621621         */
    622622        private function setup_actions() {
     623                // Enqueue scripts
     624                add_action( 'bp_members_admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10, 1 );
    623625
    624626                // Register the metabox in Member's community admin profile
    625627                add_action( 'bp_members_admin_xprofile_metabox', array( $this, 'register_metaboxes' ), 10, 3 );
    class BP_XProfile_User_Admin { 
    629631        }
    630632
    631633        /**
     634         * Enqueue needed scripts.
     635         *
     636         * @access public
     637         * @since BuddyPress (2.3.0)
     638         */
     639        public function enqueue_scripts( $screen_id ) {
     640                if ( false === strpos( $screen_id, 'users_page_bp-profile-edit' ) && false === strpos( $screen_id, 'profile_page_bp-profile-edit' ) ) {
     641                        return;
     642                }
     643
     644                /**
     645                 * Get Thickbox
     646                 *
     647                 * We cannot simply use add_thickbox() here as WordPress is not playing
     648                 * nice with Thickbox width/height see https://core.trac.wordpress.org/ticket/17249
     649                 * Using media-upload might be interesting in the future for the send to editor stuff
     650                 * and we make sure the tb_window is wide enougth
     651                 */
     652                wp_enqueue_style ( 'thickbox' );
     653                wp_enqueue_script( 'media-upload' );
     654
     655                // Get Avatar Uploader
     656                bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' );
     657        }
     658
     659        /**
    632660         * Register the xProfile metabox on Community Profile admin page.
    633661         *
    634662         * @access public
    class BP_XProfile_User_Admin { 
    952980         * @param WP_User $user The WP_User object for the user being edited.
    953981         */
    954982        public function user_admin_avatar_metabox( $user = null ) {
    955 
     983                // Bail if no user id
    956984                if ( empty( $user->ID ) ) {
    957985                        return;
    958                 } ?>
     986                }
     987
     988                // We need to make sure WP_USE_THEMES is set to true to use bp_locate_template()
     989                if ( ! defined( 'WP_USE_THEMES' ) ) {
     990                        define( 'WP_USE_THEMES', true );
     991                }
     992                ?>
    959993
    960994                <div class="avatar">
    961995
    class BP_XProfile_User_Admin { 
    9841018
    9851019                        <?php endif; ?>
    9861020
     1021                        <?php // Avatar Editor ;?>
     1022                        <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>
     1023
     1024                        <div id="bp-xprofile-avatar-editor" style="display:none;">
     1025                                <?php bp_get_template_part( 'attachments/avatars/index' ); ?>
     1026                        </div>
    9871027                </div>
    9881028                <?php
    9891029        }