Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm working with the BuddyPress extended profile component and would like to add image fields to the WordPress user profile. Is there code that I can add to my theme's functions.php so it inserts the "Image" option into the plugin?

I have searched the BuddyPress and WordPress Codex forums and haven't come across code for intercepting the plugin's operation without editing core files.

share|improve this question

closed as off-topic by Pieter Goosen, ialocin, kaiser Aug 7 at 11:12

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

    
@kaiser I'm puzzled by this move to classify the question as "off-topic". First of all, I asked it 3 years ago and it attracted no opposition till now. Secondly, it's about BuddyPress which is squarely in the WordPress territory. Where else would you use BuddyPress apart from within an install of WordPress? Does this also mean that any question relating to a WordPress plugin is deemed unfit for WordPress SE? –  KalenGi Aug 7 at 17:44
    
All plugin specific questions are off topic since quite some time. We just happened to catch up a bit with the help of the Summer CleanUp. That helpsnthe regarding support forums and we anyway dont have any BuddyPress experts on the site. And we cant support 30k+ plugins. For additional questions about the policy please go ask on meta. –  kaiser Aug 7 at 17:52
    
@kaiser based on the discussion about this question on meta I have updated the question and the answer. Is the new version acceptable? –  KalenGi Aug 8 at 12:45
    
We highly appreciate what you have done. Still it's completely specific to this plugin and the current version of it: I can't understand what's going on without searching up this plugin in this specific version, reading its source and then trying to follow up with your answer. This answer would have much more value if you put it in a blog post or in the BuddyPress support forums or in some of their official blogs (if they have any). I upvoted your questions and answer so doesn't get hit by auto clean up, but reopening isn't possible. Please consider what I wrote above (blog). –  kaiser Aug 8 at 12:52
    
I also want to suggest that if you want to participate on this question and work on such high quality answers like yours below, that you jump either into the new questions queue or take a look at the "unanswered" queue. This normally is where really interesting questions hide :) –  kaiser Aug 8 at 12:54

1 Answer 1

up vote 2 down vote accepted

I figured out a way to go about adding the image type field without editing core BuddyPress files. The solution involves adding code to the theme's functions.php that intercepts the plugin's loading, display and saving. It also updates the WordPress upload location in order to direct the profile images to a subdirectory of the the uploads directory. The full solution is here.

Step 1. Add a new field type:

function bpd_add_new_xprofile_field_type($field_types){
    $image_field_type = array('image');
    $field_types = array_merge($field_types, $image_field_type);
    return $field_types;
}

add_filter( 'xprofile_field_types', 'bpd_add_new_xprofile_field_type' );

Step 2. Handle the rendering of the new field type in the WordPress Admin panel

function bpd_admin_render_new_xprofile_field_type($field, $echo = true){

    ob_start();
        switch ( $field->type ) {
            case 'image':
                ?>
                    <input type="file" name="<?php bp_the_profile_field_input_name() ?>" id="<?php bp_the_profile_field_input_name() ?>" value="" />
                <?php
                break;
            default :
                ?>
                    <p>Field type unrecognized</p>
                <?php
        }

        $output = ob_get_contents();
    ob_end_clean();

    if($echo){
        echo $output;
        return;
    }
    else{
        return $output;
    }

}

add_filter( 'xprofile_admin_field', 'bpd_admin_render_new_xprofile_field_type' );

Step 3. Handle the rendering of the new field type on the WordPress front-end

function bpd_edit_render_new_xprofile_field($echo = true){

    if(empty ($echo)){
        $echo = true;
    }

    ob_start();
        if ( bp_get_the_profile_field_type() == 'image' ){
            $imageFieldInputName = bp_get_the_profile_field_input_name();
            $image = WP_CONTENT_URL . bp_get_the_profile_field_edit_value();

        ?>
                <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
                <input type="file" name="<?php echo $imageFieldInputName; ?>" id="<?php echo $imageFieldInputName; ?>" value="" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>/>
                <img src="<?php echo $image; ?>" alt="<?php bp_the_profile_field_name(); ?>" />

        <?php

        } 

        $output = ob_get_contents();
    ob_end_clean();

    if($echo){
        echo $output;
        return;
    }
    else{
        return $output;
    }

}

add_action( 'bp_custom_profile_edit_fields', 'bpd_edit_render_new_xprofile_field' );

Step 4. Access the WordPress registered hook functions to remove the BuddyPress profile saving handler and insert a new one. This is necessary in order to handle the saving of the custom field before passing control back to BuddyPress.

