Skip to:
Content

BuddyPress.org

Ticket #6570: 6570.04.patch

File 6570.04.patch, 131.5 KB (added by imath, 5 years ago)
  • src/bp-core/admin/bp-core-admin-settings.php

    diff --git src/bp-core/admin/bp-core-admin-settings.php src/bp-core/admin/bp-core-admin-settings.php
    index 1550c0d..5cac7aa 100644
    function bp_admin_setting_callback_avatar_uploads() { 
    160160<?php
    161161}
    162162
     163/**
     164 * Allow members to upload cover images field.
     165 *
     166 * @since 2.4.0
     167 */
     168function bp_admin_setting_callback_cover_image_uploads() {
     169?>
     170        <input id="bp-disable-cover-image-uploads" name="bp-disable-cover-image-uploads" type="checkbox" value="1" <?php checked( ! bp_disable_cover_image_uploads() ); ?> />
     171        <label for="bp-disable-cover-image-uploads"><?php _e( 'Allow registered members to upload cover images', 'buddypress' ); ?></label>
     172<?php
     173}
     174
    163175/** Groups Section ************************************************************/
    164176
    165177/**
    function bp_admin_setting_callback_group_avatar_uploads() { 
    198210<?php
    199211}
    200212
     213/**
     214 * 'Enable group cover images' field markup.
     215 *
     216 * @since 2.4.0
     217 */
     218function bp_admin_setting_callback_group_cover_image_uploads() {
     219?>
     220        <input id="bp-disable-group-cover-image-uploads" name="bp-disable-group-cover-image-uploads" type="checkbox" value="1" <?php checked( ! bp_disable_group_cover_image_uploads() ); ?> />
     221        <label for="bp-disable-group-cover-image-uploads"><?php _e( 'Allow customizable cover images for groups', 'buddypress' ); ?></label>
     222<?php
     223}
     224
    201225/** Forums Section ************************************************************/
    202226
    203227/**
    function bp_core_admin_settings_save() { 
    300324                $legacy_options = array(
    301325                        'bp-disable-account-deletion',
    302326                        'bp-disable-avatar-uploads',
     327                        'bp-disable-cover-image-uploads',
    303328                        'bp-disable-group-avatar-uploads',
     329                        'bp-disable-group-cover-image-uploads',
    304330                        'bp_disable_blogforum_comments',
    305331                        'bp-disable-profile-sync',
    306332                        'bp_restrict_group_creation',
  • src/bp-core/bp-core-actions.php

    diff --git src/bp-core/bp-core-actions.php src/bp-core/bp-core-actions.php
    index 3612378..5778efd 100644
    add_action( 'bp_template_redirect', 'bp_post_request', 10 ); 
    9393add_action( 'bp_template_redirect', 'bp_get_request',        10 );
    9494
    9595/**
    96  * Add the BuddyPress functions file.
     96 * Add the BuddyPress functions file and the Theme Compat Default features.
    9797 */
    98 add_action( 'bp_after_setup_theme', 'bp_load_theme_functions', 1 );
     98add_action( 'bp_after_setup_theme', 'bp_load_theme_functions',                    1 );
     99add_action( 'bp_after_setup_theme', 'bp_register_theme_compat_default_features', 10 );
    99100
    100101// Load the admin.
    101102if ( is_admin() ) {
  • src/bp-core/bp-core-admin.php

    diff --git src/bp-core/bp-core-admin.php src/bp-core/bp-core-admin.php
    index f220010..6859f57 100644
    class BP_Admin { 
    338338                        // Add the main section
    339339                        add_settings_section( 'bp_xprofile', _x( 'Profile Settings', 'BuddyPress setting tab', 'buddypress' ), 'bp_admin_setting_callback_xprofile_section', 'buddypress' );
    340340
     341                        // Avatars
    341342                        add_settings_field( 'bp-disable-avatar-uploads', __( 'Profile Photo Uploads', 'buddypress' ), 'bp_admin_setting_callback_avatar_uploads', 'buddypress', 'bp_xprofile' );
    342343                        register_setting( 'buddypress', 'bp-disable-avatar-uploads', 'intval' );
    343344
     345                        // Cover images
     346                        if ( bp_is_active( 'xprofile', 'cover_image' ) ) {
     347                                add_settings_field( 'bp-disable-cover-image-uploads', __( 'Cover Image Uploads', 'buddypress' ), 'bp_admin_setting_callback_cover_image_uploads', 'buddypress', 'bp_xprofile' );
     348                                register_setting( 'buddypress', 'bp-disable-cover-image-uploads', 'intval' );
     349                        }
     350
    344351                        // Profile sync setting
    345352                        add_settings_field( 'bp-disable-profile-sync',   __( 'Profile Syncing',  'buddypress' ), 'bp_admin_setting_callback_profile_sync', 'buddypress', 'bp_xprofile' );
    346353                        register_setting  ( 'buddypress', 'bp-disable-profile-sync', 'intval' );
    class BP_Admin { 
    360367                        // Allow group avatars.
    361368                        add_settings_field( 'bp-disable-group-avatar-uploads', __( 'Group Photo Uploads', 'buddypress' ), 'bp_admin_setting_callback_group_avatar_uploads', 'buddypress', 'bp_groups' );
    362369                        register_setting( 'buddypress', 'bp-disable-group-avatar-uploads', 'intval' );
     370
     371                        // Allow group cover images.
     372                        if ( bp_is_active( 'groups', 'cover_image' ) ) {
     373                                add_settings_field( 'bp-disable-group-cover-image-uploads', __( 'Group Cover Image Uploads', 'buddypress' ), 'bp_admin_setting_callback_group_cover_image_uploads', 'buddypress', 'bp_groups' );
     374                                register_setting( 'buddypress', 'bp-disable-group-cover-image-uploads', 'intval' );
     375                        }
    363376                }
    364377
    365378                /** Forums ************************************************************/
  • src/bp-core/bp-core-attachments.php

    diff --git src/bp-core/bp-core-attachments.php src/bp-core/bp-core-attachments.php
    index 7646b80..ba37de6 100644
    function bp_attachments_enqueue_scripts( $class = '' ) { 
    257257                 * @param string $object the object the avatar belongs to (eg: user or group)
    258258                 */
    259259                $settings['nav'] = bp_sort_by_key( apply_filters( 'bp_attachments_avatar_nav', $avatar_nav, $object ), 'order', 'num' );
     260
     261        // Specific to BuddyPress cover images
     262        } elseif ( 'bp_cover_image_upload' === $defaults['multipart_params']['action'] ) {
     263
     264                // Cover images only need 1 file and 1 only!
     265                $defaults['multi_selection'] = false;
     266
     267                // Default cover component is xprofile
     268                $cover_component = 'xprofile';
     269
     270                // Get the object we're editing the cover image of
     271                $object = $defaults['multipart_params']['bp_params']['object'];
     272
     273                // Set the cover component according to the object
     274                if ( 'group' === $object ) {
     275                        $cover_component = 'groups';
     276                } elseif ( 'user' !== $object ) {
     277                        $cover_component = apply_filters( 'bp_attachments_cover_image_ui_component', $cover_component );
     278                }
     279                // Get cover image advised dimensions
     280                $cover_dimensions = bp_attachments_get_cover_image_dimensions( $cover_component );
     281
     282                // Set warning messages
     283                $strings['cover_image_warnings'] = apply_filters( 'bp_attachments_cover_image_ui_warnings', array(
     284                        'dimensions'  => sprintf(
     285                                        __( 'For better results, make sure to upload an image having a width >= %1$s px and a height >= %2$s px.', 'buddypress' ),
     286                                        (int) $cover_dimensions['width'],
     287                                        (int) $cover_dimensions['height']
     288                                ),
     289                ) );
    260290        }
    261291
    262292        // Set Plupload settings
    function bp_attachments_enqueue_scripts( $class = '' ) { 
    317347function bp_attachments_current_user_can( $capability, $args = array() ) {
    318348        $can = false;
    319349
    320         if ( 'edit_avatar' === $capability ) {
     350        if ( 'edit_avatar' === $capability || 'edit_cover_image' === $capability ) {
    321351                /**
    322352                 * Needed avatar arguments are set.
    323353                 */
    function bp_attachments_get_template_part( $slug ) { 
    410440                bp_get_template_part( $attachment_template_part );
    411441        }
    412442}
     443
     444/** Cover Image ***************************************************************/
     445
     446/**
     447 * Get the cover image settings
     448 *
     449 * @since  2.4.0
     450 *
     451 * @param  string $component the component to get the settings for ("xprofile" for user or "groups")
     452 * @return array            the cover image settings
     453 */
     454function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) {
     455        // Default parameters
     456        $args = array();
     457
     458        // First look in BP Theme Compat
     459        $cover_image = bp_get_theme_compat_feature( 'cover_image' );
     460
     461        if ( ! empty( $cover_image ) ) {
     462                $args = (array) $cover_image;
     463        }
     464
     465        /**
     466         * Then let people override/set the feature using this dynamic filter
     467         *
     468         * eg: for the user's profile cover image use :
     469         * add_filter( 'bp_before_xprofile_cover_image_settings_parse_args', 'your_filter', 10, 1 );
     470         *
     471         * @since  2.4.0
     472         *
     473         * @param array $settings the cover image settings
     474         */
     475        $settings = bp_parse_args( $args, array(
     476                'components'    => array(),
     477                'width'         => 1300,
     478                'height'        => 225,
     479                'callback'      => '',
     480                'theme_handle'  => '',
     481                'default_cover' => '',
     482        ), $component . '_cover_image_settings' );
     483
     484        if ( empty( $settings['components'] ) || empty( $settings['callback'] ) || empty( $settings['theme_handle'] ) ) {
     485                return false;
     486        }
     487
     488        // Current component is not supported
     489        if ( ! in_array( $component, $settings['components'] ) ) {
     490                return false;
     491        }
     492
     493        // Finally return the settings
     494        return $settings;
     495}
     496
     497/**
     498 * Get cover image Width and Height
     499 *
     500 * @since  2.4.0
     501 *
     502 * @param  string $component the BuddyPress component concerned ("xprofile" for user or "groups")
     503 * @return array             an associative array containing the advised width and height for the cover image
     504 */
     505function bp_attachments_get_cover_image_dimensions( $component = 'xprofile' ) {
     506        // Let's prevent notices when setting the warning strings
     507        $default = array( 'width' => 0, 'height' => 0 );
     508
     509        $settings = bp_attachments_get_cover_image_settings( $component );
     510
     511        if ( empty( $settings ) ) {
     512                return false;
     513        }
     514
     515        // Get width and height
     516        $wh = array_intersect_key( $settings, $default );
     517
     518        /**
     519         * Filter here to edit the cover image dimensions if needed.
     520         *
     521         * @since  2.4.0
     522         *
     523         * @param  array  $wh        an associative array containing the width and height values
     524         * @param  array  $settings  an associative array containing all the feature settings
     525         * @param  string $compnent  the requested component
     526         */
     527        return apply_filters( 'bp_attachments_get_cover_image_dimensions', $wh, $settings, $component );
     528}
     529
     530/**
     531 * Are we on a page to edit a cover image ?
     532 *
     533 * @since  2.4.0
     534 *
     535 * @todo  The Groups single item part
     536 * @return bool True if on a page to edit a cover image, false otherwise
     537 */
     538function bp_attachments_cover_image_is_edit() {
     539        $retval = false;
     540
     541        $current_component = bp_current_component();
     542        if ( 'profile' === $current_component ) {
     543                $current_component = 'xprofile';
     544        }
     545
     546        if ( ! bp_is_active( $current_component, 'cover_image' ) ) {
     547                return $retval;
     548        }
     549
     550        if ( bp_is_user_change_cover_image() ) {
     551                $retval = ! bp_disable_cover_image_uploads();
     552        }
     553
     554        if ( ( bp_is_group_admin_page() && 'group-cover-image' == bp_get_group_current_admin_tab() )
     555                || ( bp_is_group_create() && bp_is_group_creation_step( 'group-cover-image' ) ) ) {
     556                $retval = ! bp_disable_group_cover_image_uploads();
     557        }
     558
     559        return apply_filters( 'bp_attachments_cover_image_is_edit', $retval, $current_component );
     560}
     561
     562/**
     563 * Get the url or the path for a type of attachment
     564 *
     565 * @since  2.4.0
     566 *
     567 * @param  string $data whether to get the url or the path
     568 * @param  array  $args {
     569 *     @type string $object_dir  The object dir (eg: members/groups). Defaults to members.
     570 *     @type int    $item_id     The object id (eg: a user or a group id). Defaults to current user.
     571 *     @type string $type        The type of the attachment which is also the subdir where files are saved.
     572 *                               Defaults to 'cover-image'
     573 *     @type string $file        The name of the file.
     574 * }
     575 * @return string|bool the url or the path to the attachment, false otherwise
     576 */
     577function bp_attachments_get_attachment( $data = 'url', $args = array() ) {
     578        // Default value
     579        $attachment_data = false;
     580
     581        $r = bp_parse_args( $args, array(
     582                'object_dir' => 'members',
     583                'item_id'    => bp_loggedin_user_id(),
     584                'type'       => 'cover-image',
     585                'file'       => '',
     586        ), 'attachments_get_attachment_src' );
     587
     588        // Get BuddyPress Upload Dir
     589        $bp_upload_dir = bp_upload_dir();
     590
     591        $type_subdir = 'buddypress/' . $r['object_dir'] . '/' . $r['item_id'] . '/' . $r['type'];
     592        $type_dir    = trailingslashit( $bp_upload_dir['basedir'] ) . $type_subdir;
     593
     594        if ( ! is_dir( $type_dir ) ) {
     595                return $attachment_data;
     596        }
     597
     598        if ( ! empty( $r['file'] ) ) {
     599                if ( ! file_exists( trailingslashit( $type_dir ) . $r['file'] ) ) {
     600                        return $attachment_data;
     601                }
     602
     603                if ( 'url' === $data ) {
     604                        $attachment_data = trailingslashit( $bp_upload_dir['baseurl'] ) . $type_subdir . '/' . $r['file'];
     605                } else {
     606                        $attachment_data = trailingslashit( $type_dir ) . $r['file'];
     607                }
     608
     609        } else {
     610                $file = false;
     611
     612                // Open the directory and get the first file
     613                if ( $att_dir = opendir( $type_dir ) ) {
     614
     615                        while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) {
     616                                // Look for the first file having the type in its name
     617                                if ( false !== strpos( $attachment_file, $r['type'] ) && empty( $file ) ) {
     618                                        $file = $attachment_file;
     619                                        break;
     620                                }
     621                        }
     622                }
     623
     624                if ( empty( $file ) ) {
     625                        return $attachment_data;
     626                }
     627
     628                if ( 'url' === $data ) {
     629                        $attachment_data = trailingslashit( $bp_upload_dir['baseurl'] ) . $type_subdir . '/' . $file;
     630                } else {
     631                        $attachment_data = trailingslashit( $type_dir ) . $file;
     632                }
     633        }
     634
     635        return $attachment_data;
     636}
     637
     638/**
     639 * Does the user has a cover image ?
     640 *
     641 * @since  2.4.0
     642 *
     643 * @param  int $user_id
     644 * @return bool True if the user has a cover image, false otherwise
     645 */
     646function bp_attachments_get_user_has_cover_image( $user_id = 0 ) {
     647        if ( empty( $user_id ) ) {
     648                $user_id = bp_displayed_user_id();
     649        }
     650
     651        $cover_src = bp_attachments_get_attachment( 'url', array(
     652                'item_id'   => $user_id,
     653        ) );
     654
     655        return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $user_id );
     656}
     657
     658/**
     659 * Does the group has a cover image ?
     660 *
     661 * @since  2.4.0
     662 *
     663 * @param  int $group_id
     664 * @return bool True if the group has a cover image, false otherwise
     665 */
     666function bp_attachments_get_group_has_cover_image( $group_id = 0 ) {
     667        if ( empty( $group_id ) ) {
     668                $group_id = bp_get_current_group_id();
     669        }
     670
     671        $cover_src = bp_attachments_get_attachment( 'url', array(
     672                'object_dir' => 'groups',
     673                'item_id'    => $group_id,
     674        ) );
     675
     676        return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $group_id );
     677}
     678
     679/**
     680 * Delete an attachment for the given arguments
     681 *
     682 * @since  2.4.0
     683 *
     684 * @param  array $args
     685 * @see    bp_attachments_get_attachment() For more information on accepted arguments.
     686 * @return bool True if the attachment was deleted, false otherwise
     687 */
     688function bp_attachments_delete_file( $args = array() ) {
     689        $cover_path = bp_attachments_get_attachment( 'path', $args );
     690
     691        if ( empty( $cover_path ) ) {
     692                return false;
     693        }
     694
     695        @unlink( $cover_path );
     696        return true;
     697}
     698
     699/**
     700 * Ajax Upload and set a cover image
     701 *
     702 * @since  2.4.0
     703 *
     704 * @return  string|null A json object containing success data if the upload succeeded
     705 *                      error message otherwise.
     706 */
     707function bp_attachments_cover_image_ajax_upload() {
     708        // Bail if not a POST action
     709        if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
     710                wp_die();
     711        }
     712
     713        /**
     714         * Sending the json response will be different if
     715         * the current Plupload runtime is html4
     716         */
     717        $is_html4 = false;
     718        if ( ! empty( $_POST['html4' ] ) ) {
     719                $is_html4 = true;
     720        }
     721
     722        // Check the nonce
     723        check_admin_referer( 'bp-uploader' );
     724
     725        // Init the BuddyPress parameters
     726        $bp_params = array();
     727
     728        // We need it to carry on
     729        if ( ! empty( $_POST['bp_params' ] ) ) {
     730                $bp_params = bp_parse_args( $_POST['bp_params' ], array(
     731                        'object'  => 'user',
     732                        'item_id' => bp_loggedin_user_id(),
     733                ), 'attachments_cover_image_ajax_upload' );
     734        } else {
     735                bp_attachments_json_response( false, $is_html4 );
     736        }
     737
     738        // We need the object to set the uploads dir filter
     739        if ( empty( $bp_params['object'] ) ) {
     740                bp_attachments_json_response( false, $is_html4 );
     741        }
     742
     743        // Capability check
     744        if ( ! bp_attachments_current_user_can( 'edit_cover_image', $bp_params ) ) {
     745                bp_attachments_json_response( false, $is_html4 );
     746        }
     747
     748        $bp          = buddypress();
     749        $needs_reset = array();
     750
     751        // Default object data
     752        $object_data = array( 'dir' => 'members', 'component' => 'xprofile' );
     753        if ( 'group' === $bp_params['object'] ) {
     754                $object_data = array( 'dir' => 'groups', 'component' => 'groups' );
     755
     756                if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
     757                        $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
     758                        $bp->groups->current_group = groups_get_group( array(
     759                                'group_id'        => $bp_params['item_id'],
     760                                'populate_extras' => false,
     761                        ) );
     762                }
     763        } elseif ( 'user' !== $bp_params['object'] ) {
     764                $object_data = apply_filters( 'bp_attachments_cover_image_object_dir', $object_data, $bp_params['object'] );
     765
     766                if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) {
     767                        $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user );
     768                        $bp->displayed_user->id = $bp_params['item_id'];
     769                }
     770        }
     771
     772        $cover_image_attachment = new BP_Attachment_Cover_Image();
     773        $uploaded = $cover_image_attachment->upload( $_FILES );
     774
     775        // Reset objects
     776        if ( ! empty( $needs_reset ) ) {
     777                if ( ! empty( $needs_reset['component'] ) ) {
     778                        $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value'];
     779                } else {
     780                        $bp->{$needs_reset['key']} = $needs_reset['value'];
     781                }
     782        }
     783
     784        if ( ! empty( $uploaded['error'] ) ) {
     785                // Upload error response
     786                bp_attachments_json_response( false, $is_html4, array(
     787                        'type'    => 'upload_error',
     788                        'message' => sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $uploaded['error'] ),
     789                ) );
     790        }
     791
     792        // Get advised dimensions for the cover image
     793        $dimensions = bp_attachments_get_cover_image_dimensions( $object_data['component'] );
     794
     795        // Resize the image so that it fit with the cover image dimensions
     796        $cover_image  = $cover_image_attachment->fit( $uploaded['file'], $dimensions );
     797        $is_too_small = false;
     798
     799        // Image is too small in width and height
     800        if ( empty( $cover_image ) ) {
     801                $cover_file = $cover_image_attachment->generate_filename( $uploaded['file'] );
     802                @rename( $uploaded['file'], $cover_file );
     803
     804                // It's too small!
     805                $is_too_small = true;
     806        } elseif ( ! empty( $cover_image['path'] ) ) {
     807                $cover_file   = $cover_image['path'];
     808
     809                if ( $cover_image['width'] < $dimensions['width'] || $cover_image['height'] < $dimensions['height'] ) {
     810                        $is_too_small = true;
     811                }
     812        }
     813
     814        // Default error message
     815        $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
     816
     817        if ( empty( $cover_file ) ) {
     818                // Upload error response
     819                bp_attachments_json_response( false, $is_html4, array(
     820                        'type'    => 'upload_error',
     821                        'message' => __( 'There was a problem uploading the cover image.', 'buddypress' ),
     822                ) );
     823        }
     824
     825        // Set the basename for the cover file
     826        $cover_basename = wp_basename( $cover_file );
     827
     828        // Get BuddyPress Upload Dir
     829        $bp_upload_dir = bp_upload_dir();
     830
     831        $cover_subdir = 'buddypress/' . $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image';
     832        $cover_dir    = trailingslashit( $bp_upload_dir['basedir'] ) . $cover_subdir;
     833
     834        if ( ! is_dir( $cover_dir ) ) {
     835                // Upload error response
     836                bp_attachments_json_response( false, $is_html4, array(
     837                        'type'    => 'upload_error',
     838                        'message' => $error_message,
     839                ) );
     840        }
     841
     842        // Clean up the cover dir to only keep the uploaded cover image
     843        if ( $att_dir = opendir( $cover_dir ) ) {
     844                while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) {
     845                        // skip directories and the new cover image
     846                        if ( 2 < strlen( $attachment_file ) && 0 !== strpos( $attachment_file, '.' ) && $cover_basename !== $attachment_file ) {
     847                                @unlink( $cover_dir . '/' . $attachment_file );
     848                        }
     849                }
     850        }
     851
     852        // Build the url to the file
     853        $cover_url = trailingslashit( $bp_upload_dir['baseurl'] ) . $cover_subdir . '/' . $cover_basename;
     854
     855        // Init Feedback code, 1 is success
     856        $feedback_code = 1;
     857
     858        // 0 is the size warning
     859        if ( $is_too_small ) {
     860                $feedback_code = 0;
     861        }
     862
     863        // Set the name of the file
     864        $name = $_FILES['file']['name'];
     865        $name_parts = pathinfo( $name );
     866        $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) );
     867
     868        // Finally return the cover image url to the UI
     869        bp_attachments_json_response( true, $is_html4, array(
     870                'name'          => $name,
     871                'url'           => $cover_url,
     872                'feedback_code' => $feedback_code,
     873        ) );
     874}
     875add_action( 'wp_ajax_bp_cover_image_upload', 'bp_attachments_cover_image_ajax_upload' );
     876
     877/**
     878 * Ajax delete a cover image for a given object and item id.
     879 *
     880 * @since 2.4.0
     881 *
     882 * @return string|null A json object containing success data if the cover image was deleted
     883 *                     error message otherwise.
     884 */
     885function bp_attachments_cover_image_ajax_delete() {
     886        // Bail if not a POST action.
     887        if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
     888                wp_send_json_error();
     889        }
     890
     891        $cover_image_data = $_POST;
     892
     893        if ( empty( $cover_image_data['object'] ) || empty( $cover_image_data['item_id'] ) ) {
     894                wp_send_json_error();
     895        }
     896
     897        // Check the nonce
     898        check_admin_referer( 'bp_delete_cover_image', 'nonce' );
     899
     900        // Capability check
     901        if ( ! bp_attachments_current_user_can( 'edit_cover_image', $cover_image_data ) ) {
     902                wp_send_json_error();
     903        }
     904
     905        // Set object for the user's case
     906        if ( 'user' === $cover_image_data['object'] ) {
     907                $component = 'xprofile';
     908                $dir       = 'members';
     909
     910        // Set it for any other cases
     911        } else {
     912                $component = $cover_image_data['object'] . 's';
     913                $dir       = $component;
     914        }
     915
     916        // Handle delete
     917        if ( bp_attachments_delete_file( array( 'item_id' => $cover_image_data['item_id'], 'object_dir' => $dir, 'type' => 'cover-image' ) ) ) {
     918
     919                // Defaults no cover image
     920                $response         = array(
     921                        'reset_url'     => '',
     922                        'feedback_code' => 3 ,
     923                );
     924
     925                // Get cover image settings in case there's a default header
     926                $cover_params = bp_attachments_get_cover_image_settings( $component );
     927
     928                // Check if there's a default cover
     929                if ( ! empty( $cover_params['default_cover'] ) ) {
     930                        $response['reset_url'] = $cover_params['default_cover'];
     931                }
     932
     933                // Finally send the reset url
     934                wp_send_json_success( $response );
     935
     936        } else {
     937                wp_send_json_error( array(
     938                        'feedback_code' => 2,
     939                ) );
     940        }
     941}
     942add_action( 'wp_ajax_bp_cover_image_delete', 'bp_attachments_cover_image_ajax_delete' );
  • src/bp-core/bp-core-catchuri.php

    diff --git src/bp-core/bp-core-catchuri.php src/bp-core/bp-core-catchuri.php
    index e0cdf60..836ae7d 100644
    function bp_core_load_template( $templates ) { 
    402402        }
    403403
    404404        /**
    405          * Filters the template locations.
    406          *
    407          * Allows plugins to alter where the template files are located.
    408          *
    409          * @since BuddyPress (1.1.0)
    410          *
    411          * @param string $template           Located template path.
    412          * @param array  $filtered_templates Array of templates to attempt to load.
     405         * It's a modal, use the specific template
    413406         */
    414         $located_template = apply_filters( 'bp_located_template', $template, $filtered_templates );
     407        if ( bp_is_modal() ) {
     408                $located_template = bp_locate_template( reset( $filtered_templates ), false );
     409        } else {
     410                /**
     411                 * Filters the template locations.
     412                 *
     413                 * Allows plugins to alter where the template files are located.
     414                 *
     415                 * @since BuddyPress (1.1.0)
     416                 *
     417                 * @param string $template           Located template path.
     418                 * @param array  $filtered_templates Array of templates to attempt to load.
     419                 */
     420                $located_template = apply_filters( 'bp_located_template', $template, $filtered_templates );
     421        }
     422
    415423        if ( !empty( $located_template ) ) {
    416424                // Template was located, lets set this as a valid page and not a 404.
    417425                status_header( 200 );
  • src/bp-core/bp-core-classes.php

    diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php
    index 7d1e0be..0da6fbb 100644
    require dirname( __FILE__ ) . '/classes/class-bp-recursive-query.php'; 
    2323require dirname( __FILE__ ) . '/classes/class-bp-media-extractor.php';
    2424require dirname( __FILE__ ) . '/classes/class-bp-attachment.php';
    2525require dirname( __FILE__ ) . '/classes/class-bp-attachment-avatar.php';
     26require dirname( __FILE__ ) . '/classes/class-bp-attachment-cover-image.php';
  • src/bp-core/bp-core-cssjs.php

    diff --git src/bp-core/bp-core-cssjs.php src/bp-core/bp-core-cssjs.php
    index 392f926..ebeab51 100644
    function bp_core_register_common_scripts() { 
    4343                'bp-avatar'   => array( 'file' => "{$url}avatar{$min}.js", 'dependencies' => array( 'jcrop' ), 'footer' => true ),
    4444                'bp-webcam'   => array( 'file' => "{$url}webcam{$min}.js", 'dependencies' => array( 'bp-avatar' ), 'footer' => true ),
    4545
     46                // 2.4
     47                'bp-cover-image' => array( 'file' => "{$url}cover-image{$min}.js", 'dependencies' => array(), 'footer' => true ),
     48
     49                // 2.4
     50                'bp-modal' => array( 'file' => "{$url}modal{$min}.js", 'dependencies' => array( 'thickbox' ), 'footer' => true ),
     51
    4652        ) );
    4753
    4854        $version = bp_get_version();
    function bp_core_register_common_styles() { 
    8793                        'file'         => "{$url}avatar{$min}.css",
    8894                        'dependencies' => array( 'jcrop' )
    8995                ),
     96                'bp-modal' => array(
     97                        'file'         => "{$url}modal{$min}.css",
     98                        'dependencies' => array( 'thickbox' )
     99                ),
    90100        ) );
    91101
    92102        foreach ( $styles as $id => $style ) {
    function bp_core_avatar_scripts() { 
    140150add_action( 'bp_enqueue_scripts', 'bp_core_avatar_scripts' );
    141151
    142152/**
     153 * Enqueues the css and js required by the Cover Image UI.
     154 *
     155 * @since  2.4.0
     156 */
     157function bp_core_cover_image_scripts() {
     158        if ( ! bp_attachments_cover_image_is_edit() ) {
     159                return false;
     160        }
     161
     162        // Enqueue the Attachments scripts for the Cover Image UI
     163        bp_attachments_enqueue_scripts( 'BP_Attachment_Cover_Image' );
     164}
     165add_action( 'bp_enqueue_scripts', 'bp_core_cover_image_scripts' );
     166
     167/**
    143168 * Enqueues jCrop library and hooks BP's custom cropper JS.
    144169 */
    145170function bp_core_add_jquery_cropper() {
    function bp_core_get_js_dependencies() { 
    337362                'bp-jquery-scroll-to'
    338363        ) );
    339364}
     365
     366/**
     367 * Add inline css to display the component's single item cover image
     368 *
     369 * @since 2.4.0
     370 *
     371 * @param  bool $return true to get the inline css
     372 * @return string|array the inline css or an associative array containing
     373 *                      the css rules and the style handle
     374 */
     375function bp_add_cover_image_inline_css( $return = false ) {
     376        $bp = buddypress();
     377
     378        // Find the component of the current item
     379        if ( bp_is_user() ) {
     380
     381                // User is not allowed to upload cover images
     382                // no need to carry on
     383                if ( bp_disable_cover_image_uploads() ) {
     384                        return;
     385                }
     386
     387                $cover_image_object = array(
     388                        'component' => 'xprofile',
     389                        'object' => $bp->displayed_user
     390                );
     391        } elseif ( bp_is_group() ) {
     392
     393                // Users are not allowed to upload cover images for their groups
     394                // no need to carry on
     395                if ( bp_disable_group_cover_image_uploads() ) {
     396                        return;
     397                }
     398
     399                $cover_image_object = array(
     400                        'component' =>'groups',
     401                        'object' => $bp->groups->current_group
     402                );
     403        } else {
     404                $cover_image_object = apply_filters( 'bp_current_cover_image_object_inline_css', array() );
     405        }
     406
     407        // Bail if no component were found.
     408        if ( empty( $cover_image_object['component'] ) || empty( $cover_image_object['object'] ) || ! bp_is_active( $cover_image_object['component'], 'cover_image' ) ) {
     409                return;
     410        }
     411
     412        // Get the settings of the cover image feature for the current component
     413        $params = bp_attachments_get_cover_image_settings( $cover_image_object['component'] );
     414
     415        // Bail if no params.
     416        if ( empty( $params ) ) {
     417                return;
     418        }
     419
     420        // Try to call the callback
     421        if ( is_callable( $params['callback'] ) ) {
     422
     423                $object_dir = $cover_image_object['component'];
     424
     425                if ( 'xprofile' === $object_dir ) {
     426                        $object_dir = 'members';
     427                }
     428
     429                $cover_image = bp_attachments_get_attachment( 'url', array(
     430                        'object_dir' => $object_dir,
     431                        'item_id'    => $cover_image_object['object']->id,
     432                ) );
     433
     434                if ( empty( $cover_image ) ) {
     435                        if ( ! empty( $params['default_cover'] ) ) {
     436                                $cover_image = $params['default_cover'];
     437                        }
     438                }
     439
     440                $inline_css = call_user_func_array( $params['callback'], array( array(
     441                        'cover_image' => esc_url( $cover_image ),
     442                        'component'   => sanitize_key( $cover_image_object['component'] ),
     443                        'object_id'   => (int) $cover_image_object['object']->id,
     444                        'width'       => (int) $params['width'],
     445                        'height'      => (int) $params['height'],
     446                ) ) );
     447
     448                // Finally add the inline css to the handle
     449                if ( ! empty( $inline_css ) ) {
     450
     451                        // Used to get the css when Ajax setting the cover image
     452                        if ( true === $return ) {
     453                                return array(
     454                                        'css_rules' => '<style type="text/css">' . "\n" . $inline_css . "\n" . '</style>',
     455                                        'handle'    => $params['theme_handle'],
     456                                );
     457                        }
     458
     459                        wp_add_inline_style( $params['theme_handle'], $inline_css );
     460                } else {
     461                        return false;
     462                }
     463        }
     464}
     465add_action( 'bp_enqueue_scripts', 'bp_add_cover_image_inline_css', 11 );
     466
     467/**
     468 * Add the needed script and css for the BuddyPress modal
     469 *
     470 * @since 2.4.0
     471 */
     472function bp_add_modal() {
     473        // Enqueue me just once per page, please.
     474        if ( did_action( 'bp_modal_scripts_enqueued' ) ) {
     475                return;
     476        }
     477
     478        wp_enqueue_script( 'bp-modal' );
     479        wp_enqueue_style ( 'bp-modal' );
     480
     481        /**
     482         * Fires at the conclusion of bp_add_modal()
     483         * to avoid the scripts to be loaded more than once.
     484         *
     485         * @since 2.4.0
     486         */
     487        do_action( 'bp_modal_scripts_enqueued' );
     488}
     489
     490/**
     491 * Enqueue scripts for the BuddyPress modal iframe
     492 *
     493 * @since  2.4.0
     494 *
     495 * @param  bool $is_admin  wether the context is wp-admin or not
     496 */
     497function bp_modal_enqueue_scripts( $is_admin = false ) {
     498        global $wp_filter;
     499
     500        // Leave themes register their stylesheet
     501        $theme = get_template();
     502        if ( empty( $theme ) ) {
     503                $theme = get_stylesheet();
     504        }
     505
     506        // Only keep scripts enqueued hooking bp_enqueue_scripts.
     507        if ( isset( $wp_filter[ 'wp_enqueue_scripts' ] ) ) {
     508                foreach ( $wp_filter[ 'wp_enqueue_scripts' ] as $priority => $actions ) {
     509
     510                        foreach ( $actions as $key => $actions_data ) {
     511                                if ( 'bp_enqueue_scripts' !== $key && ! ( false !== strpos( $key, $theme ) && ! $is_admin ) ) {
     512                                        unset( $wp_filter[ 'wp_enqueue_scripts' ][ $priority ][ $key ] );
     513                                }
     514                        }
     515                }
     516        }
     517
     518        return wp_enqueue_scripts();
     519}
     520add_action( 'bp_modal_header', 'bp_modal_enqueue_scripts',  1 );
     521add_action( 'bp_modal_header', 'locale_stylesheet'            );
     522add_action( 'bp_modal_header', 'wp_print_styles',           8 );
     523add_action( 'bp_modal_header', 'wp_print_head_scripts',     9 );
     524add_action( 'bp_modal_footer', 'wp_print_footer_scripts',  20 );
     525
     526/* Admin context */
     527add_action( 'bp_admin_modal_header', 'bp_modal_enqueue_scripts',     1 );
     528add_action( 'bp_admin_modal_header', 'register_admin_color_schemes', 2 );
     529add_action( 'bp_admin_modal_header', 'print_admin_styles',           3 );
     530add_action( 'bp_admin_modal_footer', '_wp_footer_scripts'              );
  • src/bp-core/bp-core-dependency.php

    diff --git src/bp-core/bp-core-dependency.php src/bp-core/bp-core-dependency.php
    index 22f5a30..13dd373 100644
    function bp_enqueue_scripts() { 
    383383}
    384384
    385385/**
     386 * Fire the 'bp_modal_header' action, or the 'bp_admin_modal_header' in the modal was opened from
     387 * an Administration screen.
     388 *
     389 * @since 2.4.0
     390 */
     391function bp_modal_header( $is_admin = false ) {
     392        $action = 'bp_modal_header';
     393
     394        if ( true === (bool) $is_admin ) {
     395                $action = 'bp_admin_modal_header';
     396        }
     397
     398        /**
     399         * Fires inside the 'bp_modal_header' function.
     400         *
     401         * @since 2.4.0
     402         *
     403         * @param  bool $is_admin True for a wp-admin context, false otherwise
     404         */
     405        do_action( $action, $is_admin );
     406}
     407
     408/**
     409 * Fire the 'bp_modal_footer' action, or the 'bp_admin_modal_footer' in the modal was opened from
     410 * an Administration screen.
     411 *
     412 * @since 2.4.0
     413 */
     414function bp_modal_footer( $is_admin = false ) {
     415        $action = 'bp_modal_footer';
     416
     417        if ( true === (bool) $is_admin ) {
     418                $action = 'bp_admin_modal_footer';
     419        }
     420
     421        /**
     422         * Fires inside the 'bp_modal_footer' function.
     423         *
     424         * @since 2.4.0
     425         *
     426         * @param  bool $is_admin True for a wp-admin context, false otherwise
     427         */
     428        do_action( $action, $is_admin );
     429}
     430
     431/**
    386432 * Fire the 'bp_add_rewrite_tag' action, where BP adds its custom rewrite tags.
    387433 *
    388434 * @since BuddyPress (1.8.0)
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 1ea91ec..8f7a36a 100644
    function bp_update_is_item_mod( $is_item_mod = false, $component = '' ) { 
    19871987}
    19881988
    19891989/**
     1990 * Set a BuddyPress modal
     1991 *
     1992 * @since  2.4.0
     1993 *
     1994 * @param  bool $set whether the current screen is a modal (True) or not (False)
     1995 */
     1996function bp_set_is_modal( $set = false ) {
     1997        buddypress()->core->is_modal = $set;
     1998}
     1999
     2000/**
    19902001 * Trigger a 404.
    19912002 *
    19922003 * @since BuddyPress (1.5.0)
  • src/bp-core/bp-core-options.php

    diff --git src/bp-core/bp-core-options.php src/bp-core/bp-core-options.php
    index c3911a1..e8b8ed0 100644
    function bp_get_default_options() { 
    2424
    2525                /** Components ********************************************************/
    2626
    27                 'bp-deactivated-components'       => array(),
     27                'bp-deactivated-components'            => array(),
    2828
    2929                /** bbPress ***********************************************************/
    3030
    3131                // Legacy bbPress config location
    32                 'bb-config-location'              => ABSPATH . 'bb-config.php',
     32                'bb-config-location'                   => ABSPATH . 'bb-config.php',
    3333
    3434                /** XProfile **********************************************************/
    3535
    3636                // Base profile groups name
    37                 'bp-xprofile-base-group-name'     => 'Base',
     37                'bp-xprofile-base-group-name'          => 'Base',
    3838
    3939                // Base fullname field name
    40                 'bp-xprofile-fullname-field-name' => 'Name',
     40                'bp-xprofile-fullname-field-name'      => 'Name',
    4141
    4242                /** Blogs *************************************************************/
    4343
    4444                // Used to decide if blogs need indexing
    45                 'bp-blogs-first-install'          => false,
     45                'bp-blogs-first-install'               => false,
    4646
    4747                /** Settings **********************************************************/
    4848
    4949                // Disable the WP to BP profile sync
    50                 'bp-disable-profile-sync'         => false,
     50                'bp-disable-profile-sync'              => false,
    5151
    5252                // Hide the Toolbar for logged out users
    53                 'hide-loggedout-adminbar'         => false,
     53                'hide-loggedout-adminbar'              => false,
    5454
    5555                // Avatar uploads
    56                 'bp-disable-avatar-uploads'       => false,
     56                'bp-disable-avatar-uploads'            => false,
     57
     58                // Cover image uploads
     59                'bp-disable-cover-image-uploads'       => false,
    5760
    5861                // Group Profile Photos
    59                 'bp-disable-group-avatar-uploads' => false,
     62                'bp-disable-group-avatar-uploads'      => false,
     63
     64                // Group Cover image uploads
     65                'bp-disable-group-cover-image-uploads' => false,
    6066
    6167                // Allow users to delete their own accounts
    62                 'bp-disable-account-deletion'     => false,
     68                'bp-disable-account-deletion'          => false,
    6369
    6470                // Allow comments on blog and forum activity items
    65                 'bp-disable-blogforum-comments'   => true,
     71                'bp-disable-blogforum-comments'        => true,
    6672
    6773                // The ID for the current theme package.
    68                 '_bp_theme_package_id'            => 'legacy',
     74                '_bp_theme_package_id'                 => 'legacy',
    6975
    7076                /** Groups ************************************************************/
    7177
    7278                // @todo Move this into the groups component
    7379
    7480                // Restrict group creation to super admins
    75                 'bp_restrict_group_creation'      => false,
     81                'bp_restrict_group_creation'           => false,
    7682
    7783                /** Akismet ***********************************************************/
    7884
    7985                // Users from all sites can post
    80                 '_bp_enable_akismet'              => true,
     86                '_bp_enable_akismet'                   => true,
    8187
    8288                /** Activity HeartBeat ************************************************/
    8389
    8490                // HeartBeat is on to refresh activities
    85                 '_bp_enable_heartbeat_refresh'    => true,
     91                '_bp_enable_heartbeat_refresh'         => true,
    8692
    8793                /** BuddyBar **********************************************************/
    8894
    8995                // Force the BuddyBar
    90                 '_bp_force_buddybar'              => false,
     96                '_bp_force_buddybar'                   => false,
    9197
    9298                /** Legacy theme *********************************************/
    9399
    94100                // Whether to register the bp-default themes directory
    95                 '_bp_retain_bp_default'           => false,
     101                '_bp_retain_bp_default'                => false,
    96102
    97103                /** Widgets **************************************************/
    98104                'widget_bp_core_login_widget'                => false,
    function bp_disable_avatar_uploads( $default = true ) { 
    597603}
    598604
    599605/**
     606 * Are members able to upload their own cover images?
     607 *
     608 * @since 2.4.0
     609 *
     610 * @uses bp_get_option() To get the cover image uploads option.
     611 *
     612 * @param bool $default Optional. Fallback value if not found in the database.
     613 *                      Default: false.
     614 *
     615 * @return bool True if cover image uploads are disabled, otherwise false.
     616 */
     617function bp_disable_cover_image_uploads( $default = false ) {
     618
     619        /**
     620         * Filters whether or not members are able to upload their own cover images.
     621         *
     622         * @since 2.4.0
     623         *
     624         * @param bool $value Whether or not members are able to upload their own cover images.
     625         */
     626        return (bool) apply_filters( 'bp_disable_cover_image_uploads', (bool) bp_get_option( 'bp-disable-cover-image-uploads', $default ) );
     627}
     628
     629/**
    600630 * Are group avatars disabled?
    601631 *
    602632 * For backward compatibility, this option falls back on the value of 'bp-disable-avatar-uploads' when no value is
    function bp_disable_group_avatar_uploads( $default = null ) { 
    632662}
    633663
    634664/**
     665 * Are group cover images disabled?
     666 *
     667 * @since 2.4.0
     668 *
     669 * @uses bp_get_option() To get the group cover image uploads option.
     670 *
     671 * @param bool $default Optional. Fallback value if not found in the database.
     672 *                      Default: false.
     673 *
     674 * @return bool True if group cover image uploads are disabled, otherwise false.
     675 */
     676function bp_disable_group_cover_image_uploads( $default = false ) {
     677
     678        /**
     679         * Filters whether or not members are able to upload group cover images.
     680         *
     681         * @since 2.4.0
     682         *
     683         * @param bool $value Whether or not members are able to upload thier groups cover images.
     684         */
     685        return (bool) apply_filters( 'bp_disable_group_cover_image_uploads', (bool) bp_get_option( 'bp-disable-group-cover-image-uploads', $default ) );
     686}
     687
     688/**
    635689 * Are members able to delete their own accounts?
    636690 *
    637691 * @since BuddyPress (1.6.0)
  • src/bp-core/bp-core-template.php

    diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
    index 52bae24..3bc82ec 100644
    function bp_is_active( $component = '', $feature = '' ) { 
    19341934
    19351935                // Is feature active?
    19361936                if ( ! empty( $feature ) ) {
     1937                        // The xProfile component is specific
     1938                        if ( 'xprofile' === $component ) {
     1939                                $component = 'profile';
     1940                        }
     1941
    19371942                        if ( empty( buddypress()->$component->features ) || false === in_array( $feature, buddypress()->$component->features, true ) ) {
    19381943                                $retval = false;
    19391944                        }
    function bp_is_user_change_avatar() { 
    22472252}
    22482253
    22492254/**
     2255 * Is the current page the a user's change cover image profile page?
     2256 *
     2257 * Eg http://example.com/members/joe/profile/change-cover-image/ (or a subpage thereof).
     2258 *
     2259 * @since  2.4.0
     2260 *
     2261 * @return True if the current page is a user's profile edit cover image page.
     2262 */
     2263function bp_is_user_change_cover_image() {
     2264        return (bool) ( bp_is_profile_component() && bp_is_current_action( 'change-cover-image' ) );
     2265}
     2266
     2267/**
    22502268 * Is this a user's forums page?
    22512269 *
    22522270 * Eg http://example.com/members/joe/forums/ (or a subpage thereof).
    function bp_is_register_page() { 
    27472765}
    27482766
    27492767/**
     2768 * Is the current page the BuddyPress modal?
     2769 *
     2770 * Eg http://example.com/members/foobar/bp-modal.
     2771 *
     2772 * @return bool True if the current page is the BuddyPress modal.
     2773 */
     2774function bp_is_modal() {
     2775        $retval = false;
     2776        $bp = buddypress();
     2777
     2778        if ( isset( $bp->core->is_modal ) ) {
     2779                $retval = (bool) $bp->core->is_modal;
     2780        }
     2781
     2782        return $retval;
     2783}
     2784
     2785/**
    27502786 * Customize the body class, according to the currently displayed BP content.
    27512787 */
    27522788function bp_the_body_class() {
    function bp_nav_menu( $args = array() ) { 
    33343370                return $nav_menu;
    33353371        }
    33363372}
     3373
     3374/**
     3375 * Output a modal link
     3376 *
     3377 * @since  2.4.0
     3378 *
     3379 * @param  array  $args the attributes of the BuddyPress modal
     3380 */
     3381function bp_modal_link( $args = array() ) {
     3382        echo bp_get_modal_link( $args );
     3383}
     3384
     3385        /**
     3386         * Get a modal link
     3387         *
     3388         * @since  2.4.0
     3389         *
     3390         * @param  array  $args {
     3391         *     An array of arguments.
     3392         *
     3393         *     @type int    $item_id      The ID of the item. Default: current user_id. Required.
     3394         *     @type string $object       The type of object (eg: user, group..). Default:user. Required.
     3395         *     @type string $width        The width of the modal. Default:600. Optionnal.
     3396         *     @type string $height       The height of the modal. Default:500. Optionnal.
     3397         *     @type string $modal_title  The title tag for the generated iframe on link click. Default: ''. Optionnal.
     3398         *     @type string $modal_action The name of the action that will be executed by the modal. Default: ''.Required.
     3399         *     @type array  $link_class   The list of class to add to the generated link. Default: empty array. Optionnal.
     3400         *     @type string $link_title   The title attribute of the link. Default: 'Open window'. Optionnal.
     3401         *     @type string $link_text    The text of the link. Default: 'Open window'. Optionnal.
     3402         *     @type bool   $html         Whether to return an <a> HTML element, vs a raw URL
     3403         *                                to a modal link. If false, <a>-specific arguments (like 'link_class')
     3404         *                                will be ignored. Default: true.
     3405         * }
     3406         * @return string the html to link to the modal
     3407         */
     3408        function bp_get_modal_link( $args = array() ) {
     3409                $r = bp_parse_args( $args, array(
     3410                        'item_id'      => bp_loggedin_user_id(),
     3411                        'object'       => 'user',
     3412                        'width'        => 600,
     3413                        'height'       => 500,
     3414                        'modal_title'  => '',
     3415                        'modal_action' => '',
     3416                        'link_title'   => array(),
     3417                        'link_title'   => '',
     3418                        'link_text'    => __( 'Open window', 'buddypress' ),
     3419                        'html'         => true,
     3420                ) );
     3421
     3422                if ( empty( $r['item_id'] ) || empty( $r['object'] ) || empty( $r['modal_action'] ) ) {
     3423                        return;
     3424                }
     3425
     3426                if ( empty( $r['link_title'] ) ) {
     3427                        $r['link_title'] = $r['link_text'];
     3428                }
     3429
     3430                // Add BuddyPress modal
     3431                bp_add_modal();
     3432
     3433                $query_args = array(
     3434                        'is_admin'  => 0,
     3435                        'title'     => $r['modal_title'],
     3436                        'action'    => $r['modal_action'],
     3437                        'TB_iframe' => true,
     3438                        'width'     => $r['width'],
     3439                        'height'    => $r['height'],
     3440                );
     3441
     3442                if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
     3443                        $query_args['is_admin'] = 1;
     3444                }
     3445
     3446                if ( 'group' === $r['object'] ) {
     3447                        if ( is_a( $r['item_id'], 'BP_Groups_Group' ) ) {
     3448                                $group = $r['item_id'];
     3449                        } else {
     3450                                $group = groups_get_group( array( 'group_id' => $r['item_id'] ) );
     3451                        }
     3452
     3453                        $group_link = bp_get_group_permalink( $group );
     3454
     3455                        if ( empty( $group_link ) ) {
     3456                                return;
     3457                        }
     3458
     3459                        if ( 'group-avatar' === $r['modal_action'] || 'group-cover-image' === $r['modal_action'] ) {
     3460                                $group_link = trailingslashit( $group_link . 'admin' );
     3461                        }
     3462
     3463                        $modal_link = add_query_arg( $query_args, trailingslashit( $group_link . 'bp-modal' ) );
     3464
     3465                } elseif ( 'user' === $r['object'] ) {
     3466                        $user_link = bp_core_get_user_domain( $r['item_id'] );
     3467
     3468                        if ( empty( $user_link ) ) {
     3469                                return;
     3470                        }
     3471
     3472                        if ( 'change-avatar' === $r['modal_action'] || 'change-cover-image' === $r['modal_action'] ) {
     3473                                $user_link = trailingslashit( $user_link . 'profile' );
     3474                        }
     3475
     3476                        $modal_link = add_query_arg( $query_args, trailingslashit( $user_link . 'bp-modal' ) );
     3477
     3478                } else {
     3479                        return;
     3480                }
     3481
     3482                if ( ! $r['html'] ) {
     3483                        /**
     3484                         * Filter here to edit the modal link
     3485                         *
     3486                         * @since  2.4.0
     3487                         *
     3488                         * @param  string $value the modal link
     3489                         * @param  array  $r     the modal link parameter
     3490                         */
     3491                        return apply_filters( 'bp_get_modal_link', $modal_link, $r );
     3492                } else {
     3493                        /**
     3494                         * Filter here to edit the modal link
     3495                         *
     3496                         * @since  2.4.0
     3497                         *
     3498                         * @param  string $value the modal link
     3499                         * @param  array  $r     the modal link parameter
     3500                         */
     3501                        return apply_filters( 'bp_get_modal_html_link', sprintf( '<a href="%1$s" class="bp-thickbox %2$s" title="%3$s">%4$s</a>',
     3502                                esc_url( $modal_link ),
     3503                                esc_attr( join( ' ', (array) $r['link_class'] ) ),
     3504                                esc_attr( $r['link_title'] ),
     3505                                esc_html( $r['link_text'] )
     3506                        ), $r );
     3507                }
     3508        }
     3509
     3510/**
     3511 * Output the modal iframe title tag
     3512 *
     3513 * @since  2.4.0
     3514 */
     3515function bp_modal_title() {
     3516        echo bp_modal_get_title();
     3517}
     3518
     3519        /**
     3520         * Get the modale iframe title tag
     3521         *
     3522         * @since  2.4.0
     3523         *
     3524         * @return string the title tag for the modal iframe
     3525         */
     3526        function bp_modal_get_title() {
     3527                $title = _x( 'BuddyPress modal', 'BuddyPress' );
     3528
     3529                if ( isset( $_GET['title'] ) ) {
     3530                        $title = $_GET['title'];
     3531                }
     3532
     3533                return apply_filters( 'bp_modal_title', esc_html( strip_tags( $title ) ), $title );
     3534        }
     3535
     3536/**
     3537 * Output the modal content
     3538 *
     3539 * @since  2.4.0
     3540 */
     3541function bp_modal_content() {
     3542        $action = 'bp_modal_content';
     3543
     3544        if ( isset( $_GET['action'] ) ) {
     3545                $action .= '_' .sanitize_file_name( $_GET['action'] );
     3546        }
     3547
     3548        /**
     3549         * This is a dynamic action depending on the $modal_action
     3550         * defined in bp_get_modal_link.
     3551         *
     3552         * @since  2.4.0
     3553         *
     3554         * eg: "bp_modal_content_$modal_action"
     3555         */
     3556        do_action( $action );
     3557}
  • src/bp-core/bp-core-theme-compatibility.php

    diff --git src/bp-core/bp-core-theme-compatibility.php src/bp-core/bp-core-theme-compatibility.php
    index 897b775..8139fe9 100644
    function bp_set_theme_compat_original_template( $template = '' ) { 
    437437}
    438438
    439439/**
     440 * Set a theme compat feature
     441 *
     442 * @since 2.4.0
     443 *
     444 * @param  string $theme_id the theme id (eg: legacy)
     445 * @param  array  $feature  an associative array (eg: array( name => 'feature_name', 'settings' => array() ))
     446 */
     447function bp_set_theme_compat_feature( $theme_id, $feature = array() ) {
     448        if ( empty( $theme_id ) || empty( $feature['name'] ) ) {
     449                return;
     450        }
     451
     452        // Get BuddyPress instance
     453        $bp = buddypress();
     454
     455        // Get current theme compat theme
     456        $theme_compat_theme = $bp->theme_compat->theme;
     457
     458        // Bail if theme is not in use
     459        if ( $theme_id !== $theme_compat_theme->id ) {
     460                return;
     461        }
     462
     463        $features = $theme_compat_theme->__get( 'features' );
     464        if ( empty( $features ) ) {
     465                $features = array();
     466        }
     467
     468        // Bail if the feature is already registered or no settings were provided
     469        if ( isset( $features[ $feature['name'] ] ) || empty( $feature['settings'] ) ) {
     470                return;
     471        }
     472
     473        // Add the feature
     474        $features[ $feature['name'] ] = (object) $feature['settings'];
     475
     476        // The feature is attached to components
     477        if ( isset( $features[ $feature['name'] ]->components ) ) {
     478                // Set the feature for each concerned component
     479                foreach ( (array) $features[ $feature['name'] ]->components as $component ) {
     480                        // The xProfile component is specific
     481                        if ( 'xprofile' === $component ) {
     482                                $component = 'profile';
     483                        }
     484
     485                        if ( isset( $bp->{$component} ) ) {
     486                                if ( isset( $bp->{$component}->features ) ) {
     487                                        $bp->{$component}->features[] = $feature['name'];
     488                                } else {
     489                                        $bp->{$component}->features = array( $feature['name'] );
     490                                }
     491                        }
     492                }
     493        }
     494
     495        // Finally update the theme compat features
     496        $theme_compat_theme->__set( 'features', $features );
     497}
     498
     499/**
     500 * Get a theme compat feature
     501 *
     502 * @since 2.4.0
     503 *
     504 * @param  string $feature the feature (eg: cover_image)
     505 * @return object          the feature settings.
     506 */
     507function bp_get_theme_compat_feature( $feature = '' ) {
     508        // Get current theme compat theme
     509        $theme_compat_theme = buddypress()->theme_compat->theme;
     510
     511        // Get features
     512        $features = $theme_compat_theme->__get( 'features' );
     513
     514        if ( ! isset( $features[ $feature ] ) ) {
     515                return false;
     516        }
     517
     518        return $features[ $feature ];
     519}
     520
     521/**
     522 * Setup the theme's features
     523 *
     524 * Note: BP Legacy's buddypress-functions.php is not loaded in WP Administration
     525 * as it's done using bp_locate_template()
     526 *
     527 * @since 2.4.0
     528 *
     529 * @global $content_width the content width of the theme
     530 */
     531function bp_register_theme_compat_default_features() {
     532        global $content_width;
     533
     534        // If the current theme doesn't need theme compat, bail at this point.
     535        if ( ! bp_use_theme_compat_with_current_theme() ) {
     536                return $template;
     537        }
     538
     539        // Get the theme
     540        $current_theme = wp_get_theme();
     541        $theme_handle  = $current_theme->get_stylesheet();
     542        $parent        = $current_theme->parent();
     543
     544        if ( $parent ) {
     545                $theme_handle = $parent->get_stylesheet();
     546        }
     547
     548        /**
     549         * Since Companion stylesheets, the $content_width is smaller
     550         * than the width used by BuddyPress, so we need to manually set the
     551         * content width for the concerned themes.
     552         *
     553         * array( stylesheet => content width used by BuddyPress )
     554         */
     555        $bp_content_widths = array(
     556                'twentyfifteen'  => 1300,
     557                'twentyfourteen' => 955,
     558                'twentythirteen' => 890,
     559        );
     560
     561        // Default values
     562        $bp_content_width = (int) $content_width;
     563        $bp_handle        = 'bp-legacy-css';
     564
     565        // Specific to themes having companion stylesheets
     566        if ( isset( $bp_content_widths[ $theme_handle ] ) ) {
     567                $bp_content_width = $bp_content_widths[ $theme_handle ];
     568                $bp_handle        = 'bp-' . $theme_handle;
     569        }
     570
     571        if ( is_rtl() ) {
     572                $bp_handle .= '-rtl';
     573        }
     574
     575        $top_offset    = 150;
     576        $avatar_height = apply_filters( 'bp_core_avatar_full_height', $top_offset );
     577
     578        if ( $avatar_height > $top_offset ) {
     579                $top_offset = $avatar_height;
     580        }
     581
     582        bp_set_theme_compat_feature( 'legacy', array(
     583                'name'     => 'cover_image',
     584                'settings' => array(
     585                        'components'   => array( 'xprofile', 'groups' ),
     586                        'width'        => $bp_content_width,
     587                        'height'       => $top_offset + round( $avatar_height / 2 ),
     588                        'callback'     => 'bp_legacy_theme_cover_image',
     589                        'theme_handle' => $bp_handle,
     590                ),
     591        ) );
     592}
     593
     594/**
    440595 * Check whether a given template is the one that WP originally selected to display current page.
    441596 *
    442597 * @since BuddyPress (1.7.0)
  • src/bp-core/classes/class-bp-attachment-cover-image.php

    diff --git src/bp-core/classes/class-bp-attachment-cover-image.php src/bp-core/classes/class-bp-attachment-cover-image.php
    index e69de29..563d8ac 100644
     
     1<?php
     2/**
     3 * Core Cover Image attachment class.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 */
     8
     9// Exit if accessed directly
     10defined( 'ABSPATH' ) || exit;
     11
     12/**
     13 * BP Attachment Cover Image class.
     14 *
     15 * Extends BP Attachment to manage the cover images uploads.
     16 *
     17 * @since 2.4.0
     18 */
     19class BP_Attachment_Cover_Image extends BP_Attachment {
     20        /**
     21         * The constuctor
     22         *
     23         * @since 2.4.0
     24         */
     25        public function __construct() {
     26                parent::__construct( array(
     27                        'action'             => 'bp_cover_image_upload',
     28                        'file_input'         => 'file',
     29                        'base_dir'           => 'buddypress',
     30                        'required_wp_files'  => array( 'file', 'image' ),
     31
     32                        /* @todo use a custom error, like we are doing for avatars */
     33                        'allowed_mime_types' => array( 'jpg', 'png', 'gif' ),
     34                ) );
     35        }
     36
     37        /**
     38         * Set the directory when uploading a file
     39         *
     40         * @since 2.4.0
     41         *
     42         * @return array upload data (path, url, basedir...)
     43         */
     44        public function upload_dir_filter() {
     45                // Default values are for profiles
     46                $object_id = bp_displayed_user_id();
     47
     48                if ( empty( $object_id ) ) {
     49                        $object_id = bp_loggedin_user_id();
     50                }
     51
     52                $object_directory = 'members';
     53
     54                // We're in a group, edit default values
     55                if ( bp_is_group() || bp_is_group_create() ) {
     56                        $object_id        = bp_get_current_group_id();
     57                        $object_directory = 'groups';
     58                }
     59
     60                // Set the subdir
     61                $subdir  = '/' . $object_directory . '/' . $object_id . '/cover-image';
     62
     63                return apply_filters( 'bp_attachments_cover_image_upload_datas', array(
     64                        'path'    => $this->upload_path . $subdir,
     65                        'url'     => $this->url . $subdir,
     66                        'subdir'  => $subdir,
     67                        'basedir' => $this->upload_path,
     68                        'baseurl' => $this->url,
     69                        'error'   => false
     70                ) );
     71        }
     72
     73        /**
     74         * Adjust the cover image to fit with advised width & height.
     75         *
     76         * @since 2.4.0
     77         *
     78         * @param string $file the absolute path to the file.
     79         * @return mixed
     80         */
     81        public function fit( $file = '', $dimensions = array() ) {
     82                if ( empty( $dimensions['width'] ) || empty( $dimensions['height'] ) ) {
     83                        return false;
     84                }
     85
     86                // Get image size
     87                $size   = @getimagesize( $file );
     88                $retval = false;
     89
     90                // Check image size and shrink if too large
     91                if ( $size[0] > $dimensions['width'] || $size[1] > $dimensions['height'] ) {
     92                        $editor = wp_get_image_editor( $file );
     93
     94                        if ( ! is_wp_error( $editor ) ) {
     95                                $editor->set_quality( 100 );
     96
     97                                $resized = $editor->resize( $dimensions['width'], $dimensions['height'], true );
     98                                if ( ! is_wp_error( $resized ) ) {
     99                                        $cover   = $editor->save( $this->generate_filename( $file ) );
     100                                } else {
     101                                        $retval = $resized;
     102                                }
     103
     104                                // Check for cover creation errors
     105                                if ( ( false === $retval ) && is_wp_error( $cover ) ) {
     106                                        $retval = $cover;
     107                                }
     108
     109                                // Cover is good so proceed
     110                                if ( false === $retval ) {
     111                                        $retval = $cover;
     112                                }
     113
     114                        } else {
     115                                $retval = $editor;
     116                        }
     117                }
     118
     119                return $retval;
     120        }
     121
     122        /**
     123         * Generate a filename for the cover image
     124         *
     125         * @since 2.4.0
     126         *
     127         * @param  string $file the absolute path to the file.
     128         * @return string       the absolute path to the new file name
     129         */
     130        public function generate_filename( $file = '' ) {
     131                if ( empty( $file ) || ! file_exists( $file ) ) {
     132                        return false;
     133                }
     134
     135                $info    = pathinfo( $file );
     136                $dir     = $info['dirname'];
     137                $ext     = strtolower( $info['extension'] );
     138                $name    = wp_hash( $file . time() ) . '-bp-cover-image';
     139
     140                return trailingslashit( $dir ) . "{$name}.{$ext}";
     141        }
     142
     143        /**
     144         * Build script datas for the Uploader UI
     145         *
     146         * @since 2.4.0
     147         *
     148         * @return array the javascript localization data
     149         */
     150        public function script_data() {
     151                // Get default script data
     152                $script_data = parent::script_data();
     153
     154                if ( bp_is_user() ) {
     155                        $item_id = bp_displayed_user_id();
     156
     157                        $script_data['bp_params'] = array(
     158                                'object'          => 'user',
     159                                'item_id'         => $item_id,
     160                                'has_cover_image' => bp_attachments_get_user_has_cover_image( $item_id ),
     161                                'nonces'  => array(
     162                                        'remove' => wp_create_nonce( 'bp_delete_cover_image' ),
     163                                ),
     164                        );
     165
     166                        // Set feedback messages
     167                        $script_data['feedback_messages'] = array(
     168                                1 => __( 'Your new cover image was uploaded successfully.', 'buddypress' ),
     169                                2 => __( 'There was a problem deleting your cover image. Please try again.', 'buddypress' ),
     170                                3 => __( 'Your cover image was deleted successfully!', 'buddypress' ),
     171                        );
     172                } elseif ( bp_is_group() ) {
     173                        $item_id = bp_get_current_group_id();
     174
     175                        $script_data['bp_params'] = array(
     176                                'object'          => 'group',
     177                                'item_id'         => bp_get_current_group_id(),
     178                                'has_cover_image' => bp_attachments_get_group_has_cover_image( $item_id ),
     179                                'nonces'  => array(
     180                                        'remove' => wp_create_nonce( 'bp_delete_cover_image' ),
     181                                ),
     182                        );
     183
     184                        // Set feedback messages
     185                        $script_data['feedback_messages'] = array(
     186                                1 => __( 'The group cover image was uploaded successfully.', 'buddypress' ),
     187                                2 => __( 'There was a problem deleting the group cover image. Please try again.', 'buddypress' ),
     188                                3 => __( 'The group cover image was deleted successfully!', 'buddypress' ),
     189                        );
     190                } else {
     191                        /**
     192                         * Use this filter to include specific BuddyPress params for your object.
     193                         * e.g. Cover image for blogs single item.
     194                         *
     195                         * @since 2.4.0
     196                         *
     197                         * @param array $value The cover image specific BuddyPress parameters.
     198                         */
     199                        $script_data['bp_params'] = apply_filters( 'bp_attachment_cover_image_params', array() );
     200                }
     201
     202                // Include our specific js & css
     203                $script_data['extra_js']  = array( 'bp-cover-image' );
     204                $script_data['extra_css'] = array( 'bp-avatar' );
     205
     206                return apply_filters( 'bp_attachments_cover_image_script_data', $script_data );
     207        }
     208}
  • src/bp-core/css/avatar.css

    diff --git src/bp-core/css/avatar.css src/bp-core/css/avatar.css
    index 385852f..2986dff 100644
     
    1 div.bp-avatar-status {
     1div.bp-avatar-status,
     2div.bp-cover-image-status {
    23        clear: both;
    34        margin: 1em 0;
    45}
    56
    6 div.bp-avatar-status p.updated {
     7div.bp-avatar-status p.updated,
     8div.bp-cover-image-status p.updated {
    79        display: block;
    810        padding: 10px 15px;
    911}
    1012
    11 div.bp-avatar-status p.success {
     13div.bp-avatar-status p.success,
     14div.bp-cover-image-status p.success {
    1215        background-color: #efc;
    1316        border: 1px solid #591;
    1417        color: #250;
    1518}
    1619
    17 div.bp-avatar-status p.error {
     20div.bp-avatar-status p.error,
     21div.bp-cover-image-status p.error {
    1822        background-color: #fdc;
    1923        border: 1px solid #a00;
    2024        color: #800;
    2125}
    2226
    23 div.bp-avatar-status .bp-progress {
     27div.bp-avatar-status .bp-progress,
     28div.bp-cover-image-status .bp-progress {
    2429        background: none;
    2530        border: 1px solid #d1d1d1;
    2631        float: right;
    div.bp-avatar-status .bp-progress { 
    3338        width: 200px;
    3439}
    3540
    36 div.bp-avatar-status .bp-bar {
     41div.bp-avatar-status .bp-bar,
     42div.bp-cover-image-status .bp-bar {
    3743        background-color: #c3ff88;
    3844        width: 0;
    3945        height: 100%;
  • src/bp-core/css/modal.css

    diff --git src/bp-core/css/modal.css src/bp-core/css/modal.css
    index e69de29..9de4a80 100644
     
     1body.bp-modal #TB_title {
     2        float: left;
     3        height: 1px;
     4}
     5
     6body.bp-modal #TB_ajaxWindowTitle {
     7        display: none;
     8}
     9
     10body.bp-modal #TB_window {
     11        max-width: 90%;
     12        max-height: 90%;
     13}
     14
     15body.bp-modal .tb-close-icon,
     16#bp-modal-buttons .bp-full-height-icon {
     17        left: auto;
     18        right: -30px;
     19        color: #eee;
     20        -webkit-transition: color .1s ease-in-out, background .1s ease-in-out;
     21        transition: color .1s ease-in-out, background .1s ease-in-out;
     22}
     23
     24body.bp-modal #TB_closeWindowButton:focus,
     25body.bp-modal #TB_closeWindowButton:focus .tb-close-icon,
     26body.bp-modal .tb-close-icon:focus,
     27body.bp-modal .tb-close-icon:hover,
     28#bp-modal-buttons #bp-modal-full-height:focus,
     29#bp-modal-buttons #bp-modal-full-height:focus .bp-full-height-icon,
     30#bp-modal-buttons .bp-full-height-icon:focus,
     31#bp-modal-buttons .bp-full-height-icon:hover {
     32        color: #00a0d2;
     33        outline: none;
     34        -webkit-box-shadow: none;
     35        box-shadow: none;
     36}
     37
     38body.buddypress .tb-close-icon:before,
     39body.toplevel_page_bp-groups .tb-close-icon:before {
     40        content: "\f335";
     41        font-size: 32px;
     42}
     43
     44#bp-modal-buttons .bp-full-height-icon {
     45        position:absolute;
     46        top:30px;
     47        text-align: center;
     48        line-height: 29px;
     49        width: 29px;
     50        height: 29px;
     51}
     52
     53#bp-modal-buttons .bp-full-height-icon:before {
     54        font: normal 20px/32px 'dashicons';
     55        speak: none;
     56        -webkit-font-smoothing: antialiased;
     57        -moz-osx-font-smoothing: grayscale;
     58}
     59
     60#bp-modal-buttons .bp-full-height-icon:before {
     61        content: "\f316";
     62}
     63
     64#bp-modal-buttons .bp-full-height-icon.max:before {
     65        content: "\f317";
     66}
     67
     68body.bp-modal #TB_iframeContent {
     69        margin:0;
     70        max-width: 100%;
     71        max-height: 100%;
     72}
  • src/bp-core/js/avatar.js

    diff --git src/bp-core/js/avatar.js src/bp-core/js/avatar.js
    index c5019df..fe5ed66 100644
    window.bp = window.bp || {}; 
    2626                        // Init some vars
    2727                        this.views    = new Backbone.Collection();
    2828                        this.jcropapi = {};
    29                         this.warning = null;
     29                        this.warning  = null;
     30                        this.opener   = window.opener || window.parent || window.top;
    3031
    3132                        // Set up nav
    3233                        this.setupNav();
    window.bp = window.bp || {}; 
    236237                                type:          _.isUndefined( avatar.get( 'type' ) ) ? 'crop' : avatar.get( 'type' ),
    237238                                nonce:         avatar.get( 'nonces' ).set
    238239                        } ).done( function( response ) {
    239                                 var avatarStatus = new bp.Views.AvatarStatus( {
    240                                         value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
    241                                         type : 'success'
    242                                 } );
     240                                var avatarClass,
     241                                    avatarStatus = new bp.Views.AvatarStatus( {
     242                                                value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
     243                                                type : 'success'
     244                                        } );
    243245
    244246                                self.views.add( {
    245247                                        id   : 'status',
    window.bp = window.bp || {}; 
    248250
    249251                                avatarStatus.inject( '.bp-avatar-status' );
    250252
     253                                avatarClass = '.' + avatar.get( 'object' ) + '-' + response.item_id + '-avatar';
     254
     255                                // Update each avatars of the parent page
     256                                if ( typeof self.opener.bp.updateAvatars !== 'undefined' ) {
     257                                        self.opener.bp.updateAvatars( avatarClass, response.avatar );
     258
    251259                                // Update each avatars of the page
    252                                 $( '.' + avatar.get( 'object' ) + '-' + response.item_id + '-avatar' ).each( function() {
    253                                         $(this).prop( 'src', response.avatar );
    254                                 } );
     260                                } else {
     261                                        $( avatarClass ).each( function() {
     262                                                $(this).prop( 'src', response.avatar );
     263                                        } );
     264                                }
    255265
    256266                                // Inject the Delete nav
    257267                                bp.Avatar.navItems.get( 'delete' ).set( { hide: 0 } );
    window.bp = window.bp || {}; 
    312322                                object:        model.get( 'object' ),
    313323                                nonce:         model.get( 'nonces' ).remove
    314324                        } ).done( function( response ) {
    315                                 var avatarStatus = new bp.Views.AvatarStatus( {
    316                                         value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
    317                                         type : 'success'
    318                                 } );
     325                                var avatarClass,
     326                                        avatarStatus = new bp.Views.AvatarStatus( {
     327                                                value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
     328                                                type : 'success'
     329                                        } );
    319330
    320331                                self.views.add( {
    321332                                        id   : 'status',
    window.bp = window.bp || {}; 
    324335
    325336                                avatarStatus.inject( '.bp-avatar-status' );
    326337
     338                                avatarClass = '.' + model.get( 'object' ) + '-' + response.item_id + '-avatar';
     339
     340                                // Update each avatars of the parent page
     341                                if ( typeof self.opener.bp.updateAvatars !== 'undefined' ) {
     342                                        self.opener.bp.updateAvatars( avatarClass, response.avatar );
     343
    327344                                // Update each avatars of the page
    328                                 $( '.' + model.get( 'object' ) + '-' + response.item_id + '-avatar').each( function() {
    329                                         $( this ).prop( 'src', response.avatar );
    330                                 } );
     345                                } else {
     346                                        $( avatarClass ).each( function() {
     347                                                $( this ).prop( 'src', response.avatar );
     348                                        } );
     349                                }
    331350
    332351                                 // Remove the Delete nav
    333352                                 bp.Avatar.navItems.get( 'delete' ).set( { active: 0, hide: 1 } );
  • src/bp-core/js/cover-image.js

    diff --git src/bp-core/js/cover-image.js src/bp-core/js/cover-image.js
    index e69de29..d0f6078 100644
     
     1/* global bp, BP_Uploader, _, Backbone */
     2
     3window.bp = window.bp || {};
     4
     5( function( exports, $ ) {
     6
     7        // Bail if not set
     8        if ( typeof BP_Uploader === 'undefined' ) {
     9                return;
     10        }
     11
     12        bp.Models      = bp.Models || {};
     13        bp.Collections = bp.Collections || {};
     14        bp.Views       = bp.Views || {};
     15
     16        bp.CoverImage = {
     17                start: function() {
     18
     19                        // Init some vars
     20                        this.views   = new Backbone.Collection();
     21                        this.warning = null;
     22                        this.opener  = window.opener || window.parent || window.top;
     23
     24                        // Set up views
     25                        this.uploaderView();
     26
     27                        // Inform about the needed dimensions
     28                        this.displayWarning( BP_Uploader.strings.cover_image_warnings.dimensions );
     29
     30                        // Set up the delete view if needed
     31                        if ( true === BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image ) {
     32                                this.deleteView();
     33                        }
     34                },
     35
     36                uploaderView: function() {
     37                        // Listen to the Queued uploads
     38                        bp.Uploader.filesQueue.on( 'add', this.uploadProgress, this );
     39
     40                        // Create the BuddyPress Uploader
     41                        var uploader = new bp.Views.Uploader();
     42
     43                        // Add it to views
     44                        this.views.add( { id: 'upload', view: uploader } );
     45
     46                        // Display it
     47                        uploader.inject( '.bp-cover-image' );
     48                },
     49
     50                uploadProgress: function() {
     51                        // Create the Uploader status view
     52                        var coverImageUploadProgress = new bp.Views.coverImageUploadProgress( { collection: bp.Uploader.filesQueue } );
     53
     54                        if ( ! _.isUndefined( this.views.get( 'status' ) ) ) {
     55                                this.views.set( { id: 'status', view: coverImageUploadProgress } );
     56                        } else {
     57                                this.views.add( { id: 'status', view: coverImageUploadProgress } );
     58                        }
     59
     60                        // Display it
     61                        coverImageUploadProgress.inject( '.bp-cover-image-status' );
     62                },
     63
     64                deleteView: function() {
     65                        // Create the delete model
     66                        var delete_model = new Backbone.Model( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
     67                                'object',
     68                                'item_id',
     69                                'nonces'
     70                        ) );
     71
     72                        // Do not add it if already there!
     73                        if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) {
     74                                return;
     75                        }
     76
     77                        // Create the delete view
     78                        var deleteView = new bp.Views.DeleteCoverImage( { model: delete_model } );
     79
     80                        // Add it to views
     81                        this.views.add( { id: 'delete', view: deleteView } );
     82
     83                        // Display it
     84                        deleteView.inject( '.bp-cover-image-manage' );
     85                },
     86
     87                deleteCoverImage: function( model ) {
     88                        var self = this,
     89                                deleteView;
     90
     91                        // Remove the delete view
     92                        if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) {
     93                                deleteView = this.views.get( 'delete' );
     94                                deleteView.get( 'view' ).remove();
     95                                this.views.remove( { id: 'delete', view: deleteView } );
     96                        }
     97
     98                        // Remove the cover image !
     99                        bp.ajax.post( 'bp_cover_image_delete', {
     100                                json:          true,
     101                                item_id:       model.get( 'item_id' ),
     102                                object:        model.get( 'object' ),
     103                                nonce:         model.get( 'nonces' ).remove
     104                        } ).done( function( response ) {
     105                                var coverImageStatus = new bp.Views.CoverImageStatus( {
     106                                        value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
     107                                        type : 'success'
     108                                } );
     109
     110                                self.views.add( {
     111                                        id   : 'status',
     112                                        view : coverImageStatus
     113                                } );
     114
     115                                coverImageStatus.inject( '.bp-cover-image-status' );
     116
     117                                // Reset the header of the parent page
     118                                if ( typeof self.opener.bp.updateCoverImage !== 'undefined' ) {
     119                                        self.opener.bp.updateCoverImage( response.reset_url );
     120
     121                                // Reset the header of the page
     122                                } else {
     123                                        $( '#header-cover-image' ).css( {
     124                                                'background-image': 'url( ' + response.reset_url + ' )'
     125                                        } );
     126                                }
     127
     128                                // Reset the has_cover_image bp_param
     129                                BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image = false;
     130
     131                        } ).fail( function( response ) {
     132                                var feedback = BP_Uploader.strings.default_error;
     133                                if ( ! _.isUndefined( response ) ) {
     134                                        feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ];
     135                                }
     136
     137                                var coverImageStatus = new bp.Views.CoverImageStatus( {
     138                                        value : feedback,
     139                                        type : 'error'
     140                                } );
     141
     142                                self.views.add( {
     143                                        id   : 'status',
     144                                        view : coverImageStatus
     145                                } );
     146
     147                                coverImageStatus.inject( '.bp-cover-image-status' );
     148
     149                                // Put back the delete view
     150                                bp.CoverImage.deleteView();
     151                        } );
     152                },
     153
     154                removeWarning: function() {
     155                        if ( ! _.isNull( this.warning ) ) {
     156                                this.warning.remove();
     157                        }
     158                },
     159
     160                displayWarning: function( message ) {
     161                        this.removeWarning();
     162
     163                        this.warning = new bp.Views.uploaderWarning( {
     164                                value: message
     165                        } );
     166
     167                        this.warning.inject( '.bp-cover-image-status' );
     168                }
     169        };
     170
     171        // Custom Uploader Files view
     172        bp.Views.coverImageUploadProgress = bp.Views.uploaderStatus.extend( {
     173                className: 'files',
     174
     175                initialize: function() {
     176                        bp.Views.uploaderStatus.prototype.initialize.apply( this, arguments );
     177
     178                        this.collection.on( 'change:url', this.uploadResult, this );
     179                },
     180
     181                uploadResult: function( model ) {
     182                        var message, type, cover = {};
     183
     184                        if ( ! _.isUndefined( model.get( 'url' ) ) ) {
     185
     186                                // Image is too small
     187                                if ( 0 === model.get( 'feedback_code' ) ) {
     188                                        message = BP_Uploader.strings.cover_image_warnings.dimensions;
     189                                        type    = 'warning';
     190
     191                                // Success, Rock n roll!
     192                                } else {
     193                                        message = BP_Uploader.strings.feedback_messages[ model.get( 'feedback_code' ) ];
     194                                        type = 'success';
     195                                }
     196
     197                                this.views.set( '.bp-uploader-progress', new bp.Views.CoverImageStatus( {
     198                                        value : message,
     199                                        type  : type
     200                                } ) );
     201
     202                                // Update the header of the parent page
     203                                if ( typeof bp.CoverImage.opener.bp.updateCoverImage !== 'undefined' ) {
     204                                        bp.CoverImage.opener.bp.updateCoverImage( model.get( 'url' ) );
     205
     206                                // Update the header of the page
     207                                } else {
     208                                        $( '#header-cover-image' ).css( {
     209                                                'background-image': 'url( ' + model.get( 'url' ) + ' )'
     210                                        } );
     211                                }
     212
     213                                // Add the delete view
     214                                bp.CoverImage.deleteView();
     215                        }
     216                }
     217        } );
     218
     219        // BuddyPress Cover Image Feedback view
     220        bp.Views.CoverImageStatus = bp.View.extend( {
     221                tagName: 'p',
     222                className: 'updated',
     223                id: 'bp-cover-image-feedback',
     224
     225                initialize: function() {
     226                        this.el.className += ' ' + this.options.type;
     227                        this.value = this.options.value;
     228                },
     229
     230                render: function() {
     231                        this.$el.html( this.value );
     232                        return this;
     233                }
     234        } );
     235
     236        // BuddyPress Cover Image Delete view
     237        bp.Views.DeleteCoverImage = bp.View.extend( {
     238                tagName: 'div',
     239                id: 'bp-delete-cover-image-container',
     240                template: bp.template( 'bp-cover-image-delete' ),
     241
     242                events: {
     243                        'click #bp-delete-cover-image': 'deleteCoverImage'
     244                },
     245
     246                deleteCoverImage: function( event ) {
     247                        event.preventDefault();
     248
     249                        bp.CoverImage.deleteCoverImage( this.model );
     250                }
     251        } );
     252
     253        bp.CoverImage.start();
     254
     255})( bp, jQuery );
  • src/bp-core/js/modal.js

    diff --git src/bp-core/js/modal.js src/bp-core/js/modal.js
    index e69de29..cccce85 100644
     
     1/* global bp */
     2
     3window.bp = window.bp || {};
     4
     5( function( $ ) {
     6        var originalWidth, originalHeight, originalIframeHeight;
     7
     8        // Asjust Thickbox
     9        bp_tb_position = function() {
     10                var availableWidth  = $( window ).width(),
     11                        availableHeight = $( window ).height(),
     12                        needReposition  = false;
     13
     14                // Don't do anything if we don't have needed Thickbox attributes
     15                if ( typeof TB_WIDTH === 'undefined' || typeof TB_HEIGHT === 'undefined' || typeof tb_position === 'undefined' ) {
     16                        return;
     17                }
     18
     19                // Only set originalWidth and originalHeight if not defined
     20                if ( typeof originalWidth === 'undefined' ) {
     21                        originalWidth = TB_WIDTH;
     22                }
     23
     24                if ( typeof originalHeight === 'undefined' ) {
     25                        originalHeight = TB_HEIGHT;
     26                }
     27
     28                if ( availableWidth < TB_WIDTH ) {
     29                        TB_WIDTH = availableWidth - 50;
     30                        needReposition = true;
     31                } else if ( availableWidth > originalWidth ) {
     32                        TB_WIDTH = originalWidth;
     33                        needReposition = true;
     34                }
     35
     36                if ( availableHeight < TB_HEIGHT ) {
     37                        TB_HEIGHT = availableHeight - 50;
     38                        needReposition = true;
     39                } else if ( availableHeight > originalHeight ) {
     40                        TB_HEIGHT = originalHeight;
     41                        needReposition = true;
     42                }
     43
     44                // Ask Thickbox to "reposition"
     45                if ( true === needReposition ) {
     46                        tb_position();
     47
     48                        $( '#TB_window' ).css( {
     49                                'height' : TB_HEIGHT + 'px'
     50                        } );
     51
     52                        $( '#TB_iframeContent' ).css( {
     53                                'width' : originalWidth - 1 + 'px',
     54                                'height' : TB_HEIGHT - 1 + 'px'
     55                        } );
     56                }
     57        };
     58
     59        // Make sure links are not containing bigger dimensions than available ones
     60        $( 'a.bp-thickbox' ).each( function() {
     61                var href = $( this ).attr( 'href' ),
     62                        availableWidth  = $( window ).width(),
     63                        availableHeight = $( window ).height();
     64
     65                if ( ! href ) {
     66                        return;
     67                }
     68
     69                // Requested Thickbox width & height
     70                var tb_width  = href.match( /width=([0-9]+)/ );
     71                var tb_height = href.match( /height=([0-9]+)/ );
     72
     73                if ( tb_width[1] ) {
     74                        // If too large resize
     75                        if ( parseInt( tb_width[1] ) > availableWidth ) {
     76                                href = href.replace( /width=[0-9]+/g, 'width=' + Number( availableWidth - 50 ) );
     77
     78                        // Leave unchanged
     79                        } else {
     80                                href = href.replace( /width=[0-9]+/g, 'width=' + tb_width[1] );
     81                        }
     82                }
     83
     84                if ( tb_height[1] ) {
     85                        // If too large resize
     86                        if ( parseInt( tb_height[1] ) > availableHeight ) {
     87                                href = href.replace( /height=[0-9]+/g, 'height=' + Number( availableHeight - 50 ) );
     88
     89                        // Leave unchanged
     90                        } else {
     91                                href = href.replace( /height=[0-9]+/g, 'height=' + tb_height[1] );
     92                        }
     93                }
     94
     95                // Reset links
     96                $( this ).attr( 'href', href );
     97        } );
     98
     99        // Listen to bp-thickbox links
     100        $( document ).ready( function() {
     101                tb_init( 'a.bp-thickbox' );
     102                $( 'body' ).addClass( 'bp-modal' );
     103        } );
     104
     105        // Add a button to the BuddyPress modal
     106        window.tb_showIframe = function() {
     107                var isBPiframe = $( '#TB_iframeContent' ).prop( 'src' ).match( /bp-modal/ );
     108
     109                if ( null === isBPiframe ) {
     110                        return;
     111                }
     112
     113                $( '#TB_title' ).append( '<div id="bp-modal-buttons"><a href="#" id="bp-modal-full-height"><span class="screen-reader-text">Zoom</span><div class="bp-full-height-icon"></div></a>' );
     114        };
     115
     116        // Toggle the BuddyPress modal height from original to full
     117        $( 'body' ).on( 'click', '#bp-modal-buttons .bp-full-height-icon', function( event ) {
     118                event.preventDefault();
     119
     120                var bpFullHeighBtn = $( this );
     121
     122                bp_tb_position();
     123
     124                if ( typeof originalIframeHeight === 'undefined' ) {
     125                        originalIframeHeight = $( '#TB_iframeContent' ).prop( 'style' ).height;
     126                }
     127
     128                if ( ! bpFullHeighBtn.hasClass( 'max' ) ) {
     129                        TB_HEIGHT = $( window ).height() - 50;
     130                        bpFullHeighBtn.addClass( 'max' );
     131                } else {
     132                        TB_HEIGHT = originalIframeHeight;
     133                        bpFullHeighBtn.removeClass( 'max' );
     134                }
     135
     136                // Reposition
     137                tb_position();
     138
     139                $( '#TB_window' ).css( {
     140                        'height' : TB_HEIGHT + 'px'
     141                } );
     142
     143                $( '#TB_iframeContent' ).css( {
     144                        'width' : originalWidth - 1 + 'px',
     145                        'height' : TB_HEIGHT - 1 + 'px'
     146                } );
     147        } );
     148
     149        // Reposition on window resize
     150        $( window ).resize( function() { bp_tb_position(); } );
     151
     152        /**
     153         * Update the avatars for a given class
     154         *
     155         * @param  {string} avatarClass the name of the class
     156         * @param  {string} replace     the link to the avatar
     157         */
     158        bp.updateAvatars = function( avatarClass, replace ) {
     159                $( avatarClass ).each( function() {
     160                        $(this).prop( 'src', replace );
     161                } );
     162        };
     163
     164        /**
     165         * Update the cover image
     166         *
     167         * @param  {string} cover_url The url of the cover image
     168         */
     169        bp.updateCoverImage = function( cover_url ) {
     170                $( '#header-cover-image' ).css( {
     171                        'background-image': 'url( ' + cover_url + ' ) '
     172                } );
     173
     174                if ( $( '.bp-cover-image-preview' ).length ) {
     175
     176                        if ( ! cover_url ) {
     177                                $( '.bp-cover-image-preview' ).addClass( 'hide' );
     178                                $( '.bp-cover-image-preview' ).removeClass( 'thickbox' );
     179                        } else {
     180                                $( '.bp-cover-image-preview' ).addClass( 'thickbox' );
     181                                $( '.bp-cover-image-preview' ).removeClass( 'hide' );
     182                        }
     183
     184                        $( '.bp-cover-image-preview' ).prop( 'href', cover_url );
     185                }
     186        }
     187
     188        /**
     189         * Insert/Update html inside a given selector
     190         *
     191         * @param  {string} selectorId the element ID
     192         * @param  {string} html       the html to insert
     193         */
     194        bp.updateHtml = function( selectorId, html ) {
     195                $( selectorId ).html( html );
     196        };
     197
     198        /**
     199         * Insert/Update an input value
     200         * @param  {string} inputId the input ID
     201         * @param  {string} val     the value to insert
     202         */
     203        bp.updateVal = function( inputId, val ) {
     204                $( selectorId ).val( val );
     205        };
     206
     207} )( jQuery );
  • src/bp-groups/admin/css/admin.css

    diff --git src/bp-groups/admin/css/admin.css src/bp-groups/admin/css/admin.css
    index 651a6d5..aedbafa 100644
    table.bp-group-members .urole-column { 
    8484        padding-left: 20px;
    8585        padding-right: 20px;
    8686}
     87
     88div#bp_group_avatar div.avatar {
     89        width: 150px;
     90        margin: 0 auto;
     91}
     92
     93div#bp_group_avatar div.avatar img {
     94        max-width: 100%;
     95        height: auto;
     96}
     97
     98div#bp_group_avatar a.bp-groups-avatar-admin-edit,
     99div#bp_group_cover_image a.bp-groups-cover-image-admin-edit,
     100div#bp_group_cover_image a#bp-groups-cover-image-admin-preview {
     101    display: block;
     102    margin: 1em 0;
     103    text-decoration: none;
     104    color: #888;
     105}
     106
     107div#bp_group_cover_image a.bp-groups-cover-image-admin-edit,
     108div#bp_group_cover_image a#bp-groups-cover-image-admin-preview {
     109        text-align: center;
     110        display: inline-block;
     111        margin-right: 5px;
     112        font-size: 90%;
     113}
     114
     115div#bp_group_avatar a.bp-groups-avatar-admin-edit:before,
     116div#bp_group_cover_image a.bp-groups-cover-image-admin-edit:before,
     117div#bp_group_cover_image a#bp-groups-cover-image-admin-preview:before {
     118        font: normal 20px/1 'dashicons';
     119        speak: none;
     120        display: inline-block;
     121        padding: 0 2px 0 0;
     122        top: 0;
     123        left: -1px;
     124        position: relative;
     125        vertical-align: top;
     126        -webkit-font-smoothing: antialiased;
     127        -moz-osx-font-smoothing: grayscale;
     128        text-decoration: none !important;
     129        color: #888;
     130}
     131
     132div#bp_group_avatar a.bp-groups-avatar-admin-edit:before,
     133div#bp_group_cover_image a.bp-groups-cover-image-admin-edit:before {
     134        content: "\f107";
     135}
     136
     137div#bp_group_cover_image a#bp-groups-cover-image-admin-preview:before {
     138        content: "\f179";
     139}
     140
     141div#bp_group_cover_image a#bp-groups-cover-image-admin-preview.hide {
     142        display:none;
     143}
  • src/bp-groups/bp-groups-admin.php

    diff --git src/bp-groups/bp-groups-admin.php src/bp-groups/bp-groups-admin.php
    index 0abc180..a51231a 100644
    function bp_groups_admin_load() { 
    133133                add_meta_box( 'bp_group_add_members', _x( 'Add New Members', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_add_new_members', get_current_screen()->id, 'normal', 'core' );
    134134                add_meta_box( 'bp_group_members', _x( 'Manage Members', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_members', get_current_screen()->id, 'normal', 'core' );
    135135
     136                // Manage Group's avatar
     137                $disabled_avatar_uploads = (int) bp_disable_group_avatar_uploads();
     138                if ( ! $disabled_avatar_uploads && buddypress()->avatar->show_avatars && bp_attachments_is_wp_version_supported() ) {
     139                        add_meta_box( 'bp_group_avatar', _x( 'Photo', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_avatar', get_current_screen()->id, 'side', 'core' );
     140                }
     141
     142                // Metabox to manage the group's cover image
     143                if ( bp_group_use_cover_image_header() ) {
     144                        add_meta_box( 'bp_group_cover_images', _x( 'Cover Image', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_cover_image', get_current_screen()->id, 'side', 'core' );
     145                }
     146
    136147                /**
    137148                 * Fires after the registration of all of the default group meta boxes.
    138149                 *
    function bp_groups_admin_edit_metabox_settings( $item ) { 
    798809}
    799810
    800811/**
     812 * Output the markup for a single group's Edit Avatar metabox.
     813 *
     814 * @since 2.4.0
     815 */
     816function bp_groups_admin_edit_metabox_avatar( $item ) {
     817        ?>
     818        <div class="avatar">
     819
     820                <?php
     821                echo bp_core_fetch_avatar( array(
     822                        'item_id' => $item->id,
     823                        'object'  => 'group',
     824                        'type'    => 'full',
     825                        'title'   => $item->name
     826                ) );
     827
     828                bp_modal_link( array(
     829                        'item_id'       => $item,
     830                        'object'        => 'group',
     831                        'width'         => 800,
     832                        'height'        => 400,
     833                        'modal_title'   => __( 'Edit Group Photo', 'buddypress' ),
     834                        'modal_action'  => 'group-avatar',
     835                        'link_text'     => __( 'Edit Group Photo', 'buddypress' ),
     836                        'link_class'    => array( 'bp-groups-avatar-admin-edit' ),
     837                ) );
     838                ?>
     839
     840        </div>
     841        <?php
     842}
     843
     844/**
     845 * Output the markup for a single group's Edit cover image metabox.
     846 *
     847 * @since 2.4.0
     848 */
     849 function bp_groups_admin_edit_metabox_cover_image( $item ) {
     850        $dimensions = bp_attachments_get_cover_image_dimensions( 'groups' );
     851
     852        $cover_src = bp_attachments_get_attachment( 'url', array(
     853                'object_dir' => 'groups',
     854                'item_id'    => $item->id,
     855        ) );
     856
     857        printf( '
     858                <style type="text/css">
     859                        #header-cover-image {
     860                                display: block;
     861                                height: %1$spx;
     862                                background: #c5c5c5 url( %2$s );
     863                                background-position: center top;
     864                                background-size: cover;
     865                        }
     866                </style>
     867        ', $dimensions['height'], $cover_src );
     868        ?>
     869        <div id="bp_group_cover_image">
     870
     871                <div id="header-cover-image"></div>
     872
     873                <a id="bp-groups-cover-image-admin-preview" href="<?php echo esc_url( $cover_src ) ;?>" title="<?php esc_attr_e( 'Group Cover Image', 'budypress' ) ;?>" class="bp-cover-image-preview <?php echo ! empty( $cover_src ) ? 'thickbox' : 'hide' ;?>">
     874                        <?php esc_html_e( 'View Cover Image', 'budypress' ) ;?>
     875                </a>
     876
     877                <?php bp_modal_link( array(
     878                        'item_id'       => $item,
     879                        'object'        => 'group',
     880                        'width'         => 800,
     881                        'height'        => 400,
     882                        'modal_title'   => __( 'Edit Cover Image', 'buddypress' ),
     883                        'modal_action'  => 'group-cover-image',
     884                        'link_text'     => __( 'Edit Cover Image', 'buddypress' ),
     885                        'link_class'    => array( 'bp-groups-cover-image-admin-edit' ),
     886                ) ); ?>
     887
     888        </div>
     889        <?php
     890}
     891
     892/**
    801893 * Output the markup for a single group's Add New Members metabox.
    802894 *
    803895 * @since BuddyPress (1.7.0)
  • src/bp-groups/bp-groups-loader.php

    diff --git src/bp-groups/bp-groups-loader.php src/bp-groups/bp-groups-loader.php
    index c5f6f05..27a29a3 100644
    class BP_Groups_Component extends BP_Component { 
    313313                        );
    314314                }
    315315
     316                if ( bp_group_use_cover_image_header() ) {
     317                        $this->group_creation_steps['group-cover-image'] = array(
     318                                'name'     => _x( 'Cover Image', 'Group screen nav', 'buddypress' ),
     319                                'position' => 25
     320                        );
     321                }
     322
    316323                // If friends component is active, add invitations
    317324                if ( bp_is_active( 'friends' ) ) {
    318325                        $this->group_creation_steps['group-invites'] = array(
    class BP_Groups_Component extends BP_Component { 
    591598                                        ), $default_params );
    592599                                }
    593600
     601                                if ( bp_group_use_cover_image_header() ) {
     602                                        $sub_nav[] = array_merge( array(
     603                                                'name'     => __( 'Cover Image', 'buddypress' ),
     604                                                'slug'     => 'group-cover-image',
     605                                                'position' => 25,
     606                                        ), $default_params );
     607                                }
     608
    594609                                $sub_nav[] = array_merge( array(
    595610                                        'name'     => __( 'Members', 'buddypress' ),
    596611                                        'slug'     => 'manage-members',
  • src/bp-groups/bp-groups-screens.php

    diff --git src/bp-groups/bp-groups-screens.php src/bp-groups/bp-groups-screens.php
    index 1477c00..8567c2a 100644
    function groups_screen_group_admin_avatar() { 
    990990add_action( 'bp_screens', 'groups_screen_group_admin_avatar' );
    991991
    992992/**
     993 * Handle the display of a group's Change cover image page.
     994 *
     995 * @since 2.4.0
     996 */
     997function groups_screen_group_admin_cover_image() {
     998        if ( 'group-cover-image' != bp_get_group_current_admin_tab() ) {
     999                return false;
     1000        }
     1001
     1002        // If the logged-in user doesn't have permission or if cover image uploads are disabled, then stop here
     1003        if ( ! bp_is_item_admin() || bp_disable_group_avatar_uploads() ) {
     1004                return false;
     1005        }
     1006
     1007        /**
     1008         * Fires before the loading of the group Change cover image page template.
     1009         *
     1010         * @since 2.4.0
     1011         *
     1012         * @param int $id ID of the group that is being displayed.
     1013         */
     1014        do_action( 'groups_screen_group_admin_cover_image', bp_get_current_group_id() );
     1015
     1016        /**
     1017         * Filters the template to load for a group's Change cover image page.
     1018         *
     1019         * @since 2.4.0
     1020         *
     1021         * @param string $value Path to a group's Change cover image template.
     1022         */
     1023        bp_core_load_template( apply_filters( 'groups_template_group_admin_cover_image', 'groups/single/home' ) );
     1024}
     1025add_action( 'bp_screens', 'groups_screen_group_admin_cover_image' );
     1026
     1027/**
    9931028 * This function handles actions related to member management on the group admin.
    9941029 */
    9951030function groups_screen_group_admin_manage_members() {
    function groups_screen_group_admin_delete_group() { 
    13081343add_action( 'bp_screens', 'groups_screen_group_admin_delete_group' );
    13091344
    13101345/**
     1346 * Handle the display for a group modal
     1347 *
     1348 * @since 2.4.0
     1349 */
     1350function groups_sreen_modal() {
     1351        $bp = buddypress();
     1352
     1353        if ( bp_is_group_admin_page() && 'bp-modal' === bp_action_variable( 0 ) ) {
     1354
     1355                if ( ! bp_is_item_admin() ) {
     1356                        return;
     1357                }
     1358
     1359                if ( ! empty( $_GET['action'] ) ) {
     1360                        $bp->action_variables = array( sanitize_file_name( $_GET['action'] ) );
     1361                }
     1362
     1363                bp_set_is_modal( true );
     1364
     1365        } elseif ( 'bp-modal' === bp_current_action() ) {
     1366                if ( ! empty( $_GET['action'] ) ) {
     1367                        $bp->current_action = sanitize_file_name( $_GET['action'] );
     1368                }
     1369
     1370                bp_set_is_modal( true );
     1371        }
     1372
     1373        if ( bp_is_modal() ) {
     1374                bp_core_load_template( 'assets/modal' );
     1375        }
     1376}
     1377add_action( 'bp_screens', 'groups_sreen_modal', 0 );
     1378
     1379/**
    13111380 * Render the group settings fields on the Notification Settings page.
    13121381 */
    13131382function groups_screen_notification_settings() {
  • src/bp-groups/bp-groups-template.php

    diff --git src/bp-groups/bp-groups-template.php src/bp-groups/bp-groups-template.php
    index 0e3ec0a..46ad531 100644
    function bp_group_avatar_mini( $group = false ) { 
    998998                ) );
    999999        }
    10001000
     1001/** Group cover image *********************************************************/
     1002
     1003/**
     1004 * Should we use the group's cover image header
     1005 *
     1006 * @since 2.4.0
     1007 *
     1008 * @return bool True if the displayed user has a cover image,
     1009 *              False otherwise
     1010 */
     1011function bp_group_use_cover_image_header() {
     1012        return (bool) bp_is_active( 'groups', 'cover_image' ) && ! bp_disable_group_cover_image_uploads() && bp_attachments_is_wp_version_supported();
     1013}
     1014
    10011015/**
    10021016 * Output the 'last active' string for the current group in the loop.
    10031017 *
    function bp_groups_get_profile_stats( $args = '' ) { 
    62606274         */
    62616275        return apply_filters( 'bp_groups_get_profile_stats', $r['output'], $r );
    62626276}
     6277
     6278/**
     6279 * Output the Edit avatar template part for the group modal
     6280 *
     6281 * @since 2.4.0
     6282 */
     6283function bp_groups_modal_manage_avatar() {
     6284        ?>
     6285        <h1><?php esc_html_e( 'Edit Group Profile Photo', 'buddypress' ); ?></h1>
     6286
     6287        <?php bp_attachments_get_template_part( 'avatars/index' );
     6288}
     6289add_action( 'bp_modal_content_group-avatar', 'bp_groups_modal_manage_avatar' );
     6290
     6291/**
     6292 * Output the Edit cover image template part for the group modal
     6293 *
     6294 * @since 2.4.0
     6295 */
     6296function bp_groups_modal_manage_cover_image() {
     6297        ?>
     6298        <h1><?php esc_html_e( 'Edit Group Cover Image', 'buddypress' ); ?></h1>
     6299
     6300        <?php bp_attachments_get_template_part( 'cover-images/index' );
     6301}
     6302add_action( 'bp_modal_content_group-cover-image', 'bp_groups_modal_manage_cover_image' );
  • src/bp-members/admin/css/admin.css

    diff --git src/bp-members/admin/css/admin.css src/bp-members/admin/css/admin.css
    index c780cf9..12b05ce 100644
    div#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,
    2828div#community-profile-page a.bp-xprofile-avatar-user-admin:before,
    29 div#community-profile-page a.bp-xprofile-avatar-user-edit:before {
     29div#community-profile-page a.bp-xprofile-avatar-user-edit:before,
     30div#community-profile-page a.bp-xprofile-cover-image-user-edit:before,
     31div#community-profile-page a#bp-xprofile-cover-image-user-preview:before {
    3032        font: normal 20px/1 'dashicons';
    3133        speak: none;
    3234        display: inline-block;
    div#community-profile-page a.bp-xprofile-avatar-user-admin:before { 
    6163        content:"\f182";
    6264}
    6365
    64 div#community-profile-page a.bp-xprofile-avatar-user-edit:before {
     66div#community-profile-page a.bp-xprofile-avatar-user-edit:before,
     67div#community-profile-page a.bp-xprofile-cover-image-user-edit:before {
    6568        content: "\f107";
    6669}
    6770
     71div#community-profile-page a#bp-xprofile-cover-image-user-preview:before {
     72        content: "\f179";
     73}
     74
    6875div#community-profile-page div#bp_xprofile_user_admin_avatar div.avatar {
    6976        width:150px;
    7077        margin:0 auto;
    div#community-profile-page div#bp_xprofile_user_admin_avatar div.avatar img { 
    7582        height: auto;
    7683}
    7784
    78 div#community-profile-page div#bp_xprofile_user_admin_avatar a {
     85div#community-profile-page div#bp_xprofile_user_admin_avatar a,
     86div#community-profile-page a#bp-xprofile-cover-image-user-preview,
     87div#community-profile-page a.bp-xprofile-cover-image-user-edit {
    7988        display:block;
    8089        margin:1em 0;
    8190        text-decoration:none;
    8291        color:#888;
    8392}
    8493
     94div#community-profile-page a#bp-xprofile-cover-image-user-preview,
     95div#community-profile-page a.bp-xprofile-cover-image-user-edit {
     96        text-align: center;
     97        display: inline-block;
     98        margin-right: 5px;
     99        font-size: 90%;
     100}
     101
     102div#community-profile-page a#bp-xprofile-cover-image-user-preview.hide {
     103        display:none;
     104}
     105
    85106div#community-profile-page p.not-activated {
    86107        margin:1em 1em 0;
    87108        color:red;
  • src/bp-members/bp-members-screens.php

    diff --git src/bp-members/bp-members-screens.php src/bp-members/bp-members-screens.php
    index 2377fdc..c516fdf 100644
    function bp_core_screen_activation() { 
    377377}
    378378add_action( 'bp_screens', 'bp_core_screen_activation' );
    379379
     380/**
     381 * Handle the display for a user modal
     382 *
     383 * @since 2.4.0
     384 */
     385function bp_members_sreen_modal() {
     386        $bp = buddypress();
     387
     388        if ( bp_is_profile_component() && 'bp-modal' === bp_current_action() ) {
     389
     390                if ( ! bp_is_item_admin() ) {
     391                        return;
     392                }
     393
     394                if ( ! empty( $_GET['action'] ) ) {
     395                        $bp->current_action = sanitize_file_name( $_GET['action'] );
     396                }
     397
     398                bp_set_is_modal( true );
     399
     400        } elseif ( bp_is_user() && 'bp-modal' === bp_current_component() ) {
     401                if ( ! empty( $_GET['action'] ) ) {
     402                        $bp->current_action = sanitize_file_name( $_GET['action'] );
     403                }
     404
     405                bp_set_is_modal( true );
     406        }
     407
     408        if ( bp_is_modal() ) {
     409                bp_core_load_template( 'assets/modal' );
     410        }
     411}
     412add_action( 'bp_screens', 'bp_members_sreen_modal', 0 );
     413
    380414/** Theme Compatibility *******************************************************/
    381415
    382416/**
  • src/bp-members/bp-members-template.php

    diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php
    index f4d482f..50ce7ae 100644
    function bp_get_displayed_user_nav() { 
    14671467        }
    14681468}
    14691469
     1470/** Cover image ***************************************************************/
     1471
     1472/**
     1473 * Should we use the cover image header
     1474 *
     1475 * @since 2.4.0
     1476 *
     1477 * @return bool True if the displayed user has a cover image,
     1478 *              False otherwise
     1479 */
     1480function bp_displayed_user_use_cover_image_header() {
     1481        return (bool) bp_is_active( 'xprofile', 'cover_image' ) && ! bp_disable_cover_image_uploads() && bp_attachments_is_wp_version_supported();
     1482}
     1483
    14701484/** Avatars *******************************************************************/
    14711485
    14721486/**
  • src/bp-templates/bp-legacy/buddypress-functions.php

    diff --git src/bp-templates/bp-legacy/buddypress-functions.php src/bp-templates/bp-legacy/buddypress-functions.php
    index fb7cdb4..31d7889 100644
    class BP_Legacy extends BP_Theme_Compat { 
    5858         * @access private
    5959         */
    6060        protected function setup_globals() {
    61                 $bp            = buddypress();
    62                 $this->id      = 'legacy';
    63                 $this->name    = __( 'BuddyPress Legacy', 'buddypress' );
    64                 $this->version = bp_get_version();
    65                 $this->dir     = trailingslashit( $bp->themes_dir . '/bp-legacy' );
    66                 $this->url     = trailingslashit( $bp->themes_url . '/bp-legacy' );
     61                $bp             = buddypress();
     62                $this->id       = 'legacy';
     63                $this->name     = __( 'BuddyPress Legacy', 'buddypress' );
     64                $this->version  = bp_get_version();
     65                $this->dir      = trailingslashit( $bp->themes_dir . '/bp-legacy' );
     66                $this->url      = trailingslashit( $bp->themes_url . '/bp-legacy' );
    6767        }
    6868
    6969        /**
    class BP_Legacy extends BP_Theme_Compat { 
    123123                                add_action( 'bp_directory_blogs_actions',    'bp_blogs_visit_blog_button'           );
    124124                                add_action( 'bp_blogs_directory_blog_types', 'bp_legacy_theme_blog_create_nav', 999 );
    125125                        }
     126
     127                        // Wait till the BuddyPress loggedin user is set before creating the header's self profile buttons
     128                        add_action( 'bp_core_setup_globals', array( $this, 'self_profile_header_buttons' ) );
    126129                }
    127130
    128131                /** Notices ***********************************************************/
    class BP_Legacy extends BP_Theme_Compat { 
    597600
    598601                return $templates;
    599602        }
     603
     604        /**
     605         * Add Self Profile buttons to edit avatars and cover images
     606         *
     607         * @since 2.4.0
     608         */
     609        public function self_profile_header_buttons() {
     610                // Edit Avatar button
     611                if ( bp_self_profile_avatar_can_edit() ) {
     612                        add_action( 'bp_member_header_actions', 'bp_profile_edit_avatar_button',      5 );
     613                }
     614
     615                // Edit Cover Image button
     616                if ( bp_self_profile_cover_image_can_edit() ) {
     617                        add_action( 'bp_member_header_actions', 'bp_profile_edit_cover_image_button', 9 );
     618                }
     619        }
    600620}
    601621new BP_Legacy();
    602622endif;
    function bp_legacy_theme_ajax_messages_star_handler() { 
    17171737        echo '-1';
    17181738        die();
    17191739}
     1740
     1741/**
     1742 * BP Legacy's callback for the cover image feature
     1743 *
     1744 * @since  2.4.0
     1745 *
     1746 * @param  array  $params the current component's feature parameters
     1747 * @return array          an array to inform about the css handle to attach the css rules to
     1748 */
     1749function bp_legacy_theme_cover_image( $params = array() ) {
     1750        if ( empty( $params ) ) {
     1751                return;
     1752        }
     1753
     1754        // avatar height - padding - 1/2 avatar height
     1755        $avatar_offset = $params['height'] - 5 - round( (int) bp_core_avatar_full_height() / 2 );
     1756
     1757        // header content offset + spacing
     1758        $top_offset  = bp_core_avatar_full_height() - 10;
     1759        $left_offset = bp_core_avatar_full_width() + 20;
     1760
     1761        $cover_image = isset( $params['cover_image'] ) ? 'background-image: url(' . $params['cover_image'] . ');' : '';
     1762
     1763        $hide_avatar_style = '';
     1764
     1765        // Adjust the cover image header, in case avatars are completely disabled
     1766        if ( ! buddypress()->avatar->show_avatars ) {
     1767                $hide_avatar_style = '
     1768                        #buddypress #item-header-cover-image #item-header-avatar {
     1769                                display:  none;
     1770                        }
     1771                ';
     1772
     1773                if ( bp_is_user() ) {
     1774                        $hide_avatar_style = '
     1775                                #buddypress #item-header-cover-image #item-header-avatar a {
     1776                                        display: block;
     1777                                        height: ' . $top_offset . 'px;
     1778                                        margin: 0 15px 19px 0;
     1779                                }
     1780
     1781                                #buddypress div#item-header #item-header-cover-image #item-header-content {
     1782                                        margin-left:auto;
     1783                                }
     1784                        ';
     1785                }
     1786        }
     1787
     1788        return '
     1789                /* Cover image */
     1790                #buddypress #header-cover-image {
     1791                        height: ' . $params["height"] . 'px;
     1792                        ' . $cover_image . '
     1793                }
     1794
     1795                #buddypress #create-group-form #header-cover-image {
     1796                        position: relative;
     1797                        margin: 1em 0;
     1798                }
     1799
     1800                .bp-user #buddypress #item-header {
     1801                        padding-top: 0;
     1802                }
     1803
     1804                #buddypress #item-header-cover-image #item-header-avatar {
     1805                        margin-top: '. $avatar_offset .'px;
     1806                        float: none;
     1807                        overflow:visible;
     1808                        width:auto;
     1809                }
     1810
     1811                #buddypress div#item-header #item-header-cover-image #item-header-content {
     1812                        clear: both;
     1813                        float: left;
     1814                        margin-left: ' . $left_offset . 'px;
     1815                        margin-top: -' . $top_offset . 'px;
     1816                        width:auto;
     1817                }
     1818
     1819                body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-header-content,
     1820                body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions {
     1821                        margin-top: ' . $params["height"] . 'px;
     1822                        margin-left: 0;
     1823                        clear: none;
     1824                }
     1825
     1826                body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions {
     1827                        padding-top: 20px;
     1828                }
     1829
     1830                ' . $hide_avatar_style . '
     1831
     1832                /* This should only happen on regular screens */
     1833                #buddypress div#item-header-cover-image h2 a,
     1834                #buddypress div#item-header-cover-image h2 {
     1835                        color: #FFF;
     1836                        text-rendering: optimizelegibility;
     1837                        text-shadow: 0px 0px 3px rgba( 0, 0, 0, 0.8 );
     1838                        margin: 0;
     1839                        font-size:200%;
     1840                }
     1841
     1842                #buddypress #item-header-cover-image #item-header-avatar img.avatar {
     1843                        border: solid 2px #FFF;
     1844                        background: rgba( 255, 255, 255, 0.8 );
     1845                }
     1846
     1847                #buddypress #item-header-cover-image #item-header-avatar a {
     1848                        border: none;
     1849                        text-decoration: none;
     1850                }
     1851
     1852                #buddypress #item-header-cover-image #item-buttons {
     1853                        overflow:hidden;
     1854                        margin: 20px 0 10px;
     1855                        padding: 0 0 5px;
     1856                }
     1857
     1858                #buddypress #item-header-cover-image #item-buttons:before {
     1859                        content:"\00a0";
     1860                }
     1861
     1862                @media screen and (max-width: 782px) {
     1863                        #buddypress #item-header-cover-image #item-header-avatar,
     1864                        .bp-user #buddypress #item-header #item-header-cover-image #item-header-avatar,
     1865                        #buddypress div#item-header #item-header-cover-image #item-header-content {
     1866                                width:100%;
     1867                                text-align:center;
     1868                        }
     1869
     1870                        #buddypress #item-header-cover-image #item-header-avatar a {
     1871                                display:inline-block;
     1872                        }
     1873
     1874                        #buddypress #item-header-cover-image #item-header-avatar img {
     1875                                margin:0;
     1876                        }
     1877
     1878                        #buddypress div#item-header #item-header-cover-image #item-header-content,
     1879                        body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-header-content,
     1880                        body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions {
     1881                                margin:0;
     1882                        }
     1883
     1884                        #buddypress div#item-header-cover-image h2 a,
     1885                        #buddypress div#item-header-cover-image h2 {
     1886                                color: inherit;
     1887                                text-shadow: none;
     1888                                margin:25px 0 0;
     1889                                font-size:200%;
     1890                        }
     1891
     1892                        #buddypress #item-header-cover-image #item-buttons div {
     1893                                float:none;
     1894                                display:inline-block;
     1895                        }
     1896
     1897                        #buddypress #item-header-cover-image #item-buttons:before {
     1898                                content:"";
     1899                        }
     1900
     1901                        #buddypress #item-header-cover-image #item-buttons {
     1902                                margin: 5px 0;
     1903                        }
     1904                }
     1905        ';
     1906}
  • src/bp-templates/bp-legacy/buddypress/assets/_attachments/cover-images/index.php

    diff --git src/bp-templates/bp-legacy/buddypress/assets/_attachments/cover-images/index.php src/bp-templates/bp-legacy/buddypress/assets/_attachments/cover-images/index.php
    index e69de29..a552682 100644
     
     1<?php
     2/**
     3 * BuddyPress Cover Images main template
     4 *
     5 * This template is used to inject the BuddyPress Backbone views
     6 * dealing with cover images.
     7 * It's also used to create the common Backbone views
     8 *
     9 * @since 2.4
     10 *
     11 * @package BuddyPress
     12 * @subpackage bp-attachments
     13 */
     14?>
     15
     16<div class="bp-cover-image"></div>
     17<div class="bp-cover-image-status"></div>
     18<div class="bp-cover-image-manage"></div>
     19
     20<?php bp_attachments_get_template_part( 'uploader' ); ?>
     21
     22<script id="tmpl-bp-cover-image-delete" type="text/html">
     23        <# if ( 'user' === data.object ) { #>
     24                <p><?php _e( "If you'd like to delete your current cover image but not upload a new one, please use the delete Cover Image button.", 'buddypress' ); ?></p>
     25                <p><a class="button edit" id="bp-delete-cover-image" href="#" title="<?php esc_attr_e( 'Delete Cover Image', 'buddypress' ); ?>"><?php esc_html_e( 'Delete My Cover Image', 'buddypress' ); ?></a></p>
     26        <# } else if ( 'group' === data.object ) { #>
     27                <p><?php _e( "If you'd like to remove the existing group cover image but not upload a new one, please use the delete group cover image button.", 'buddypress' ); ?></p>
     28                <p><a class="button edit" id="bp-delete-cover-image" href="#" title="<?php esc_attr_e( 'Delete Cover Image', 'buddypress' ); ?>"><?php esc_html_e( 'Delete Group Cover Image', 'buddypress' ); ?></a></p>
     29        <# } else { #>
     30                <?php do_action( 'bp_attachments_cover_image_delete_template' ); ?>
     31        <# } #>
     32</script>
     33
     34<?php do_action( 'bp_attachments_cover_image_main_template' ); ?>
  • src/bp-templates/bp-legacy/buddypress/assets/modal.php

    diff --git src/bp-templates/bp-legacy/buddypress/assets/modal.php src/bp-templates/bp-legacy/buddypress/assets/modal.php
    index e69de29..d162ebc 100644
     
     1<?php
     2/**
     3 * BuddyPress Modal template
     4 *
     5 * This template is used to render the BuddyPress modal
     6 *
     7 * @since 2.4
     8 *
     9 * @package BuddyPress
     10 * @subpackage bp-core
     11 */
     12
     13$is_admin = false;
     14// Check if the modal was opened from an Admin page
     15// And enqueue admin style if needed
     16if ( ! empty( $_GET['is_admin'] ) ) {
     17        $is_admin = true;
     18        wp_enqueue_style( 'colors' );
     19}
     20
     21?>
     22<!DOCTYPE html>
     23<!--[if IE 8]>
     24<html xmlns="http://www.w3.org/1999/xhtml" class="ie8" <?php language_attributes(); ?>>
     25<![endif]-->
     26<!--[if !(IE 8) ]><!-->
     27<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?> style="background-color:#FFF">
     28<!--<![endif]-->
     29<head>
     30<meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php echo get_option( 'blog_charset' ); ?>" />
     31<title><?php bloginfo('name') ?> &rsaquo; <?php bp_modal_title(); ?></title>
     32
     33<?php bp_modal_header( $is_admin ); ?>
     34
     35</head>
     36<body class="bp-core-ui iframe <?php echo ( true === $is_admin ) ? 'bp-admin' : 'bp-front' ;?> no-js">
     37<script type="text/javascript">
     38document.body.className = document.body.className.replace('no-js', 'js');
     39</script>
     40
     41<div id="buddypress" class="bp-modal <?php echo ( true === $is_admin ) ? 'wrap' : '' ;?>">
     42
     43        <?php bp_modal_content(); ?>
     44
     45</div>
     46
     47<?php bp_modal_footer( $is_admin ); ?>
     48
     49</body>
     50</html>
  • 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 23deafc..2bb7f47 100644
    do_action( 'bp_before_create_group_page' ); ?> 
    255255
    256256                        <?php endif; ?>
    257257
    258                         <?php /* Group creation step 4: Invite friends to group */ ?>
     258                        <?php /* Group creation step 4: Cover image */ ?>
     259                        <?php if ( bp_is_group_creation_step( 'group-cover-image' ) ) : ?>
     260
     261                                <?php
     262
     263                                /**
     264                                 * Fires before the display of the group cover image creation step.
     265                                 *
     266                                 * @since 2.4.0
     267                                 */
     268                                do_action( 'bp_before_group_cover_image_creation_step' ); ?>
     269
     270                                <div id="header-cover-image"></div>
     271
     272                                <p><?php _e( 'The Cover Image will be used to customize the header of your group.', 'buddypress' ); ?></p>
     273
     274                                <?php bp_attachments_get_template_part( 'cover-images/index' ); ?>
     275
     276                                <?php
     277
     278                                /**
     279                                 * Fires after the display of the group cover image creation step.
     280                                 *
     281                                 * @since 2.4.0
     282                                 */
     283                                do_action( 'bp_after_group_cover_image_creation_step' ); ?>
     284
     285                                <?php wp_nonce_field( 'groups_create_save_group-cover-image' ); ?>
     286
     287                        <?php endif; ?>
     288
     289                        <?php /* Group creation step 5: Invite friends to group */ ?>
    259290                        <?php if ( bp_is_group_creation_step( 'group-invites' ) ) : ?>
    260291
    261292                                <?php
  • 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 25bcf3d..896e04c 100644
    do_action( 'bp_before_group_admin_content' ); ?> 
    218218
    219219<?php endif; ?>
    220220
     221<?php /* Group Cover image Settings */ ?>
     222<?php if ( bp_is_group_admin_screen( 'group-cover-image' ) ) : ?>
     223
     224        <h4><?php _e( 'Change Cover Image', 'buddypress' ); ?></h4>
     225
     226        <?php
     227
     228        /**
     229         * Fires before the display of profile cover image upload content.
     230         *
     231         * @since 2.4.0
     232         */
     233        do_action( 'bp_before_group_settings_cover_image' ); ?>
     234
     235        <p><?php _e( 'The Cover Image will be used to customize the header of your group.', 'buddypress' ); ?></p>
     236
     237        <?php bp_attachments_get_template_part( 'cover-images/index' ); ?>
     238
     239        <?php
     240
     241        /**
     242         * Fires after the display of group cover image upload content.
     243         *
     244         * @since 2.4.0
     245         */
     246        do_action( 'bp_after_group_settings_cover_image' ); ?>
     247
     248<?php endif; ?>
     249
    221250<?php /* Manage Group Members */ ?>
    222251<?php if ( bp_is_group_admin_screen( 'manage-members' ) ) : ?>
    223252
  • src/bp-templates/bp-legacy/buddypress/groups/single/cover-image-header.php

    diff --git src/bp-templates/bp-legacy/buddypress/groups/single/cover-image-header.php src/bp-templates/bp-legacy/buddypress/groups/single/cover-image-header.php
    index e69de29..248c448 100644
     
     1<?php
     2
     3/**
     4 * BuddyPress - Groups Cover Image Header
     5 *
     6 * @package BuddyPress
     7 * @subpackage bp-legacy
     8 */
     9
     10?>
     11
     12<?php
     13
     14/**
     15 * Fires before the display of a group's header.
     16 *
     17 * @since BuddyPress (1.2.0)
     18 */
     19do_action( 'bp_before_group_header' ); ?>
     20
     21<a id="header-cover-image" href="<?php bp_group_permalink(); ?>"></a>
     22
     23<div id="item-header-cover-image">
     24        <?php if ( ! bp_disable_group_avatar_uploads() ) : ?>
     25                <div id="item-header-avatar">
     26                        <a href="<?php bp_group_permalink(); ?>" title="<?php bp_group_name(); ?>">
     27
     28                                <?php bp_group_avatar(); ?>
     29
     30                        </a>
     31                </div><!-- #item-header-avatar -->
     32        <?php endif; ?>
     33
     34        <div id="item-header-content">
     35
     36                <div id="item-buttons">
     37
     38                        <?php
     39
     40                        /**
     41                         * Fires in the group header actions section.
     42                         *
     43                         * @since BuddyPress (1.2.6)
     44                         */
     45                        do_action( 'bp_group_header_actions' ); ?>
     46
     47                </div><!-- #item-buttons -->
     48
     49                <?php
     50
     51                /**
     52                 * Fires before the display of the group's header meta.
     53                 *
     54                 * @since BuddyPress (1.2.0)
     55                 */
     56                do_action( 'bp_before_group_header_meta' ); ?>
     57
     58                <div id="item-meta">
     59
     60                        <?php
     61
     62                        /**
     63                         * Fires after the group header actions section.
     64                         *
     65                         * @since BuddyPress (1.2.0)
     66                         */
     67                        do_action( 'bp_group_header_meta' ); ?>
     68
     69                        <span class="highlight"><?php bp_group_type(); ?></span>
     70                        <span class="activity"><?php printf( __( 'active %s', 'buddypress' ), bp_get_group_last_active() ); ?></span>
     71
     72                        <?php bp_group_description(); ?>
     73
     74                </div>
     75        </div><!-- #item-header-content -->
     76
     77        <div id="item-actions">
     78
     79                <?php if ( bp_group_is_visible() ) : ?>
     80
     81                        <h3><?php _e( 'Group Admins', 'buddypress' ); ?></h3>
     82
     83                        <?php bp_group_list_admins();
     84
     85                        /**
     86                         * Fires after the display of the group's administrators.
     87                         *
     88                         * @since BuddyPress (1.1.0)
     89                         */
     90                        do_action( 'bp_after_group_menu_admins' );
     91
     92                        if ( bp_group_has_moderators() ) :
     93
     94                                /**
     95                                 * Fires before the display of the group's moderators, if there are any.
     96                                 *
     97                                 * @since BuddyPress (1.1.0)
     98                                 */
     99                                do_action( 'bp_before_group_menu_mods' ); ?>
     100
     101                                <h3><?php _e( 'Group Mods' , 'buddypress' ); ?></h3>
     102
     103                                <?php bp_group_list_mods();
     104
     105                                /**
     106                                 * Fires after the display of the group's moderators, if there are any.
     107                                 *
     108                                 * @since BuddyPress (1.1.0)
     109                                 */
     110                                do_action( 'bp_after_group_menu_mods' );
     111
     112                        endif;
     113
     114                endif; ?>
     115
     116        </div><!-- #item-actions -->
     117
     118</div><!-- #item-header-cover-image -->
     119
     120<?php
     121
     122/**
     123 * Fires after the display of a group's header.
     124 *
     125 * @since BuddyPress (1.2.0)
     126 */
     127do_action( 'bp_after_group_header' );
     128
     129/** This action is documented in bp-templates/bp-legacy/buddypress/activity/index.php */
     130do_action( 'template_notices' ); ?>
  • src/bp-templates/bp-legacy/buddypress/groups/single/home.php

    diff --git src/bp-templates/bp-legacy/buddypress/groups/single/home.php src/bp-templates/bp-legacy/buddypress/groups/single/home.php
    index 6e2727c..7653c83 100644
     
    1313
    1414        <div id="item-header" role="complementary">
    1515
    16                 <?php bp_get_template_part( 'groups/single/group-header' ); ?>
     16                <?php
     17                /**
     18                 * If the cover image feature is enabled, use a specific header
     19                 */
     20                if ( bp_group_use_cover_image_header() ) :
     21                        bp_get_template_part( 'groups/single/cover-image-header' );
     22                else :
     23                        bp_get_template_part( 'groups/single/group-header' );
     24                endif;
     25                ?>
    1726
    1827        </div><!-- #item-header -->
    1928
  • src/bp-templates/bp-legacy/buddypress/members/single/cover-image-header.php

    diff --git src/bp-templates/bp-legacy/buddypress/members/single/cover-image-header.php src/bp-templates/bp-legacy/buddypress/members/single/cover-image-header.php
    index e69de29..d59cb47 100644
     
     1<?php
     2
     3/**
     4 * BuddyPress - Users Cover Image Header
     5 *
     6 * @package BuddyPress
     7 * @subpackage bp-legacy
     8 */
     9
     10?>
     11
     12<?php
     13
     14/**
     15 * Fires before the display of a member's header.
     16 *
     17 * @since BuddyPress (1.2.0)
     18 */
     19do_action( 'bp_before_member_header' ); ?>
     20
     21<a id="header-cover-image" href="<?php bp_displayed_user_link(); ?>"></a>
     22
     23<div id="item-header-cover-image">
     24        <div id="item-header-avatar">
     25                <a href="<?php bp_displayed_user_link(); ?>">
     26
     27                        <?php bp_displayed_user_avatar( 'type=full' ); ?>
     28
     29                </a>
     30        </div><!-- #item-header-avatar -->
     31
     32        <div id="item-header-content">
     33
     34                <?php if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) : ?>
     35                        <h2 class="user-nicename">@<?php bp_displayed_user_mentionname(); ?></h2>
     36                <?php endif; ?>
     37
     38                <div id="item-buttons">
     39
     40                        <?php
     41
     42                        /**
     43                         * Fires in the member header actions section.
     44                         *
     45                         * @since BuddyPress (1.2.6)
     46                         */
     47                        do_action( 'bp_member_header_actions' ); ?>
     48
     49                </div><!-- #item-buttons -->
     50
     51                <span class="activity"><?php bp_last_activity( bp_displayed_user_id() ); ?></span>
     52
     53                <?php
     54       
     55                /**
     56                 * Fires before the display of the member's header meta.
     57                 *
     58                 * @since BuddyPress (1.2.0)
     59                 */
     60                do_action( 'bp_before_member_header_meta' ); ?>
     61       
     62                <div id="item-meta">
     63       
     64                        <?php if ( bp_is_active( 'activity' ) ) : ?>
     65       
     66                                <div id="latest-update">
     67       
     68                                        <?php bp_activity_latest_update( bp_displayed_user_id() ); ?>
     69       
     70                                </div>
     71       
     72                        <?php endif; ?>
     73       
     74                        <?php
     75       
     76                         /**
     77                          * Fires after the group header actions section.
     78                          *
     79                          * If you'd like to show specific profile fields here use:
     80                          * bp_member_profile_data( 'field=About Me' ); -- Pass the name of the field
     81                          *
     82                          * @since BuddyPress (1.2.0)
     83                          */
     84                         do_action( 'bp_profile_header_meta' );
     85       
     86                         ?>
     87       
     88                </div><!-- #item-meta -->
     89
     90        </div><!-- #item-header-content -->
     91
     92</div><!-- #item-header-cover-image -->
     93
     94<?php
     95
     96/**
     97 * Fires after the display of a member's header.
     98 *
     99 * @since BuddyPress (1.2.0)
     100 */
     101do_action( 'bp_after_member_header' ); ?>
     102
     103<?php
     104
     105/** This action is documented in bp-templates/bp-legacy/buddypress/activity/index.php */
     106do_action( 'template_notices' ); ?>
  • src/bp-templates/bp-legacy/buddypress/members/single/home.php

    diff --git src/bp-templates/bp-legacy/buddypress/members/single/home.php src/bp-templates/bp-legacy/buddypress/members/single/home.php
    index 6b9f04c..bba27e2 100644
     
    1111
    1212        <div id="item-header" role="complementary">
    1313
    14                 <?php bp_get_template_part( 'members/single/member-header' ) ?>
     14                <?php
     15                /**
     16                 * If the cover image feature is enabled, use a specific header
     17                 */
     18                if ( bp_displayed_user_use_cover_image_header() ) :
     19                        bp_get_template_part( 'members/single/cover-image-header' );
     20                else :
     21                        bp_get_template_part( 'members/single/member-header' );
     22                endif;
     23                ?>
    1524
    1625        </div><!-- #item-header -->
    1726
  • src/bp-templates/bp-legacy/buddypress/members/single/profile.php

    diff --git src/bp-templates/bp-legacy/buddypress/members/single/profile.php src/bp-templates/bp-legacy/buddypress/members/single/profile.php
    index 165cd17..f419718 100644
    do_action( 'bp_before_profile_content' ); ?> 
    3838                bp_get_template_part( 'members/single/profile/change-avatar' );
    3939                break;
    4040
     41        // Change Cover Image
     42        case 'change-cover-image' :
     43                bp_get_template_part( 'members/single/profile/change-cover-image' );
     44                break;
     45
    4146        // Compose
    4247        case 'public' :
    4348
  • src/bp-templates/bp-legacy/buddypress/members/single/profile/change-cover-image.php

    diff --git src/bp-templates/bp-legacy/buddypress/members/single/profile/change-cover-image.php src/bp-templates/bp-legacy/buddypress/members/single/profile/change-cover-image.php
    index e69de29..718e750 100644
     
     1<h4><?php _e( 'Change Cover Image', 'buddypress' ); ?></h4>
     2
     3<?php
     4
     5/**
     6 * Fires before the display of profile cover image upload content.
     7 *
     8 * @since 2.4.0
     9 */
     10do_action( 'bp_before_profile_edit_cover_image' ); ?>
     11
     12<p><?php _e( 'Your Cover Image will be used to customize the header of your profile.', 'buddypress' ); ?></p>
     13
     14<?php bp_attachments_get_template_part( 'cover-images/index' ); ?>
     15
     16<?php
     17
     18/**
     19 * Fires after the display of profile cover image upload content.
     20 *
     21 * @since 2.4.0
     22 */
     23do_action( 'bp_after_profile_edit_cover_image' ); ?>
  • src/bp-templates/bp-legacy/css/buddypress.css

    diff --git src/bp-templates/bp-legacy/css/buddypress.css src/bp-templates/bp-legacy/css/buddypress.css
    index 0d78f61..f815fba 100644
    Hello, this is the BuddyPress Legacy stylesheet. 
    1919        3.6 - Ajax Loading
    2020        3.7 - Topics and Tables - Forums and General
    2121        3.8 - Headers, Lists and Tabs - Activity, Groups, Blogs, Forums
     22                3.8.1 - Cover Image
    2223        3.9 - Private Messaging Threads
    2324        3.10 - Extended Profiles
    2425        3.11 - Widgets
     26        3.12 - Modal
    25274.0 - Media Queries
    2628        4.1 - Smartphones Landscape
    2729        4.2 - Smartphones Portrait
    a.bp-title-button { 
    845847#buddypress form *[disabled="disabled"]{
    846848        cursor: default;
    847849        opacity: .4;
    848  }
     850}
     851
     852body.modal-open .screen-reader-text,
    849853.bp-screen-reader-text {
    850854        position: absolute;
    851855        margin: -1px;
    a.bp-title-button { 
    11721176}
    11731177#buddypress div#item-header {
    11741178        overflow: hidden;
     1179        position: relative;
    11751180}
    11761181#buddypress div#item-header div#item-header-content {
    11771182        float: left;
    a.bp-title-button { 
    12521257        float: left;
    12531258        margin: 10px 10px 0 0;
    12541259}
     1260body.no-js #buddypress div#item-header .js-self-profile-button {
     1261        display:none;
     1262}
    12551263#buddypress div#item-header div#message.info {
    12561264        line-height: 80%;
    12571265}
    body.activity-permalink #buddypress ul.item-list li.activity-item { 
    13971405        list-style: none;
    13981406}
    13991407
     1408/*--------------------------------------------------------------
     14093.8.1 - Cover Image
     1410--------------------------------------------------------------*/
     1411
     1412#buddypress #header-cover-image {
     1413        background-color: #c5c5c5;
     1414        background-position: center top;
     1415        background-repeat: no-repeat;
     1416        background-size: cover;
     1417        border: 0;
     1418        display: block;
     1419        left: 0;
     1420        margin: 0;
     1421        padding: 0;
     1422        position: absolute;
     1423        top: 0;
     1424        width: 100%;
     1425        z-index: 1;
     1426}
     1427
     1428#buddypress #item-header-cover-image {
     1429        padding: 0 1em;
     1430        position: relative;
     1431        z-index: 999;
     1432}
    14001433
    14011434/*--------------------------------------------------------------
    140214353.9 - Private Messaging Threads
    body.register #buddypress div.page ul { 
    16451678}
    16461679
    16471680/*--------------------------------------------------------------
     16813.11 - Modal
     1682--------------------------------------------------------------*/
     1683body.bp-core-ui {
     1684        background-color: #FFF;
     1685        width:98%;
     1686}
     1687
     1688#buddypress.bp-modal {
     1689        margin: 1em;
     1690}
     1691
     1692#buddypress.bp-modal h1 {
     1693        margin: 1em 0;
     1694}
     1695
     1696/*--------------------------------------------------------------
    164816974.0 - Media Queries
    16491698--------------------------------------------------------------*/
    16501699/*--------------------------------------------------------------
  • src/bp-templates/bp-legacy/css/twentyfifteen.css

    diff --git src/bp-templates/bp-legacy/css/twentyfifteen.css src/bp-templates/bp-legacy/css/twentyfifteen.css
    index 7c9eabf..d56436c 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    957957
    958958.bp-user #buddypress #item-header #item-header-avatar img.avatar,
    959959.bp-user #buddypress #item-header #item-header-avatar a {
    960         border-bottom: 0;
     960        border-bottom-color: #fff;
    961961        display: inline-block;
    962962        float: none;
    963963}
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    967967                float: left;
    968968                width: 20%;
    969969        }
    970         .bp-user #buddypress #item-header #item-header-avatar img.avatar,
     970
    971971        .bp-user #buddypress #item-header #item-header-avatar a {
    972                 float: left;
    973                 width: 100%;
    974972        }
    975973        .bp-user #buddypress #item-header #item-header-content {
    976974                float: right;
  • src/bp-templates/bp-legacy/css/twentyfifteen.scss

    diff --git src/bp-templates/bp-legacy/css/twentyfifteen.scss src/bp-templates/bp-legacy/css/twentyfifteen.scss
    index 22c7eba..267a0d1 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    11991199                                text-align: center;
    12001200                                width: 100%;
    12011201
    1202                                 img.avatar,
    12031202                                a {
    12041203                                        border-bottom: 0;
    12051204                                        display: inline-block;
  • src/bp-templates/bp-legacy/css/twentyfourteen.css

    diff --git src/bp-templates/bp-legacy/css/twentyfourteen.css src/bp-templates/bp-legacy/css/twentyfourteen.css
    index b00e3fe..833cbfa 100644
    body.activity-permalink #buddypress { 
    782782                text-align: left;
    783783                width: 20%;
    784784        }
    785         .bp-user #buddypress #item-header #item-header-avatar img {
    786                 margin: 0;
    787         }
    788785        .bp-user #buddypress #item-header #item-header-content {
    789786                float: right;
    790787                width: 78%;
  • src/bp-templates/bp-legacy/css/twentyfourteen.scss

    diff --git src/bp-templates/bp-legacy/css/twentyfourteen.scss src/bp-templates/bp-legacy/css/twentyfourteen.scss
    index 8b9872f..dcf6ed7 100644
    body.activity-permalink { 
    11001100                                overflow: hidden;
    11011101                                text-align: left;
    11021102                                width: 20%;
    1103 
    1104                                 img {margin: 0;}
    11051103                        }
    11061104
    11071105                        #item-header-content {
  • src/bp-templates/bp-legacy/css/twentythirteen.css

    diff --git src/bp-templates/bp-legacy/css/twentythirteen.css src/bp-templates/bp-legacy/css/twentythirteen.css
    index d2eb95e..0405201 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    943943
    944944.bp-user #buddypress #item-header #item-header-avatar img.avatar,
    945945.bp-user #buddypress #item-header #item-header-avatar a {
    946         border-bottom: 0;
    947946        display: inline-block;
    948947        float: none;
    949948}
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    953952                float: left;
    954953                width: 20%;
    955954        }
    956         .bp-user #buddypress #item-header #item-header-avatar img.avatar,
     955
    957956        .bp-user #buddypress #item-header #item-header-avatar a {
    958                 float: left;
    959                 width: 100%;
    960957        }
    961958        .bp-user #buddypress #item-header #item-header-content {
    962959                float: right;
  • src/bp-templates/bp-legacy/css/twentythirteen.scss

    diff --git src/bp-templates/bp-legacy/css/twentythirteen.scss src/bp-templates/bp-legacy/css/twentythirteen.scss
    index 427a724..17a26f0 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    12671267                                        float: left;
    12681268                                        width: 20%;
    12691269
    1270                                         img.avatar,
    12711270                                        a {
    12721271                                                float: left;
    1273                                                 width: 100%;
    12741272                                        }
    12751273                                }
    12761274
  • src/bp-xprofile/bp-xprofile-admin.php

    diff --git src/bp-xprofile/bp-xprofile-admin.php src/bp-xprofile/bp-xprofile-admin.php
    index d729a7e..c42478b 100644
    class BP_XProfile_User_Admin { 
    684684         * @since BuddyPress (2.0.0)
    685685         */
    686686        private function setup_actions() {
    687                 // Enqueue scripts
    688                 add_action( 'bp_members_admin_enqueue_scripts',  array( $this, 'enqueue_scripts'    ), 10, 1 );
    689 
    690687                // Register the metabox in Member's community admin profile
    691688                add_action( 'bp_members_admin_xprofile_metabox', array( $this, 'register_metaboxes' ), 10, 3 );
    692689
    class BP_XProfile_User_Admin { 
    695692        }
    696693
    697694        /**
    698          * Enqueue needed scripts.
    699          *
    700          * @access public
    701          * @since BuddyPress (2.3.0)
    702          */
    703         public function enqueue_scripts( $screen_id ) {
    704                 if ( ( false === strpos( $screen_id, 'users_page_bp-profile-edit' )
    705                         && false === strpos( $screen_id, 'profile_page_bp-profile-edit' ) )
    706                         || bp_core_get_root_option( 'bp-disable-avatar-uploads' )
    707                         || ! buddypress()->avatar->show_avatars
    708                         || ! bp_attachments_is_wp_version_supported() ) {
    709                         return;
    710                 }
    711 
    712                 /**
    713                  * Get Thickbox
    714                  *
    715                  * We cannot simply use add_thickbox() here as WordPress is not playing
    716                  * nice with Thickbox width/height see https://core.trac.wordpress.org/ticket/17249
    717                  * Using media-upload might be interesting in the future for the send to editor stuff
    718                  * and we make sure the tb_window is wide enougth
    719                  */
    720                 wp_enqueue_style ( 'thickbox' );
    721                 wp_enqueue_script( 'media-upload' );
    722 
    723                 // Get Avatar Uploader
    724                 bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' );
    725         }
    726 
    727         /**
    728695         * Register the xProfile metabox on Community Profile admin page.
    729696         *
    730697         * @access public
    class BP_XProfile_User_Admin { 
    794761                                'low'
    795762                        );
    796763                }
     764
     765                if ( bp_displayed_user_use_cover_image_header() ) {
     766                        // Cover Image Metabox
     767                        add_meta_box(
     768                                'bp_xprofile_user_admin_cover_image',
     769                                _x( 'Profile Photo', 'xprofile user-admin edit screen', 'buddypress' ),
     770                                array( $this, 'user_admin_cover_image_metabox' ),
     771                                $screen_id,
     772                                'side',
     773                                'low'
     774                        );
     775                }
    797776        }
    798777
    799778        /**
    class BP_XProfile_User_Admin { 
    10641043                                'object'  => 'user',
    10651044                                'type'    => 'full',
    10661045                                'title'   => $user->display_name
    1067                         ) ); ?>
    1068 
    1069                         <?php if ( bp_get_user_has_avatar( $user->ID ) ) :
     1046                        ) );
     1047
     1048                        // Add a BuddyPress modal to edit the avatar
     1049                        if ( ! bp_core_get_root_option( 'bp-disable-avatar-uploads' ) && bp_attachments_is_wp_version_supported() ) :
     1050                                bp_modal_link( array(
     1051                                        'item_id'       => $user->ID,
     1052                                        'object'        => 'user',
     1053                                        'width'         => 800,
     1054                                        'height'        => 400,
     1055                                        'modal_title'   => __( 'Edit Profile Photo', 'buddypress' ),
     1056                                        'modal_action'  => 'change-avatar',
     1057                                        'link_text'     => __( 'Edit Profile Photo', 'buddypress' ),
     1058                                        'link_class'    => array( 'bp-xprofile-avatar-user-edit' ),
     1059                                ) );
     1060
     1061                        elseif ( bp_get_user_has_avatar( $user->ID ) ) :
    10701062
    10711063                                $query_args = array(
    10721064                                        'user_id' => $user->ID,
    class BP_XProfile_User_Admin { 
    10821074
    10831075                                <a href="<?php echo esc_url( $delete_link ); ?>" title="<?php esc_attr_e( 'Delete Profile Photo', 'buddypress' ); ?>" class="bp-xprofile-avatar-user-admin"><?php esc_html_e( 'Delete Profile Photo', 'buddypress' ); ?></a></li>
    10841076
    1085                         <?php endif;
    1086 
    1087                         // Load the Avatar UI templates if user avatar uploads are enabled and current WordPress version is supported
    1088                         if ( ! bp_core_get_root_option( 'bp-disable-avatar-uploads' ) && bp_attachments_is_wp_version_supported() ) : ?>
    1089                                 <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>
    1090                                 <div id="bp-xprofile-avatar-editor" style="display:none;">
    1091                                         <?php bp_attachments_get_template_part( 'avatars/index' ); ?>
    1092                                 </div>
    1093                         <?php endif; ?>
     1077                        <?php endif;  ?>
    10941078
    10951079                </div>
    10961080                <?php
    10971081        }
    10981082
     1083        /**
     1084         * Output the markup for a single group's Edit cover image metabox.
     1085         *
     1086         * @since 2.4.0
     1087         *
     1088         * @param WP_User $user The WP_User object for the user being edited.
     1089         */
     1090        public function user_admin_cover_image_metabox( $user = null ) {
     1091                $dimensions = bp_attachments_get_cover_image_dimensions( 'xprofile' );
     1092
     1093                $cover_src = bp_attachments_get_attachment( 'url', array(
     1094                        'object_dir' => 'members',
     1095                        'item_id'    => $user->ID,
     1096                ) );
     1097
     1098                printf( '
     1099                        <style type="text/css">
     1100                                #header-cover-image {
     1101                                        display: block;
     1102                                        height: %1$spx;
     1103                                        background: #c5c5c5 url( %2$s );
     1104                                        background-position: center top;
     1105                                        background-size: cover;
     1106                                }
     1107                        </style>
     1108                ', $dimensions['height'], $cover_src );
     1109                ?>
     1110                <div id="bp_group_cover_image">
     1111
     1112                        <div id="header-cover-image"></div>
     1113
     1114                                <a id="bp-xprofile-cover-image-user-preview" href="<?php echo esc_url( $cover_src ) ;?>" title="<?php esc_attr_e( 'User Cover Image', 'budypress' ) ;?>" class="bp-cover-image-preview <?php echo ! empty( $cover_src ) ? 'thickbox' : 'hide' ;?>">
     1115                                        <?php esc_html_e( 'View Cover Image', 'budypress' ) ;?>
     1116                                </a>
     1117
     1118                                <?php bp_modal_link( array(
     1119                                        'item_id'       => $user->ID,
     1120                                        'object'        => 'user',
     1121                                        'width'         => 800,
     1122                                        'height'        => 400,
     1123                                        'modal_title'   => __( 'Edit Cover Image', 'buddypress' ),
     1124                                        'modal_action'  => 'change-cover-image',
     1125                                        'link_text'     => __( 'Edit Cover Image', 'buddypress' ),
     1126                                        'link_class'    => array( 'bp-xprofile-cover-image-user-edit' ),
     1127                                ) ); ?>
     1128
     1129                </div>
     1130        <?php
     1131        }
    10991132}
    11001133endif; // class_exists check
    11011134
  • src/bp-xprofile/bp-xprofile-loader.php

    diff --git src/bp-xprofile/bp-xprofile-loader.php src/bp-xprofile/bp-xprofile-loader.php
    index a38b21b..3372009 100644
    class BP_XProfile_Component extends BP_Component { 
    228228                        );
    229229                }
    230230
     231                // Change Cover image
     232                if ( bp_displayed_user_use_cover_image_header() ) {
     233                        $sub_nav[] = array(
     234                                'name'            => _x( 'Change Cover Image', 'Profile header sub menu', 'buddypress' ),
     235                                'slug'            => 'change-cover-image',
     236                                'parent_url'      => $profile_link,
     237                                'parent_slug'     => $slug,
     238                                'screen_function' => 'xprofile_screen_change_cover_image',
     239                                'position'        => 40,
     240                                'user_has_access' => $access
     241                        );
     242                }
     243
    231244                // The Settings > Profile nav item can only be set up after
    232245                // the Settings component has run its own nav routine
    233246                add_action( 'bp_settings_setup_nav', array( $this, 'setup_settings_nav' ) );
    class BP_XProfile_Component extends BP_Component { 
    316329                                );
    317330                        }
    318331
     332                        if ( bp_displayed_user_use_cover_image_header() ) {
     333                                $wp_admin_nav[] = array(
     334                                        'parent' => 'my-account-' . $this->id,
     335                                        'id'     => 'my-account-' . $this->id . '-change-cover-image',
     336                                        'title'  => _x( 'Change Cover Image', 'My Account Profile sub nav', 'buddypress' ),
     337                                        'href'   => trailingslashit( $profile_link . 'change-cover-image' )
     338                                );
     339                        }
    319340                }
    320341
    321342                parent::setup_admin_bar( $wp_admin_nav );
  • src/bp-xprofile/bp-xprofile-screens.php

    diff --git src/bp-xprofile/bp-xprofile-screens.php src/bp-xprofile/bp-xprofile-screens.php
    index afb4604..0f40b8a 100644
    function xprofile_screen_change_avatar() { 
    292292}
    293293
    294294/**
     295 * Displays the change cover image page.
     296 *
     297 * @package BuddyPress XProfile
     298 *
     299 * @since 2.4.0
     300 */
     301function xprofile_screen_change_cover_image() {
     302
     303        // Bail if not the correct screen
     304        if ( ! bp_is_my_profile() && ! bp_current_user_can( 'bp_moderate' ) ) {
     305                return false;
     306        }
     307
     308        /**
     309         * Fires right before the loading of the XProfile change cover image screen template file.
     310         *
     311         * @since 2.4.0
     312         */
     313        do_action( 'xprofile_screen_change_cover_image' );
     314
     315        /**
     316         * Filters the template to load for the XProfile cover image screen.
     317         *
     318         * @since 2.4.0
     319         *
     320         * @param string $template Path to the XProfile cover image template to load.
     321         */
     322        bp_core_load_template( apply_filters( 'xprofile_template_cover_image', 'members/single/home' ) );
     323}
     324
     325/**
    295326 * Show the xprofile settings template
    296327 *
    297328 * @since BuddyPress (2.0.0)
  • src/bp-xprofile/bp-xprofile-template.php

    diff --git src/bp-xprofile/bp-xprofile-template.php src/bp-xprofile/bp-xprofile-template.php
    index 10caa0e..369ddad 100644
    function bp_profile_settings_visibility_select( $args = '' ) { 
    13231323                 */
    13241324                return apply_filters( 'bp_profile_settings_visibility_select', $retval, $r, $args );
    13251325        }
     1326
     1327/** Avatars */
     1328
     1329/**
     1330 * Does the avatar can be edited from the current user's profile
     1331 *
     1332 * @since  2.4.0
     1333 *
     1334 * @return bool True if the avatar can be edited from the current user's profile. False otherwise.
     1335 */
     1336function bp_self_profile_avatar_can_edit() {
     1337        // Default value
     1338        $can = buddypress()->avatar->show_avatars && bp_attachments_is_wp_version_supported() && ! bp_disable_avatar_uploads();
     1339
     1340        if ( ! bp_is_my_profile() ) {
     1341                $can = false;
     1342        }
     1343
     1344        /**
     1345         * Filter here if you want to disable the member's header edit avatar button
     1346         *
     1347         * @since  2.4.0
     1348         *
     1349         * @param bool $can True if the avatar can be edited. False otherwise.
     1350         */
     1351        return apply_filters( 'bp_self_profile_avatar_can_edit', $can );
     1352}
     1353
     1354/**
     1355 * Output the self profile edit avatar button
     1356 *
     1357 * @since  2.4.0
     1358 */
     1359function bp_profile_edit_avatar_button() {
     1360        echo bp_get_profile_edit_avatar_button();
     1361}
     1362        /**
     1363         * Get the self profile edit avatar button
     1364         *
     1365         * @since  2.4.0
     1366         *
     1367         * @return string HTML output
     1368         */
     1369        function bp_get_profile_edit_avatar_button() {
     1370                // Get the modal link
     1371                $modal_link = bp_get_modal_link( array(
     1372                        'item_id'       => bp_loggedin_user_id(),
     1373                        'object'        => 'user',
     1374                        'width'         => 800,
     1375                        'height'        => 480,
     1376                        'modal_title'   => __( 'Edit Profile Photo', 'buddypress' ),
     1377                        'modal_action'  => 'change-avatar',
     1378                        'html'          => false,
     1379                ) );
     1380
     1381                // Get the button
     1382                $button = array(
     1383                        'id'                => 'edit_profile_photo',
     1384                        'component'         => 'xprofile',
     1385                        'must_be_logged_in' => true,
     1386                        'block_self'        => false,
     1387                        'wrapper_class'     => 'js-self-profile-button edit-profile-photo-button',
     1388                        'wrapper_id'        => 'edit-profile-photo-button-' . bp_loggedin_user_id(),
     1389                        'link_href'         => esc_url( $modal_link ),
     1390                        'link_text'         => __( 'Edit Profile Photo', 'buddypress' ),
     1391                        'link_title'        => __( 'Edit Profile Photo', 'buddypress' ),
     1392                        'link_class'        => 'bp-thickbox'
     1393                );
     1394
     1395                /**
     1396                 * Filters the HTML for the edit avatar button.
     1397                 *
     1398                 * @since 2.4.0
     1399                 *
     1400                 * @param string $button HTML markup for edit avatar button.
     1401                 */
     1402                return bp_get_button( apply_filters( 'bp_get_profile_edit_avatar_button', $button ) );
     1403        }
     1404
     1405/**
     1406 * Output the Edit avatar template part for the user modal
     1407 *
     1408 * @since 2.4.0
     1409 */
     1410function bp_profile_modal_manage_avatar() {
     1411        ?>
     1412
     1413        <h1><?php esc_html_e( 'Edit Profile Photo', 'buddypress' ); ?></h1>
     1414
     1415        <?php bp_attachments_get_template_part( 'avatars/index' );
     1416}
     1417add_action( 'bp_modal_content_change-avatar', 'bp_profile_modal_manage_avatar' );
     1418
     1419/** Cover Images */
     1420
     1421/**
     1422 * Does the cover image can be edited from the current user's profile
     1423 *
     1424 * @since  2.4.0
     1425 *
     1426 * @return bool True if the cover image can be edited from the current user's profile. False otherwise.
     1427 */
     1428function bp_self_profile_cover_image_can_edit() {
     1429        // Default value
     1430        $can = bp_displayed_user_use_cover_image_header();
     1431
     1432        if ( ! bp_is_my_profile() ) {
     1433                $can = false;
     1434        }
     1435
     1436        /**
     1437         * Filter here if you want to disable the member's header edit cover image button
     1438         *
     1439         * @since  2.4.0
     1440         *
     1441         * @param bool $can True if the cover image can be edited. False otherwise.
     1442         */
     1443        return apply_filters( 'bp_self_profile_cover_image_can_edit', $can );
     1444}
     1445
     1446/**
     1447 * Output the self profile edit cover image button
     1448 *
     1449 * @since  2.4.0
     1450 */
     1451function bp_profile_edit_cover_image_button() {
     1452        echo bp_get_profile_edit_cover_image_button();
     1453}
     1454
     1455        /**
     1456         * Get the self profile edit cover image button
     1457         *
     1458         * @since  2.4.0
     1459         *
     1460         * @return string HTML output
     1461         */
     1462        function bp_get_profile_edit_cover_image_button() {
     1463                // Get the modal link
     1464                $modal_link = bp_get_modal_link( array(
     1465                        'item_id'       => bp_loggedin_user_id(),
     1466                        'object'        => 'user',
     1467                        'width'         => 800,
     1468                        'height'        => 480,
     1469                        'modal_title'   => __( 'Edit Cover Image', 'buddypress' ),
     1470                        'modal_action'  => 'change-cover-image',
     1471                        'html'          => false,
     1472                ) );
     1473
     1474                // Get the button
     1475                $button = array(
     1476                        'id'                => 'edit_cover_image',
     1477                        'component'         => 'xprofile',
     1478                        'must_be_logged_in' => true,
     1479                        'block_self'        => false,
     1480                        'wrapper_class'     => 'js-self-profile-button edit-cover-image-button',
     1481                        'wrapper_id'        => 'edit-cover-image-button-' . bp_loggedin_user_id(),
     1482                        'link_href'         => esc_url( $modal_link ),
     1483                        'link_text'         => __( 'Edit Cover Image', 'buddypress' ),
     1484                        'link_title'        => __( 'Edit Cover Image', 'buddypress' ),
     1485                        'link_class'        => 'bp-thickbox'
     1486                );
     1487
     1488                /**
     1489                 * Filters the HTML for the edit cover image button.
     1490                 *
     1491                 * @since 2.4.0
     1492                 *
     1493                 * @param string $button HTML markup for edit cover image button.
     1494                 */
     1495                return bp_get_button( apply_filters( 'bp_get_profile_edit_cover_image_button', $button ) );
     1496        }
     1497
     1498/**
     1499 * Output the Edit cover image template part for the user modal
     1500 *
     1501 * @since 2.4.0
     1502 */
     1503function bp_profile_modal_manage_cover_image() {
     1504        ?>
     1505
     1506        <h1><?php esc_html_e( 'Edit Cover Image', 'buddypress' ); ?></h1>
     1507
     1508        <?php bp_attachments_get_template_part( 'cover-images/index' );
     1509}
     1510add_action( 'bp_modal_content_change-cover-image', 'bp_profile_modal_manage_cover_image' );
  • tests/phpunit/testcases/core/class-bp-attachment.php

    diff --git tests/phpunit/testcases/core/class-bp-attachment.php tests/phpunit/testcases/core/class-bp-attachment.php
    index f6e7d13..35d0476 100644
    class BP_Tests_BP_Attachment_TestCases extends BP_UnitTestCase { 
    328328                // clean up!
    329329                $this->clean_files();
    330330        }
     331
     332        /**
     333         * @group upload
     334         * @group cover_image
     335         */
     336        public function test_bp_attachment_cover_image_user_upload() {
     337                $reset_files = $_FILES;
     338                $reset_post = $_POST;
     339                $bp = buddypress();
     340                $displayed_user = $bp->displayed_user;
     341                $bp->displayed_user = new stdClass;
     342
     343                $u1 = $this->factory->user->create();
     344                $bp->displayed_user->id = $u1;
     345
     346                // Upload the file
     347                $cover_image_attachment = new BP_Attachment_Cover_Image();
     348                $_POST['action'] = $cover_image_attachment->action;
     349                $_FILES[ $cover_image_attachment->file_input ] = array(
     350                        'tmp_name' => $this->image_file,
     351                        'name'     => 'mystery-man.jpg',
     352                        'type'     => 'image/jpeg',
     353                        'error'    => 0,
     354                        'size'     => filesize( $this->image_file )
     355                );
     356
     357                /* No error */
     358                $cover_image = $cover_image_attachment->upload( $_FILES );
     359                $this->assertEquals( $cover_image['file'], $bp->avatar->upload_path . '/buddypress/members/' . $u1 .'/cover-image/mystery-man.jpg' );
     360
     361                // clean up!
     362                $bp->displayed_user = $displayed_user;
     363                $this->clean_files( 'buddypress' );
     364                $_FILES = $reset_files;
     365                $_POST = $reset_post;
     366        }
    331367}