Skip to:
Content

BuddyPress.org

Ticket #6570: 6570.05.patch

File 6570.05.patch, 150.1 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 39dd4ea..67119e4 100644
    function bp_admin_setting_callback_avatar_uploads() { 
    159159<?php
    160160}
    161161
     162/**
     163 * Allow members to upload cover images field.
     164 *
     165 * @since 2.4.0
     166 */
     167function bp_admin_setting_callback_cover_image_uploads() {
     168?>
     169        <input id="bp-disable-cover-image-uploads" name="bp-disable-cover-image-uploads" type="checkbox" value="1" <?php checked( ! bp_disable_cover_image_uploads() ); ?> />
     170        <label for="bp-disable-cover-image-uploads"><?php _e( 'Allow registered members to upload cover images', 'buddypress' ); ?></label>
     171<?php
     172}
     173
    162174/** Groups Section ************************************************************/
    163175
    164176/**
    function bp_admin_setting_callback_group_avatar_uploads() { 
    197209<?php
    198210}
    199211
     212/**
     213 * 'Enable group cover images' field markup.
     214 *
     215 * @since 2.4.0
     216 */
     217function bp_admin_setting_callback_group_cover_image_uploads() {
     218?>
     219        <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() ); ?> />
     220        <label for="bp-disable-group-cover-image-uploads"><?php _e( 'Allow customizable cover images for groups', 'buddypress' ); ?></label>
     221<?php
     222}
     223
    200224/** Forums Section ************************************************************/
    201225
    202226/**
    function bp_core_admin_settings_save() { 
    299323                $legacy_options = array(
    300324                        'bp-disable-account-deletion',
    301325                        'bp-disable-avatar-uploads',
     326                        'bp-disable-cover-image-uploads',
    302327                        'bp-disable-group-avatar-uploads',
     328                        'bp-disable-group-cover-image-uploads',
    303329                        'bp_disable_blogforum_comments',
    304330                        'bp-disable-profile-sync',
    305331                        '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 7457ddd..2b3a770 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 785c4f6..fa36231 100644
    function bp_attachments_is_wp_version_supported() { 
    2525}
    2626
    2727/**
     28 * Get the max upload file size for any attachment
     29 *
     30 * @since  2.4.0
     31 *
     32 * @param  string $type A string to inform about the type of attachment
     33 *                      we wish to get the max upload file size for
     34 * @return int    max upload file size for any attachment
     35 */
     36function bp_attachments_get_max_upload_file_size( $type = '' ) {
     37        $fileupload_maxk = bp_core_get_root_option( 'fileupload_maxk' );
     38
     39        if ( '' === $fileupload_maxk ) {
     40                $fileupload_maxk = 5120000; // 5mb;
     41        } else {
     42                $fileupload_maxk = $fileupload_maxk * 1024;
     43        }
     44
     45        /**
     46         * Filter here to edit the max upload file size.
     47         *
     48         * @since  2.4.0
     49         *
     50         * @param  int    $fileupload_maxk Max upload file size for any attachment
     51         * @param  string $type            The attachment type (eg: 'avatar' or 'cover_image')
     52         */
     53        return apply_filters( 'bp_attachments_get_max_upload_file_size', $fileupload_maxk, $type );
     54}
     55
     56/**
     57 * Get allowed types for any attachment
     58 *
     59 * @since  2.4.0
     60 *
     61 * @param  string $type  The extension types to get.
     62 *                       Default: 'avatar'
     63 * @return array         The list of allowed extensions for attachments
     64 */
     65function bp_attachments_get_allowed_types( $type = 'avatar' ) {
     66        // Defaults to BuddyPress supported image extensions
     67        $exts = array( 'jpeg', 'gif', 'png' );
     68
     69        /**
     70         * It's not a BuddyPress feature, get the allowed extensions
     71         * matching the $type requested
     72         */
     73        if ( 'avatar' !== $type && 'cover_image' !== $type ) {
     74                // Reset the default exts
     75                $exts = array();
     76
     77                switch ( $type ) {
     78                        case 'video' :
     79                                $exts = wp_get_video_extensions();
     80                        break;
     81
     82                        case 'audio' :
     83                                $exts = wp_get_video_extensions();
     84                        break;
     85
     86                        default:
     87                                $allowed_mimes = get_allowed_mime_types();
     88
     89                                /**
     90                                 * Search for allowed mimes matching the type
     91                                 *
     92                                 * eg: using 'application/vnd.oasis' as the $type
     93                                 * parameter will get all OpenOffice extensions supported
     94                                 * by WordPress and allowed for the current user.
     95                                 */
     96                                if ( '' !== $type ) {
     97                                        $allowed_mimes = preg_grep( '/' . addcslashes( $type, '/.+-' ) . '/', $allowed_mimes );
     98                                }
     99
     100                                $allowed_types = array_keys( $allowed_mimes );
     101
     102                                // Loop to explode keys using '|'
     103                                foreach ( $allowed_types as $allowed_type ) {
     104                                        $t = explode( '|', $allowed_type );
     105                                        $exts = array_merge( $exts, (array) $t );
     106                                }
     107                        break;
     108                }
     109        }
     110
     111        /**
     112         * Filter here to edit the allowed extensions by attachment type.
     113         *
     114         * @since  2.4.0
     115         *
     116         * @param  array  $exts List of allowed extensions
     117         * @param  string $type The requested file type
     118         */
     119        return apply_filters( 'bp_attachments_get_allowed_types', $exts, $type );
     120}
     121
     122/**
     123 * Get allowed attachment mime types.
     124 *
     125 * @since 2.4.0
     126 *
     127 * @param  string $type         The extension types to get (Optional).
     128 * @param  array $allowed_types List of allowed extensions
     129 * @return array                List of allowed mime types
     130 */
     131function bp_attachments_get_allowed_mimes( $type = '', $allowed_types = array() ) {
     132        if ( empty( $allowed_types ) ) {
     133                $allowed_types = bp_attachments_get_allowed_types( $type );
     134        }
     135
     136        $validate_mimes = wp_match_mime_types( join( ',', $allowed_types ), wp_get_mime_types() );
     137        $allowed_mimes  = array_map( 'implode', $validate_mimes );
     138
     139        /**
     140         * Include jpg type if jpeg is set
     141         */
     142        if ( isset( $allowed_mimes['jpeg'] ) && ! isset( $allowed_mimes['jpg'] ) ) {
     143                $allowed_mimes['jpg'] = $allowed_mimes['jpeg'];
     144        }
     145
     146        return $allowed_mimes;
     147}
     148
     149/**
     150 * Check the uploaded attachment type is allowed
     151 *
     152 * @since  2.4.0
     153 *
     154 * @param  string $file          Full path to the file.
     155 * @param  string $filename      The name of the file (may differ from $file due to $file being
     156 *                               in a tmp directory).
     157 * @param  array  $allowed_mimes The attachment allowed mimes (Required)
     158 * @return bool                  True if the attachment type is allowed. False otherwise
     159 */
     160function bp_attachments_check_filetype( $file, $filename, $allowed_mimes ) {
     161        $filetype = wp_check_filetype_and_ext( $file, $filename, $allowed_mimes );
     162
     163        if ( ! empty( $filetype['ext'] ) && ! empty( $filetype['type'] ) ) {
     164                return true;
     165        }
     166
     167        return false;
     168}
     169
     170/**
    28171 * Get the BuddyPress Plupload settings.
    29172 *
    30173 * @since  2.3.0
    function bp_attachments_enqueue_scripts( $class = '' ) { 
    257400                 * @param string $object the object the avatar belongs to (eg: user or group)
    258401                 */
    259402                $settings['nav'] = bp_sort_by_key( apply_filters( 'bp_attachments_avatar_nav', $avatar_nav, $object ), 'order', 'num' );
     403
     404        // Specific to BuddyPress cover images
     405        } elseif ( 'bp_cover_image_upload' === $defaults['multipart_params']['action'] ) {
     406
     407                // Cover images only need 1 file and 1 only!
     408                $defaults['multi_selection'] = false;
     409
     410                // Default cover component is xprofile
     411                $cover_component = 'xprofile';
     412
     413                // Get the object we're editing the cover image of
     414                $object = $defaults['multipart_params']['bp_params']['object'];
     415
     416                // Set the cover component according to the object
     417                if ( 'group' === $object ) {
     418                        $cover_component = 'groups';
     419                } elseif ( 'user' !== $object ) {
     420                        $cover_component = apply_filters( 'bp_attachments_cover_image_ui_component', $cover_component );
     421                }
     422                // Get cover image advised dimensions
     423                $cover_dimensions = bp_attachments_get_cover_image_dimensions( $cover_component );
     424
     425                // Set warning messages
     426                $strings['cover_image_warnings'] = apply_filters( 'bp_attachments_cover_image_ui_warnings', array(
     427                        'dimensions'  => sprintf(
     428                                        __( 'For better results, make sure to upload an image having a width >= %1$s px and a height >= %2$s px.', 'buddypress' ),
     429                                        (int) $cover_dimensions['width'],
     430                                        (int) $cover_dimensions['height']
     431                                ),
     432                ) );
    260433        }
    261434
    262435        // Set Plupload settings
    function bp_attachments_enqueue_scripts( $class = '' ) { 
    317490function bp_attachments_current_user_can( $capability, $args = array() ) {
    318491        $can = false;
    319492
    320         if ( 'edit_avatar' === $capability ) {
     493        if ( 'edit_avatar' === $capability || 'edit_cover_image' === $capability ) {
    321494                /**
    322495                 * Needed avatar arguments are set.
    323496                 */
    function bp_attachments_get_template_part( $slug ) { 
    410583                bp_get_template_part( $attachment_template_part );
    411584        }
    412585}
     586
     587/** Cover Image ***************************************************************/
     588
     589/**
     590 * Get the cover image settings
     591 *
     592 * @since  2.4.0
     593 *
     594 * @param  string $component the component to get the settings for ("xprofile" for user or "groups")
     595 * @return array            the cover image settings
     596 */
     597function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) {
     598        // Default parameters
     599        $args = array();
     600
     601        // First look in BP Theme Compat
     602        $cover_image = bp_get_theme_compat_feature( 'cover_image' );
     603
     604        if ( ! empty( $cover_image ) ) {
     605                $args = (array) $cover_image;
     606        }
     607
     608        /**
     609         * Then let people override/set the feature using this dynamic filter
     610         *
     611         * eg: for the user's profile cover image use :
     612         * add_filter( 'bp_before_xprofile_cover_image_settings_parse_args', 'your_filter', 10, 1 );
     613         *
     614         * @since  2.4.0
     615         *
     616         * @param array $settings the cover image settings
     617         */
     618        $settings = bp_parse_args( $args, array(
     619                'components'    => array(),
     620                'width'         => 1300,
     621                'height'        => 225,
     622                'callback'      => '',
     623                'theme_handle'  => '',
     624                'default_cover' => '',
     625        ), $component . '_cover_image_settings' );
     626
     627        if ( empty( $settings['components'] ) || empty( $settings['callback'] ) || empty( $settings['theme_handle'] ) ) {
     628                return false;
     629        }
     630
     631        // Current component is not supported
     632        if ( ! in_array( $component, $settings['components'] ) ) {
     633                return false;
     634        }
     635
     636        // Finally return the settings
     637        return $settings;
     638}
     639
     640/**
     641 * Get cover image Width and Height
     642 *
     643 * @since  2.4.0
     644 *
     645 * @param  string $component the BuddyPress component concerned ("xprofile" for user or "groups")
     646 * @return array             an associative array containing the advised width and height for the cover image
     647 */
     648function bp_attachments_get_cover_image_dimensions( $component = 'xprofile' ) {
     649        // Let's prevent notices when setting the warning strings
     650        $default = array( 'width' => 0, 'height' => 0 );
     651
     652        $settings = bp_attachments_get_cover_image_settings( $component );
     653
     654        if ( empty( $settings ) ) {
     655                return false;
     656        }
     657
     658        // Get width and height
     659        $wh = array_intersect_key( $settings, $default );
     660
     661        /**
     662         * Filter here to edit the cover image dimensions if needed.
     663         *
     664         * @since  2.4.0
     665         *
     666         * @param  array  $wh        an associative array containing the width and height values
     667         * @param  array  $settings  an associative array containing all the feature settings
     668         * @param  string $compnent  the requested component
     669         */
     670        return apply_filters( 'bp_attachments_get_cover_image_dimensions', $wh, $settings, $component );
     671}
     672
     673/**
     674 * Are we on a page to edit a cover image ?
     675 *
     676 * @since  2.4.0
     677 *
     678 * @return bool True if on a page to edit a cover image, false otherwise
     679 */
     680function bp_attachments_cover_image_is_edit() {
     681        $retval = false;
     682
     683        $current_component = bp_current_component();
     684        if ( 'profile' === $current_component ) {
     685                $current_component = 'xprofile';
     686        }
     687
     688        if ( ! bp_is_active( $current_component, 'cover_image' ) ) {
     689                return $retval;
     690        }
     691
     692        if ( bp_is_user_change_cover_image() ) {
     693                $retval = ! bp_disable_cover_image_uploads();
     694        }
     695
     696        if ( ( bp_is_group_admin_page() && 'group-cover-image' == bp_get_group_current_admin_tab() )
     697                || ( bp_is_group_create() && bp_is_group_creation_step( 'group-cover-image' ) ) ) {
     698                $retval = ! bp_disable_group_cover_image_uploads();
     699        }
     700
     701        return apply_filters( 'bp_attachments_cover_image_is_edit', $retval, $current_component );
     702}
     703
     704/**
     705 * Get the url or the path for a type of attachment
     706 *
     707 * @since  2.4.0
     708 *
     709 * @param  string $data whether to get the url or the path
     710 * @param  array  $args {
     711 *     @type string $object_dir  The object dir (eg: members/groups). Defaults to members.
     712 *     @type int    $item_id     The object id (eg: a user or a group id). Defaults to current user.
     713 *     @type string $type        The type of the attachment which is also the subdir where files are saved.
     714 *                               Defaults to 'cover-image'
     715 *     @type string $file        The name of the file.
     716 * }
     717 * @return string|bool the url or the path to the attachment, false otherwise
     718 */
     719function bp_attachments_get_attachment( $data = 'url', $args = array() ) {
     720        // Default value
     721        $attachment_data = false;
     722
     723        $r = bp_parse_args( $args, array(
     724                'object_dir' => 'members',
     725                'item_id'    => bp_loggedin_user_id(),
     726                'type'       => 'cover-image',
     727                'file'       => '',
     728        ), 'attachments_get_attachment_src' );
     729
     730        // Get BuddyPress Upload Dir
     731        $bp_upload_dir = bp_upload_dir();
     732
     733        $type_subdir = 'buddypress/' . $r['object_dir'] . '/' . $r['item_id'] . '/' . $r['type'];
     734        $type_dir    = trailingslashit( $bp_upload_dir['basedir'] ) . $type_subdir;
     735
     736        if ( ! is_dir( $type_dir ) ) {
     737                return $attachment_data;
     738        }
     739
     740        if ( ! empty( $r['file'] ) ) {
     741                if ( ! file_exists( trailingslashit( $type_dir ) . $r['file'] ) ) {
     742                        return $attachment_data;
     743                }
     744
     745                if ( 'url' === $data ) {
     746                        $attachment_data = trailingslashit( $bp_upload_dir['baseurl'] ) . $type_subdir . '/' . $r['file'];
     747                } else {
     748                        $attachment_data = trailingslashit( $type_dir ) . $r['file'];
     749                }
     750
     751        } else {
     752                $file = false;
     753
     754                // Open the directory and get the first file
     755                if ( $att_dir = opendir( $type_dir ) ) {
     756
     757                        while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) {
     758                                // Look for the first file having the type in its name
     759                                if ( false !== strpos( $attachment_file, $r['type'] ) && empty( $file ) ) {
     760                                        $file = $attachment_file;
     761                                        break;
     762                                }
     763                        }
     764                }
     765
     766                if ( empty( $file ) ) {
     767                        return $attachment_data;
     768                }
     769
     770                if ( 'url' === $data ) {
     771                        $attachment_data = trailingslashit( $bp_upload_dir['baseurl'] ) . $type_subdir . '/' . $file;
     772                } else {
     773                        $attachment_data = trailingslashit( $type_dir ) . $file;
     774                }
     775        }
     776
     777        return $attachment_data;
     778}
     779
     780/**
     781 * Does the user has a cover image ?
     782 *
     783 * @since  2.4.0
     784 *
     785 * @param  int $user_id
     786 * @return bool True if the user has a cover image, false otherwise
     787 */
     788function bp_attachments_get_user_has_cover_image( $user_id = 0 ) {
     789        if ( empty( $user_id ) ) {
     790                $user_id = bp_displayed_user_id();
     791        }
     792
     793        $cover_src = bp_attachments_get_attachment( 'url', array(
     794                'item_id'   => $user_id,
     795        ) );
     796
     797        return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $user_id );
     798}
     799
     800/**
     801 * Does the group has a cover image ?
     802 *
     803 * @since  2.4.0
     804 *
     805 * @param  int $group_id
     806 * @return bool True if the group has a cover image, false otherwise
     807 */
     808function bp_attachments_get_group_has_cover_image( $group_id = 0 ) {
     809        if ( empty( $group_id ) ) {
     810                $group_id = bp_get_current_group_id();
     811        }
     812
     813        $cover_src = bp_attachments_get_attachment( 'url', array(
     814                'object_dir' => 'groups',
     815                'item_id'    => $group_id,
     816        ) );
     817
     818        return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $group_id );
     819}
     820
     821/**
     822 * Delete an attachment for the given arguments
     823 *
     824 * @since  2.4.0
     825 *
     826 * @param  array $args
     827 * @see    bp_attachments_get_attachment() For more information on accepted arguments.
     828 * @return bool True if the attachment was deleted, false otherwise
     829 */
     830function bp_attachments_delete_file( $args = array() ) {
     831        $cover_path = bp_attachments_get_attachment( 'path', $args );
     832
     833        if ( empty( $cover_path ) ) {
     834                return false;
     835        }
     836
     837        @unlink( $cover_path );
     838        return true;
     839}
     840
     841/**
     842 * Ajax Upload and set a cover image
     843 *
     844 * @since  2.4.0
     845 *
     846 * @return  string|null A json object containing success data if the upload succeeded
     847 *                      error message otherwise.
     848 */
     849function bp_attachments_cover_image_ajax_upload() {
     850        // Bail if not a POST action
     851        if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
     852                wp_die();
     853        }
     854
     855        /**
     856         * Sending the json response will be different if
     857         * the current Plupload runtime is html4
     858         */
     859        $is_html4 = false;
     860        if ( ! empty( $_POST['html4' ] ) ) {
     861                $is_html4 = true;
     862        }
     863
     864        // Check the nonce
     865        check_admin_referer( 'bp-uploader' );
     866
     867        // Init the BuddyPress parameters
     868        $bp_params = array();
     869
     870        // We need it to carry on
     871        if ( ! empty( $_POST['bp_params' ] ) ) {
     872                $bp_params = bp_parse_args( $_POST['bp_params' ], array(
     873                        'object'  => 'user',
     874                        'item_id' => bp_loggedin_user_id(),
     875                ), 'attachments_cover_image_ajax_upload' );
     876        } else {
     877                bp_attachments_json_response( false, $is_html4 );
     878        }
     879
     880        // We need the object to set the uploads dir filter
     881        if ( empty( $bp_params['object'] ) ) {
     882                bp_attachments_json_response( false, $is_html4 );
     883        }
     884
     885        // Capability check
     886        if ( ! bp_attachments_current_user_can( 'edit_cover_image', $bp_params ) ) {
     887                bp_attachments_json_response( false, $is_html4 );
     888        }
     889
     890        $bp          = buddypress();
     891        $needs_reset = array();
     892
     893        // Default object data
     894        $object_data = array( 'dir' => 'members', 'component' => 'xprofile' );
     895        if ( 'group' === $bp_params['object'] ) {
     896                $object_data = array( 'dir' => 'groups', 'component' => 'groups' );
     897
     898                if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
     899                        $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
     900                        $bp->groups->current_group = groups_get_group( array(
     901                                'group_id'        => $bp_params['item_id'],
     902                                'populate_extras' => false,
     903                        ) );
     904                }
     905        } elseif ( 'user' !== $bp_params['object'] ) {
     906                $object_data = apply_filters( 'bp_attachments_cover_image_object_dir', $object_data, $bp_params['object'] );
     907
     908                if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) {
     909                        $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user );
     910                        $bp->displayed_user->id = $bp_params['item_id'];
     911                }
     912        }
     913
     914        $cover_image_attachment = new BP_Attachment_Cover_Image();
     915        $uploaded = $cover_image_attachment->upload( $_FILES );
     916
     917        // Reset objects
     918        if ( ! empty( $needs_reset ) ) {
     919                if ( ! empty( $needs_reset['component'] ) ) {
     920                        $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value'];
     921                } else {
     922                        $bp->{$needs_reset['key']} = $needs_reset['value'];
     923                }
     924        }
     925
     926        if ( ! empty( $uploaded['error'] ) ) {
     927                // Upload error response
     928                bp_attachments_json_response( false, $is_html4, array(
     929                        'type'    => 'upload_error',
     930                        'message' => sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $uploaded['error'] ),
     931                ) );
     932        }
     933
     934        // Get advised dimensions for the cover image
     935        $dimensions = bp_attachments_get_cover_image_dimensions( $object_data['component'] );
     936
     937        // Resize the image so that it fit with the cover image dimensions
     938        $cover_image  = $cover_image_attachment->fit( $uploaded['file'], $dimensions );
     939        $is_too_small = false;
     940
     941        // Image is too small in width and height
     942        if ( empty( $cover_image ) ) {
     943                $cover_file = $cover_image_attachment->generate_filename( $uploaded['file'] );
     944                @rename( $uploaded['file'], $cover_file );
     945
     946                // It's too small!
     947                $is_too_small = true;
     948        } elseif ( ! empty( $cover_image['path'] ) ) {
     949                $cover_file   = $cover_image['path'];
     950
     951                if ( $cover_image['width'] < $dimensions['width'] || $cover_image['height'] < $dimensions['height'] ) {
     952                        $is_too_small = true;
     953                }
     954        }
     955
     956        // Default error message
     957        $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
     958
     959        if ( empty( $cover_file ) ) {
     960                // Upload error response
     961                bp_attachments_json_response( false, $is_html4, array(
     962                        'type'    => 'upload_error',
     963                        'message' => __( 'There was a problem uploading the cover image.', 'buddypress' ),
     964                ) );
     965        }
     966
     967        // Set the basename for the cover file
     968        $cover_basename = wp_basename( $cover_file );
     969
     970        // Get BuddyPress Upload Dir
     971        $bp_upload_dir = bp_upload_dir();
     972
     973        $cover_subdir = 'buddypress/' . $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image';
     974        $cover_dir    = trailingslashit( $bp_upload_dir['basedir'] ) . $cover_subdir;
     975
     976        if ( ! is_dir( $cover_dir ) ) {
     977                // Upload error response
     978                bp_attachments_json_response( false, $is_html4, array(
     979                        'type'    => 'upload_error',
     980                        'message' => $error_message,
     981                ) );
     982        }
     983
     984        // Clean up the cover dir to only keep the uploaded cover image
     985        if ( $att_dir = opendir( $cover_dir ) ) {
     986                while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) {
     987                        // skip directories and the new cover image
     988                        if ( 2 < strlen( $attachment_file ) && 0 !== strpos( $attachment_file, '.' ) && $cover_basename !== $attachment_file ) {
     989                                @unlink( $cover_dir . '/' . $attachment_file );
     990                        }
     991                }
     992        }
     993
     994        // Build the url to the file
     995        $cover_url = trailingslashit( $bp_upload_dir['baseurl'] ) . $cover_subdir . '/' . $cover_basename;
     996
     997        // Init Feedback code, 1 is success
     998        $feedback_code = 1;
     999
     1000        // 0 is the size warning
     1001        if ( $is_too_small ) {
     1002                $feedback_code = 0;
     1003        }
     1004
     1005        // Set the name of the file
     1006        $name = $_FILES['file']['name'];
     1007        $name_parts = pathinfo( $name );
     1008        $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) );
     1009
     1010        // Finally return the cover image url to the UI
     1011        bp_attachments_json_response( true, $is_html4, array(
     1012                'name'          => $name,
     1013                'url'           => $cover_url,
     1014                'feedback_code' => $feedback_code,
     1015        ) );
     1016}
     1017add_action( 'wp_ajax_bp_cover_image_upload', 'bp_attachments_cover_image_ajax_upload' );
     1018
     1019/**
     1020 * Ajax delete a cover image for a given object and item id.
     1021 *
     1022 * @since 2.4.0
     1023 *
     1024 * @return string|null A json object containing success data if the cover image was deleted
     1025 *                     error message otherwise.
     1026 */
     1027function bp_attachments_cover_image_ajax_delete() {
     1028        // Bail if not a POST action.
     1029        if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
     1030                wp_send_json_error();
     1031        }
     1032
     1033        $cover_image_data = $_POST;
     1034
     1035        if ( empty( $cover_image_data['object'] ) || empty( $cover_image_data['item_id'] ) ) {
     1036                wp_send_json_error();
     1037        }
     1038
     1039        // Check the nonce
     1040        check_admin_referer( 'bp_delete_cover_image', 'nonce' );
     1041
     1042        // Capability check
     1043        if ( ! bp_attachments_current_user_can( 'edit_cover_image', $cover_image_data ) ) {
     1044                wp_send_json_error();
     1045        }
     1046
     1047        // Set object for the user's case
     1048        if ( 'user' === $cover_image_data['object'] ) {
     1049                $component = 'xprofile';
     1050                $dir       = 'members';
     1051
     1052        // Set it for any other cases
     1053        } else {
     1054                $component = $cover_image_data['object'] . 's';
     1055                $dir       = $component;
     1056        }
     1057
     1058        // Handle delete
     1059        if ( bp_attachments_delete_file( array( 'item_id' => $cover_image_data['item_id'], 'object_dir' => $dir, 'type' => 'cover-image' ) ) ) {
     1060
     1061                // Defaults no cover image
     1062                $response         = array(
     1063                        'reset_url'     => '',
     1064                        'feedback_code' => 3 ,
     1065                );
     1066
     1067                // Get cover image settings in case there's a default header
     1068                $cover_params = bp_attachments_get_cover_image_settings( $component );
     1069
     1070                // Check if there's a default cover
     1071                if ( ! empty( $cover_params['default_cover'] ) ) {
     1072                        $response['reset_url'] = $cover_params['default_cover'];
     1073                }
     1074
     1075                // Finally send the reset url
     1076                wp_send_json_success( $response );
     1077
     1078        } else {
     1079                wp_send_json_error( array(
     1080                        'feedback_code' => 2,
     1081                ) );
     1082        }
     1083}
     1084add_action( 'wp_ajax_bp_cover_image_delete', 'bp_attachments_cover_image_ajax_delete' );
  • src/bp-core/bp-core-avatars.php

    diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php
    index 98f2a3a..10c520e 100644
    function bp_core_set_avatar_constants() { 
    3232                define( 'BP_AVATAR_ORIGINAL_MAX_WIDTH', 450 );
    3333
    3434        if ( !defined( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE' ) ) {
    35 
    36                 $fileupload_maxk = bp_core_get_root_option( 'fileupload_maxk' );
    37                 if ( '' === $fileupload_maxk ) {
    38                         define( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE', 5120000 ); // 5mb
    39                 } else {
    40                         define( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE', $fileupload_maxk * 1024 );
    41                 }
     35                define( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE', bp_attachments_get_max_upload_file_size( 'avatar' ) );
    4236        }
    4337
    4438        if ( ! defined( 'BP_SHOW_AVATARS' ) ) {
    function bp_core_check_avatar_size( $file ) { 
    13591353 * @since 2.3.0
    13601354 */
    13611355function bp_core_get_allowed_avatar_types() {
    1362         $allowed_types = array( 'jpeg', 'gif', 'png' );
     1356        $allowed_types = bp_attachments_get_allowed_types( 'avatar' );
    13631357
    13641358        /**
    13651359         * Filters the list of allowed image types.
    function bp_core_get_allowed_avatar_types() { 
    13861380 */
    13871381function bp_core_get_allowed_avatar_mimes() {
    13881382        $allowed_types  = bp_core_get_allowed_avatar_types();
    1389         $validate_mimes = wp_match_mime_types( join( ',', $allowed_types ), wp_get_mime_types() );
    1390         $allowed_mimes  = array_map( 'implode', $validate_mimes );
    13911383
    1392         /**
    1393          * Include jpg type if needed so that bp_core_check_avatar_type()
    1394          * will check for jpeg and jpg extensions.
    1395          */
    1396         if ( isset( $allowed_mimes['jpeg'] ) ) {
    1397                 $allowed_mimes['jpg'] = $allowed_mimes['jpeg'];
    1398         }
    1399 
    1400         return $allowed_mimes;
     1384        return bp_attachments_get_allowed_mimes( 'avatar', $allowed_types );
    14011385}
    14021386
    14031387/**
    function bp_core_get_allowed_avatar_mimes() { 
    14101394 * @return bool True if the file extension is permitted, otherwise false.
    14111395 */
    14121396function bp_core_check_avatar_type( $file ) {
    1413         $avatar_filetype = wp_check_filetype_and_ext( $file['file']['tmp_name'], $file['file']['name'], bp_core_get_allowed_avatar_mimes() );
    1414 
    1415         if ( ! empty( $avatar_filetype['ext'] ) && ! empty( $avatar_filetype['type'] ) ) {
    1416                 return true;
    1417         }
    1418 
    1419         return false;
     1397        return bp_attachments_check_filetype( $file['file']['tmp_name'], $file['file']['name'], bp_core_get_allowed_avatar_mimes() );
    14201398}
    14211399
    14221400/**
  • src/bp-core/bp-core-catchuri.php

    diff --git src/bp-core/bp-core-catchuri.php src/bp-core/bp-core-catchuri.php
    index 4b7d7c8..6a571cb 100644
    function bp_core_load_template( $templates ) { 
    401401        }
    402402
    403403        /**
    404          * Filters the template locations.
    405          *
    406          * Allows plugins to alter where the template files are located.
    407          *
    408          * @since 1.1.0
    409          *
    410          * @param string $template           Located template path.
    411          * @param array  $filtered_templates Array of templates to attempt to load.
     404         * It's a modal, use the specific template that
     405         * includes a specific header and footer
    412406         */
    413         $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 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
    414423        if ( !empty( $located_template ) ) {
    415424                // Template was located, lets set this as a valid page and not a 404.
    416425                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 ff5075e..32180dd 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 4ad99cd..f90d4a4 100644
    function bp_enqueue_scripts() { 
    385385}
    386386
    387387/**
     388 * Fire the 'bp_modal_header' action, or the 'bp_admin_modal_header' in the modal was opened from
     389 * an Administration screen.
     390 *
     391 * @since 2.4.0
     392 */
     393function bp_modal_header( $is_admin = false ) {
     394        $action = 'bp_modal_header';
     395
     396        if ( true === (bool) $is_admin ) {
     397                $action = 'bp_admin_modal_header';
     398        }
     399
     400        /**
     401         * Fires inside the 'bp_modal_header' function.
     402         *
     403         * @since 2.4.0
     404         *
     405         * @param  bool $is_admin True for a wp-admin context, false otherwise
     406         */
     407        do_action( $action, $is_admin );
     408}
     409
     410/**
     411 * Fire the 'bp_modal_footer' action, or the 'bp_admin_modal_footer' in the modal was opened from
     412 * an Administration screen.
     413 *
     414 * @since 2.4.0
     415 */
     416function bp_modal_footer( $is_admin = false ) {
     417        $action = 'bp_modal_footer';
     418
     419        if ( true === (bool) $is_admin ) {
     420                $action = 'bp_admin_modal_footer';
     421        }
     422
     423        /**
     424         * Fires inside the 'bp_modal_footer' function.
     425         *
     426         * @since 2.4.0
     427         *
     428         * @param  bool $is_admin True for a wp-admin context, false otherwise
     429         */
     430        do_action( $action, $is_admin );
     431}
     432
     433/**
    388434 * Fire the 'bp_add_rewrite_tag' action, where BP adds its custom rewrite tags.
    389435 *
    390436 * @since 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 9841b72..ffbcdd7 100644
    function bp_update_is_item_mod( $is_item_mod = false, $component = '' ) { 
    19861986}
    19871987
    19881988/**
     1989 * Set a BuddyPress modal
     1990 *
     1991 * @since  2.4.0
     1992 *
     1993 * @param  bool $set whether the current screen is a modal (True) or not (False)
     1994 */
     1995function bp_set_is_modal( $set = false ) {
     1996        buddypress()->core->is_modal = $set;
     1997}
     1998
     1999/**
    19892000 * Trigger a 404.
    19902001 *
    19912002 * @since 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 e825316..bb6ca3f 100644
    function bp_get_default_options() { 
    2323
    2424                /** Components ********************************************************/
    2525
    26                 'bp-deactivated-components'       => array(),
     26                'bp-deactivated-components'            => array(),
    2727
    2828                /** bbPress ***********************************************************/
    2929
    3030                // Legacy bbPress config location
    31                 'bb-config-location'              => ABSPATH . 'bb-config.php',
     31                'bb-config-location'                   => ABSPATH . 'bb-config.php',
    3232
    3333                /** XProfile **********************************************************/
    3434
    3535                // Base profile groups name
    36                 'bp-xprofile-base-group-name'     => 'Base',
     36                'bp-xprofile-base-group-name'          => 'Base',
    3737
    3838                // Base fullname field name
    39                 'bp-xprofile-fullname-field-name' => 'Name',
     39                'bp-xprofile-fullname-field-name'      => 'Name',
    4040
    4141                /** Blogs *************************************************************/
    4242
    4343                // Used to decide if blogs need indexing
    44                 'bp-blogs-first-install'          => false,
     44                'bp-blogs-first-install'               => false,
    4545
    4646                /** Settings **********************************************************/
    4747
    4848                // Disable the WP to BP profile sync
    49                 'bp-disable-profile-sync'         => false,
     49                'bp-disable-profile-sync'              => false,
    5050
    5151                // Hide the Toolbar for logged out users
    52                 'hide-loggedout-adminbar'         => false,
     52                'hide-loggedout-adminbar'              => false,
    5353
    5454                // Avatar uploads
    55                 'bp-disable-avatar-uploads'       => false,
     55                'bp-disable-avatar-uploads'            => false,
     56
     57                // Cover image uploads
     58                'bp-disable-cover-image-uploads'       => false,
    5659
    5760                // Group Profile Photos
    58                 'bp-disable-group-avatar-uploads' => false,
     61                'bp-disable-group-avatar-uploads'      => false,
     62
     63                // Group Cover image uploads
     64                'bp-disable-group-cover-image-uploads' => false,
    5965
    6066                // Allow users to delete their own accounts
    61                 'bp-disable-account-deletion'     => false,
     67                'bp-disable-account-deletion'          => false,
    6268
    6369                // Allow comments on blog and forum activity items
    64                 'bp-disable-blogforum-comments'   => true,
     70                'bp-disable-blogforum-comments'        => true,
    6571
    6672                // The ID for the current theme package.
    67                 '_bp_theme_package_id'            => 'legacy',
     73                '_bp_theme_package_id'                 => 'legacy',
    6874
    6975                /** Groups ************************************************************/
    7076
    7177                // @todo Move this into the groups component
    7278
    7379                // Restrict group creation to super admins
    74                 'bp_restrict_group_creation'      => false,
     80                'bp_restrict_group_creation'           => false,
    7581
    7682                /** Akismet ***********************************************************/
    7783
    7884                // Users from all sites can post
    79                 '_bp_enable_akismet'              => true,
     85                '_bp_enable_akismet'                   => true,
    8086
    8187                /** Activity HeartBeat ************************************************/
    8288
    8389                // HeartBeat is on to refresh activities
    84                 '_bp_enable_heartbeat_refresh'    => true,
     90                '_bp_enable_heartbeat_refresh'         => true,
    8591
    8692                /** BuddyBar **********************************************************/
    8793
    8894                // Force the BuddyBar
    89                 '_bp_force_buddybar'              => false,
     95                '_bp_force_buddybar'                   => false,
    9096
    9197                /** Legacy theme *********************************************/
    9298
    9399                // Whether to register the bp-default themes directory
    94                 '_bp_retain_bp_default'           => false,
     100                '_bp_retain_bp_default'                => false,
    95101
    96102                /** Widgets **************************************************/
    97103                'widget_bp_core_login_widget'                => false,
    function bp_disable_avatar_uploads( $default = true ) { 
    596602}
    597603
    598604/**
     605 * Are members able to upload their own cover images?
     606 *
     607 * @since 2.4.0
     608 *
     609 * @uses bp_get_option() To get the cover image uploads option.
     610 *
     611 * @param bool $default Optional. Fallback value if not found in the database.
     612 *                      Default: false.
     613 *
     614 * @return bool True if cover image uploads are disabled, otherwise false.
     615 */
     616function bp_disable_cover_image_uploads( $default = false ) {
     617
     618        /**
     619         * Filters whether or not members are able to upload their own cover images.
     620         *
     621         * @since 2.4.0
     622         *
     623         * @param bool $value Whether or not members are able to upload their own cover images.
     624         */
     625        return (bool) apply_filters( 'bp_disable_cover_image_uploads', (bool) bp_get_option( 'bp-disable-cover-image-uploads', $default ) );
     626}
     627
     628/**
    599629 * Are group avatars disabled?
    600630 *
    601631 * 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 ) { 
    631661}
    632662
    633663/**
     664 * Are group cover images disabled?
     665 *
     666 * @since 2.4.0
     667 *
     668 * @uses bp_get_option() To get the group cover image uploads option.
     669 *
     670 * @param bool $default Optional. Fallback value if not found in the database.
     671 *                      Default: false.
     672 *
     673 * @return bool True if group cover image uploads are disabled, otherwise false.
     674 */
     675function bp_disable_group_cover_image_uploads( $default = false ) {
     676
     677        /**
     678         * Filters whether or not members are able to upload group cover images.
     679         *
     680         * @since 2.4.0
     681         *
     682         * @param bool $value Whether or not members are able to upload thier groups cover images.
     683         */
     684        return (bool) apply_filters( 'bp_disable_group_cover_image_uploads', (bool) bp_get_option( 'bp-disable-group-cover-image-uploads', $default ) );
     685}
     686
     687/**
    634688 * Are members able to delete their own accounts?
    635689 *
    636690 * @since 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 7b08e3f..5780a85 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 modal default title', '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 08a4791..bcc53e0 100644
    function bp_set_theme_compat_original_template( $template = '' ) { 
    436436}
    437437
    438438/**
     439 * Set a theme compat feature
     440 *
     441 * @since 2.4.0
     442 *
     443 * @param  string $theme_id the theme id (eg: legacy)
     444 * @param  array  $feature  an associative array (eg: array( name => 'feature_name', 'settings' => array() ))
     445 */
     446function bp_set_theme_compat_feature( $theme_id, $feature = array() ) {
     447        if ( empty( $theme_id ) || empty( $feature['name'] ) ) {
     448                return;
     449        }
     450
     451        // Get BuddyPress instance
     452        $bp = buddypress();
     453
     454        // Get current theme compat theme
     455        $theme_compat_theme = $bp->theme_compat->theme;
     456
     457        // Bail if theme is not in use
     458        if ( $theme_id !== $theme_compat_theme->id ) {
     459                return;
     460        }
     461
     462        $features = $theme_compat_theme->__get( 'features' );
     463        if ( empty( $features ) ) {
     464                $features = array();
     465        }
     466
     467        // Bail if the feature is already registered or no settings were provided
     468        if ( isset( $features[ $feature['name'] ] ) || empty( $feature['settings'] ) ) {
     469                return;
     470        }
     471
     472        // Add the feature
     473        $features[ $feature['name'] ] = (object) $feature['settings'];
     474
     475        // The feature is attached to components
     476        if ( isset( $features[ $feature['name'] ]->components ) ) {
     477                // Set the feature for each concerned component
     478                foreach ( (array) $features[ $feature['name'] ]->components as $component ) {
     479                        // The xProfile component is specific
     480                        if ( 'xprofile' === $component ) {
     481                                $component = 'profile';
     482                        }
     483
     484                        if ( isset( $bp->{$component} ) ) {
     485                                if ( isset( $bp->{$component}->features ) ) {
     486                                        $bp->{$component}->features[] = $feature['name'];
     487                                } else {
     488                                        $bp->{$component}->features = array( $feature['name'] );
     489                                }
     490                        }
     491                }
     492        }
     493
     494        // Finally update the theme compat features
     495        $theme_compat_theme->__set( 'features', $features );
     496}
     497
     498/**
     499 * Get a theme compat feature
     500 *
     501 * @since 2.4.0
     502 *
     503 * @param  string $feature the feature (eg: cover_image)
     504 * @return object          the feature settings.
     505 */
     506function bp_get_theme_compat_feature( $feature = '' ) {
     507        // Get current theme compat theme
     508        $theme_compat_theme = buddypress()->theme_compat->theme;
     509
     510        // Get features
     511        $features = $theme_compat_theme->__get( 'features' );
     512
     513        if ( ! isset( $features[ $feature ] ) ) {
     514                return false;
     515        }
     516
     517        return $features[ $feature ];
     518}
     519
     520/**
     521 * Setup the theme's features
     522 *
     523 * Note: BP Legacy's buddypress-functions.php is not loaded in WP Administration
     524 * as it's done using bp_locate_template()
     525 *
     526 * @since 2.4.0
     527 *
     528 * @global $content_width the content width of the theme
     529 */
     530function bp_register_theme_compat_default_features() {
     531        global $content_width;
     532
     533        // If the current theme doesn't need theme compat, bail at this point.
     534        if ( ! bp_use_theme_compat_with_current_theme() ) {
     535                return $template;
     536        }
     537
     538        // Get the theme
     539        $current_theme = wp_get_theme();
     540        $theme_handle  = $current_theme->get_stylesheet();
     541        $parent        = $current_theme->parent();
     542
     543        if ( $parent ) {
     544                $theme_handle = $parent->get_stylesheet();
     545        }
     546
     547        /**
     548         * Since Companion stylesheets, the $content_width is smaller
     549         * than the width used by BuddyPress, so we need to manually set the
     550         * content width for the concerned themes.
     551         *
     552         * array( stylesheet => content width used by BuddyPress )
     553         */
     554        $bp_content_widths = array(
     555                'twentyfifteen'  => 1300,
     556                'twentyfourteen' => 955,
     557                'twentythirteen' => 890,
     558        );
     559
     560        // Default values
     561        $bp_content_width = (int) $content_width;
     562        $bp_handle        = 'bp-legacy-css';
     563
     564        // Specific to themes having companion stylesheets
     565        if ( isset( $bp_content_widths[ $theme_handle ] ) ) {
     566                $bp_content_width = $bp_content_widths[ $theme_handle ];
     567                $bp_handle        = 'bp-' . $theme_handle;
     568        }
     569
     570        if ( is_rtl() ) {
     571                $bp_handle .= '-rtl';
     572        }
     573
     574        $top_offset    = 150;
     575        $avatar_height = apply_filters( 'bp_core_avatar_full_height', $top_offset );
     576
     577        if ( $avatar_height > $top_offset ) {
     578                $top_offset = $avatar_height;
     579        }
     580
     581        bp_set_theme_compat_feature( 'legacy', array(
     582                'name'     => 'cover_image',
     583                'settings' => array(
     584                        'components'   => array( 'xprofile', 'groups' ),
     585                        'width'        => $bp_content_width,
     586                        'height'       => $top_offset + round( $avatar_height / 2 ),
     587                        'callback'     => 'bp_legacy_theme_cover_image',
     588                        'theme_handle' => $bp_handle,
     589                ),
     590        ) );
     591}
     592
     593/**
    439594 * Check whether a given template is the one that WP originally selected to display current page.
    440595 *
    441596 * @since 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..1413f62 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                // Allowed cover image types & upload size
     27                $allowed_types        = bp_attachments_get_allowed_types( 'cover_image' );
     28                $max_upload_file_size = bp_attachments_get_max_upload_file_size( 'cover_image' );
     29
     30                parent::__construct( array(
     31                        'action'                => 'bp_cover_image_upload',
     32                        'file_input'            => 'file',
     33                        'original_max_filesize' => $max_upload_file_size,
     34                        'base_dir'              => 'buddypress',
     35                        'required_wp_files'     => array( 'file', 'image' ),
     36
     37                        // Specific errors for cover images
     38                        'upload_error_strings'  => array(
     39                                11  => sprintf( __( 'That image is too big. Please upload one smaller than %s', 'buddypress' ), size_format( $max_upload_file_size ) ),
     40                                12  => sprintf( _n( 'Please upload only this file type: %s.', 'Please upload only these file types: %s.', count( $allowed_types ), 'buddypress' ), self::get_cover_image_types( $allowed_types ) ),
     41                        ),
     42                ) );
     43        }
     44
     45        /**
     46         * Gets the available cover image types.
     47         *
     48         * @since 2.4.0
     49         *
     50         * @param array $allowed_types Array of allowed cover image types.
     51         *
     52         * @return string comma separated list of allowed cover image types.
     53         */
     54        public static function get_cover_image_types( $allowed_types = array() ) {
     55                $types = array_map( 'strtoupper', $allowed_types );
     56                $comma = _x( ',', 'avatar types separator', 'buddypress' );
     57                return join( $comma . ' ', $types );
     58        }
     59
     60        /**
     61         * Cover image specific rules.
     62         *
     63         * Adds an error if the cover image size or type don't match BuddyPress needs.
     64         * The error code is the index of $upload_error_strings.
     65         *
     66         * @since 2.4.0
     67         *
     68         * @param  array $file the temporary file attributes (before it has been moved).
     69         *
     70         * @return array the file with extra errors if needed.
     71         */
     72        public function validate_upload( $file = array() ) {
     73                // Bail if already an error
     74                if ( ! empty( $file['error'] ) ) {
     75                        return $file;
     76                }
     77
     78                // File size is too big
     79                if ( $file['size'] > $this->original_max_filesize ) {
     80                        $file['error'] = 11;
     81
     82                // File is of invalid type
     83                } elseif ( ! bp_attachments_check_filetype( $file['tmp_name'], $file['name'], bp_attachments_get_allowed_mimes( 'cover_image' ) ) ) {
     84                        $file['error'] = 12;
     85                }
     86
     87                // Return with error code attached
     88                return $file;
     89        }
     90
     91        /**
     92         * Set the directory when uploading a file
     93         *
     94         * @since 2.4.0
     95         *
     96         * @return array upload data (path, url, basedir...)
     97         */
     98        public function upload_dir_filter() {
     99                // Default values are for profiles
     100                $object_id = bp_displayed_user_id();
     101
     102                if ( empty( $object_id ) ) {
     103                        $object_id = bp_loggedin_user_id();
     104                }
     105
     106                $object_directory = 'members';
     107
     108                // We're in a group, edit default values
     109                if ( bp_is_group() || bp_is_group_create() ) {
     110                        $object_id        = bp_get_current_group_id();
     111                        $object_directory = 'groups';
     112                }
     113
     114                // Set the subdir
     115                $subdir  = '/' . $object_directory . '/' . $object_id . '/cover-image';
     116
     117                return apply_filters( 'bp_attachments_cover_image_upload_datas', array(
     118                        'path'    => $this->upload_path . $subdir,
     119                        'url'     => $this->url . $subdir,
     120                        'subdir'  => $subdir,
     121                        'basedir' => $this->upload_path,
     122                        'baseurl' => $this->url,
     123                        'error'   => false
     124                ) );
     125        }
     126
     127        /**
     128         * Adjust the cover image to fit with advised width & height.
     129         *
     130         * @since 2.4.0
     131         *
     132         * @param string $file the absolute path to the file.
     133         * @return mixed
     134         */
     135        public function fit( $file = '', $dimensions = array() ) {
     136                if ( empty( $dimensions['width'] ) || empty( $dimensions['height'] ) ) {
     137                        return false;
     138                }
     139
     140                // Get image size
     141                $size   = @getimagesize( $file );
     142                $retval = false;
     143
     144                // Check image size and shrink if too large
     145                if ( $size[0] > $dimensions['width'] || $size[1] > $dimensions['height'] ) {
     146                        $editor = wp_get_image_editor( $file );
     147
     148                        if ( ! is_wp_error( $editor ) ) {
     149                                $editor->set_quality( 100 );
     150
     151                                $resized = $editor->resize( $dimensions['width'], $dimensions['height'], true );
     152                                if ( ! is_wp_error( $resized ) ) {
     153                                        $cover   = $editor->save( $this->generate_filename( $file ) );
     154                                } else {
     155                                        $retval = $resized;
     156                                }
     157
     158                                // Check for cover creation errors
     159                                if ( ( false === $retval ) && is_wp_error( $cover ) ) {
     160                                        $retval = $cover;
     161                                }
     162
     163                                // Cover is good so proceed
     164                                if ( false === $retval ) {
     165                                        $retval = $cover;
     166                                }
     167
     168                        } else {
     169                                $retval = $editor;
     170                        }
     171                }
     172
     173                return $retval;
     174        }
     175
     176        /**
     177         * Generate a filename for the cover image
     178         *
     179         * @since 2.4.0
     180         *
     181         * @param  string $file the absolute path to the file.
     182         * @return string       the absolute path to the new file name
     183         */
     184        public function generate_filename( $file = '' ) {
     185                if ( empty( $file ) || ! file_exists( $file ) ) {
     186                        return false;
     187                }
     188
     189                $info    = pathinfo( $file );
     190                $dir     = $info['dirname'];
     191                $ext     = strtolower( $info['extension'] );
     192                $name    = wp_hash( $file . time() ) . '-bp-cover-image';
     193
     194                return trailingslashit( $dir ) . "{$name}.{$ext}";
     195        }
     196
     197        /**
     198         * Build script datas for the Uploader UI
     199         *
     200         * @since 2.4.0
     201         *
     202         * @return array the javascript localization data
     203         */
     204        public function script_data() {
     205                // Get default script data
     206                $script_data = parent::script_data();
     207
     208                if ( bp_is_user() ) {
     209                        $item_id = bp_displayed_user_id();
     210
     211                        $script_data['bp_params'] = array(
     212                                'object'          => 'user',
     213                                'item_id'         => $item_id,
     214                                'has_cover_image' => bp_attachments_get_user_has_cover_image( $item_id ),
     215                                'nonces'  => array(
     216                                        'remove' => wp_create_nonce( 'bp_delete_cover_image' ),
     217                                ),
     218                        );
     219
     220                        // Set feedback messages
     221                        $script_data['feedback_messages'] = array(
     222                                1 => __( 'Your new cover image was uploaded successfully.', 'buddypress' ),
     223                                2 => __( 'There was a problem deleting your cover image. Please try again.', 'buddypress' ),
     224                                3 => __( 'Your cover image was deleted successfully!', 'buddypress' ),
     225                        );
     226                } elseif ( bp_is_group() ) {
     227                        $item_id = bp_get_current_group_id();
     228
     229                        $script_data['bp_params'] = array(
     230                                'object'          => 'group',
     231                                'item_id'         => bp_get_current_group_id(),
     232                                'has_cover_image' => bp_attachments_get_group_has_cover_image( $item_id ),
     233                                'nonces'  => array(
     234                                        'remove' => wp_create_nonce( 'bp_delete_cover_image' ),
     235                                ),
     236                        );
     237
     238                        // Set feedback messages
     239                        $script_data['feedback_messages'] = array(
     240                                1 => __( 'The group cover image was uploaded successfully.', 'buddypress' ),
     241                                2 => __( 'There was a problem deleting the group cover image. Please try again.', 'buddypress' ),
     242                                3 => __( 'The group cover image was deleted successfully!', 'buddypress' ),
     243                        );
     244                } else {
     245                        /**
     246                         * Use this filter to include specific BuddyPress params for your object.
     247                         * e.g. Cover image for blogs single item.
     248                         *
     249                         * @since 2.4.0
     250                         *
     251                         * @param array $value The cover image specific BuddyPress parameters.
     252                         */
     253                        $script_data['bp_params'] = apply_filters( 'bp_attachment_cover_image_params', array() );
     254                }
     255
     256                // Include our specific js & css
     257                $script_data['extra_js']  = array( 'bp-cover-image' );
     258                $script_data['extra_css'] = array( 'bp-avatar' );
     259
     260                return apply_filters( 'bp_attachments_cover_image_script_data', $script_data );
     261        }
     262}
  • src/bp-core/css/avatar-rtl.css

    diff --git src/bp-core/css/avatar-rtl.css src/bp-core/css/avatar-rtl.css
    index 18f4156..78a8cb0 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: left;
    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/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..b9538fa 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;
     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..3866cb3 100644
     
     1/* global bp, TB_WIDTH, TB_HEIGHT */
     2
     3window.bp = window.bp || {};
     4
     5( function( $ ) {
     6        var originalWidth, originalHeight, originalIframeHeight;
     7
     8        // Asjust Thickbox
     9        window.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                        window.TB_WIDTH = availableWidth - 50;
     30                        needReposition = true;
     31                } else if ( availableWidth > originalWidth ) {
     32                        window.TB_WIDTH = originalWidth;
     33                        needReposition = true;
     34                }
     35
     36                if ( availableHeight < TB_HEIGHT ) {
     37                        window.TB_HEIGHT = availableHeight - 50;
     38                        needReposition = true;
     39                } else if ( availableHeight > originalHeight ) {
     40                        window.TB_HEIGHT = originalHeight;
     41                        needReposition = true;
     42                }
     43
     44                // Ask Thickbox to "reposition"
     45                if ( true === needReposition ) {
     46                        window.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], 10 ) > 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], 10 ) > 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                window.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                window.bp_tb_position();
     123
     124                if ( typeof originalIframeHeight === 'undefined' ) {
     125                        originalIframeHeight = $( '#TB_iframeContent' ).prop( 'style' ).height;
     126                }
     127
     128                if ( ! bpFullHeighBtn.hasClass( 'max' ) ) {
     129                        window.TB_HEIGHT = $( window ).height() - 50;
     130                        bpFullHeighBtn.addClass( 'max' );
     131                } else {
     132                        window.TB_HEIGHT = originalIframeHeight;
     133                        bpFullHeighBtn.removeClass( 'max' );
     134                }
     135
     136                // Reposition
     137                window.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() { window.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                $( inputId ).val( val );
     205        };
     206
     207} )( jQuery );
  • src/bp-groups/admin/css/admin-rtl.css

    diff --git src/bp-groups/admin/css/admin-rtl.css src/bp-groups/admin/css/admin-rtl.css
    index 40bac3b..9783cb9 100644
    table.bp-group-members .urole-column { 
    8484        padding-right: 20px;
    8585        padding-left: 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-left: 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 0 0 2px;
     122        top: 0;
     123        right: -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/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..af0bae7 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                        'alt'     => sprintf( __( 'Group logo of %s', 'buddypress' ), $item->name ),
     827                ) );
     828
     829                bp_modal_link( array(
     830                        'item_id'       => $item,
     831                        'object'        => 'group',
     832                        'width'         => 800,
     833                        'height'        => 400,
     834                        'modal_title'   => __( 'Edit Group Photo', 'buddypress' ),
     835                        'modal_action'  => 'group-avatar',
     836                        'link_text'     => __( 'Edit Group Photo', 'buddypress' ),
     837                        'link_class'    => array( 'bp-groups-avatar-admin-edit' ),
     838                ) );
     839                ?>
     840
     841        </div>
     842        <?php
     843}
     844
     845/**
     846 * Output the markup for a single group's Edit cover image metabox.
     847 *
     848 * @since 2.4.0
     849 */
     850 function bp_groups_admin_edit_metabox_cover_image( $item ) {
     851        $dimensions = bp_attachments_get_cover_image_dimensions( 'groups' );
     852
     853        $cover_src = bp_attachments_get_attachment( 'url', array(
     854                'object_dir' => 'groups',
     855                'item_id'    => $item->id,
     856        ) );
     857
     858        printf( '
     859                <style type="text/css">
     860                        #header-cover-image {
     861                                display: block;
     862                                height: %1$spx;
     863                                background: #c5c5c5 url( %2$s );
     864                                background-position: center top;
     865                                background-size: cover;
     866                        }
     867                </style>
     868        ', $dimensions['height'], $cover_src );
     869        ?>
     870        <div id="bp_group_cover_image">
     871
     872                <div id="header-cover-image"></div>
     873
     874                <a id="bp-groups-cover-image-admin-preview" href="<?php echo esc_url( $cover_src ) ;?>" title="<?php esc_attr_e( 'Group Cover Image', 'buddypress' ) ;?>" class="bp-cover-image-preview <?php echo ! empty( $cover_src ) ? 'thickbox' : 'hide' ;?>">
     875                        <?php esc_html_e( 'View Cover Image', 'buddypress' ) ;?>
     876                </a>
     877
     878                <?php bp_modal_link( array(
     879                        'item_id'       => $item,
     880                        'object'        => 'group',
     881                        'width'         => 800,
     882                        'height'        => 400,
     883                        'modal_title'   => __( 'Edit Cover Image', 'buddypress' ),
     884                        'modal_action'  => 'group-cover-image',
     885                        'link_text'     => __( 'Edit Cover Image', 'buddypress' ),
     886                        'link_class'    => array( 'bp-groups-cover-image-admin-edit' ),
     887                ) ); ?>
     888
     889        </div>
     890        <?php
     891}
     892
     893/**
    801894 * Output the markup for a single group's Add New Members metabox.
    802895 *
    803896 * @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-rtl.css

    diff --git src/bp-members/admin/css/admin-rtl.css src/bp-members/admin/css/admin-rtl.css
    index a1de09c..b7fc0bd 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-left: 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/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..4fde637 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: left;
     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                        max-width: 50%;
     1825                }
     1826
     1827                body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions {
     1828                        padding-top: 20px;
     1829                        max-width: 20%;
     1830                }
     1831
     1832                ' . $hide_avatar_style . '
     1833
     1834                #buddypress div#item-header-cover-image h2 a,
     1835                #buddypress div#item-header-cover-image h2 {
     1836                        color: #FFF;
     1837                        text-rendering: optimizelegibility;
     1838                        text-shadow: 0px 0px 3px rgba( 0, 0, 0, 0.8 );
     1839                        margin: 0;
     1840                        font-size:200%;
     1841                }
     1842
     1843                #buddypress #item-header-cover-image #item-header-avatar img.avatar {
     1844                        border: solid 2px #FFF;
     1845                        background: rgba( 255, 255, 255, 0.8 );
     1846                }
     1847
     1848                #buddypress #item-header-cover-image #item-header-avatar a {
     1849                        border: none;
     1850                        text-decoration: none;
     1851                }
     1852
     1853                #buddypress #item-header-cover-image #item-buttons {
     1854                        overflow:hidden;
     1855                        margin: 20px 0 10px;
     1856                        padding: 0 0 5px;
     1857                }
     1858
     1859                #buddypress #item-header-cover-image #item-buttons:before {
     1860                        content:"\00a0";
     1861                }
     1862
     1863                @media screen and (max-width: 782px) {
     1864                        #buddypress #item-header-cover-image #item-header-avatar,
     1865                        .bp-user #buddypress #item-header #item-header-cover-image #item-header-avatar,
     1866                        #buddypress div#item-header #item-header-cover-image #item-header-content {
     1867                                width:100%;
     1868                                text-align:center;
     1869                        }
     1870
     1871                        #buddypress #item-header-cover-image #item-header-avatar a {
     1872                                display:inline-block;
     1873                        }
     1874
     1875                        #buddypress #item-header-cover-image #item-header-avatar img {
     1876                                margin:0;
     1877                        }
     1878
     1879                        #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-header-content,
     1881                        body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions {
     1882                                margin:0;
     1883                        }
     1884
     1885                        body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-header-content,
     1886                        body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions {
     1887                                max-width: 100%;
     1888                        }
     1889
     1890                        #buddypress div#item-header-cover-image h2 a,
     1891                        #buddypress div#item-header-cover-image h2 {
     1892                                color: inherit;
     1893                                text-shadow: none;
     1894                                margin:25px 0 0;
     1895                                font-size:200%;
     1896                        }
     1897
     1898                        #buddypress #item-header-cover-image #item-buttons div {
     1899                                float:none;
     1900                                display:inline-block;
     1901                        }
     1902
     1903                        #buddypress #item-header-cover-image #item-buttons:before {
     1904                                content:"";
     1905                        }
     1906
     1907                        #buddypress #item-header-cover-image #item-buttons {
     1908                                margin: 5px 0;
     1909                        }
     1910                }
     1911        ';
     1912}
  • 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 466e2c9..fade186 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 76a8936..74dc700 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-rtl.css

    diff --git src/bp-templates/bp-legacy/css/buddypress-rtl.css src/bp-templates/bp-legacy/css/buddypress-rtl.css
    index b10a629..144871e 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: right;
    a.bp-title-button { 
    12521257        float: right;
    12531258        margin: 10px 0 0 10px;
    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        right: 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/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-rtl.css

    diff --git src/bp-templates/bp-legacy/css/twentyfifteen-rtl.css src/bp-templates/bp-legacy/css/twentyfifteen-rtl.css
    index 422898c..2fd88ee 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    955955        width: 100%;
    956956}
    957957
    958 .bp-user #buddypress #item-header #item-header-avatar img.avatar,
    959958.bp-user #buddypress #item-header #item-header-avatar a {
    960959        border-bottom: 0;
    961960        display: inline-block;
  • 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..2b14228 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    955955        width: 100%;
    956956}
    957957
    958 .bp-user #buddypress #item-header #item-header-avatar img.avatar,
    959958.bp-user #buddypress #item-header #item-header-avatar a {
    960959        border-bottom: 0;
    961960        display: inline-block;
  • 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-rtl.css

    diff --git src/bp-templates/bp-legacy/css/twentyfourteen-rtl.css src/bp-templates/bp-legacy/css/twentyfourteen-rtl.css
    index 8f987c0..00803df 100644
    body.activity-permalink #buddypress { 
    782782                text-align: right;
    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: left;
    790787                width: 78%;
  • 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-rtl.css

    diff --git src/bp-templates/bp-legacy/css/twentythirteen-rtl.css src/bp-templates/bp-legacy/css/twentythirteen-rtl.css
    index b90fe14..dd32216 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    953953                float: right;
    954954                width: 20%;
    955955        }
    956         .bp-user #buddypress #item-header #item-header-avatar img.avatar,
    957956        .bp-user #buddypress #item-header #item-header-avatar a {
    958957                float: right;
    959                 width: 100%;
    960958        }
    961959        .bp-user #buddypress #item-header #item-header-content {
    962960                float: left;
  • 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..cec2289 100644
    http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 
    953953                float: left;
    954954                width: 20%;
    955955        }
    956         .bp-user #buddypress #item-header #item-header-avatar img.avatar,
    957956        .bp-user #buddypress #item-header #item-header-avatar a {
    958957                float: left;
    959                 width: 100%;
    960958        }
    961959        .bp-user #buddypress #item-header #item-header-content {
    962960                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..df90ad7 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', 'buddypress' ) ;?>" class="bp-cover-image-preview <?php echo ! empty( $cover_src ) ? 'thickbox' : 'hide' ;?>">
     1115                                        <?php esc_html_e( 'View Cover Image', 'buddypress' ) ;?>
     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}
  • tests/phpunit/testcases/core/functions.php

    diff --git tests/phpunit/testcases/core/functions.php tests/phpunit/testcases/core/functions.php
    index fd36eaf..3a4e413 100644
    class BP_Tests_Core_Functions extends BP_UnitTestCase { 
    684684                // Reset buddypress() vars
    685685                $bp->active_components = $reset_active_components;
    686686        }
     687
     688        /**
     689         * @group bp_attachments
     690         * @ticket BP6570
     691         */
     692        public function test_bp_attachments_get_allowed_types() {
     693                $supported = array( 'jpeg', 'gif', 'png' );
     694
     695                $avatar = bp_attachments_get_allowed_types( 'avatar' );
     696                $this->assertSame( $supported, $avatar );
     697
     698                $cover_image = bp_attachments_get_allowed_types( 'cover_image' );
     699                $this->assertSame( $supported, $cover_image );
     700
     701                $images = bp_attachments_get_allowed_types( 'image/' );
     702
     703                foreach ( $images as $image ) {
     704                        if ( 'image' !== wp_ext2type( $image ) ) {
     705                                $not_image = $image;
     706                        }
     707                }
     708
     709                $this->assertTrue( empty( $not_image ) );
     710        }
    687711}