function bpd_override_xprofile_screen_edit_profile(){
    $screen_edit_profile_priority = has_filter('bp_screens', 'xprofile_screen_edit_profile');

    if($screen_edit_profile_priority !== false){
        //Remove the default profile_edit handler
        remove_action( 'bp_screens', 'xprofile_screen_edit_profile', $screen_edit_profile_priority );

        //Install replalcement hook
        add_action( 'bp_screens', 'bpd_screen_edit_profile', $screen_edit_profile_priority );
    }
}

add_action( 'bp_actions', 'bpd_override_xprofile_screen_edit_profile', 10 );

Step 5. Create the custom field saving function

function bpd_screen_edit_profile(){

    if ( isset( $_POST['field_ids'] ) ) {
        if(wp_verify_nonce( $_POST['_wpnonce'], 'bp_xprofile_edit' )){

            $posted_field_ids = explode( ',', $_POST['field_ids'] );

            $post_action_found = false;
            $post_action = '';
            if (isset($_POST['action'])){
                $post_action_found = true;
                $post_action = $_POST['action'];

            }

            foreach ( (array)$posted_field_ids as $field_id ) {
                $field_name = 'field_' . $field_id;

                if ( isset( $_FILES[$field_name] ) ) {
                    require_once( ABSPATH . '/wp-admin/includes/file.php' );
                    $uploaded_file = $_FILES[$field_name]['tmp_name'];

                    // Filter the upload location
                    add_filter( 'upload_dir', 'bpd_profile_upload_dir', 10, 1 );

                    //ensure WP accepts the upload job
                    $_POST['action'] = 'wp_handle_upload';

                    $uploaded_file = wp_handle_upload( $_FILES[$field_name] );

                    $uploaded_file = str_replace(WP_CONTENT_URL, '', $uploaded_file['url']) ;

                    $_POST[$field_name] = $uploaded_file;

                }
            }

            if($post_action_found){
                $_POST['action'] = $post_action;
            }
            else{
                unset($_POST['action']);
            }

        }
    }

    if(!defined('DOING_AJAX')){
        if(function_exists('xprofile_screen_edit_profile')){
            xprofile_screen_edit_profile();
        }
    }

}

Step 6. Override the WordPress upload directory location to provide a custom image saving location

function bpd_profile_upload_dir( $upload_dir ) {
    global $bp;

    $user_id = $bp->displayed_user->id;
    $profile_subdir = '/profiles/' . $user_id;

    $upload_dir['path'] = $upload_dir['basedir'] . $profile_subdir;
    $upload_dir['url'] = $upload_dir['baseurl'] . $profile_subdir;
    $upload_dir['subdir'] = $profile_subdir;

    return $upload_dir;
}

Step 7. Create a javascript file that shall hold code for updating the field type selection drop-down to insert the new field type when the profile front-end is displayed. Let's call the file xprofile-image.js and save it in the same location as the theme's functions.php

(

    function(jQ){
        //outerHTML method (http://stackoverflow.com/a/5259788/212076)
        jQ.fn.outerHTML = function() {
            $t = jQ(this);
            if( "outerHTML" in $t[0] ){
                return $t[0].outerHTML;
            }
            else
            {
                var content = $t.wrap('<div></div>').parent().html();
                $t.unwrap();
                return content;
            }
        }

        bpd =
        {

        init : function(){

                //add image field type on Add/Edit Xprofile field admin screen
               if(jQ("div#poststuff select#fieldtype").html() !== null){

                    if(jQ('div#poststuff select#fieldtype option[value="image"]').html() === null){
                        var imageOption = '<option value="image">Image</option>';
                        jQ("div#poststuff select#fieldtype").append(imageOption);

                        var selectedOption = jQ("div#poststuff select#fieldtype").find("option:selected");
                        if((selectedOption.length == 0) || (selectedOption.outerHTML().search(/selected/i) < 0)){
                            var action = jQ("div#poststuff").parent().attr("action");

                            if (action.search(/mode=edit_field/i) >= 0){
                                jQ('div#poststuff select#fieldtype option[value="image"]').attr("selected", "selected");
                            }
                        }
                    }

                }

            }
        };

        jQ(document).ready(function(){
                bpd.init();
        });

    }

)(jQuery);

Step 8. Load the js file (xprofile-image.js)

function bpd_load_js() {
     wp_enqueue_script( 'bpd-js', get_bloginfo('stylesheet_directory') . '/xprofile-image.js',
                            array( 'jquery' ), '1.0' );
}

add_action( 'wp_print_scripts', 'bpd_load_js' );

That's it! The WordPress user profile now has support for additional image fields via the BuddyPress extended profile component.

This would be really helpful if it could be turned into a plugin.

UPDATE: I got around to creating the plugin and it's available on the WordPress Plugins page:

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.