3

I've created a custom field in user profile where upload a profile image. It's very simple.

To create fields I've used:

add_action( 'show_user_profile', 'cover_image_function' );
add_action( 'edit_user_profile', 'cover_image_function' );
function cover_image_function( $user ) 
{
   <h3>Cover Image</h3>
    <style type="text/css">
    .fh-profile-upload-options th,
    .fh-profile-upload-options td,
    .fh-profile-upload-options input {
        vertical-align: top;
    }
    .user-preview-image {
        display: block;
        height: auto;
        width: 300px;
    }
    </style>
    <table class="form-table fh-profile-upload-options">
        <tr>
            <th>
                <label for="image">Cover Image</label>
            </th>
            <td>
                <img class="user-preview-image" src="<?php echo esc_attr( get_the_author_meta( 'mycoverimage', $user->ID ) ); ?>">
                <input type="text" name="mycoverimage" id="mycoverimage" value="<?php echo esc_attr( get_the_author_meta( 'mycoverimage', $user->ID ) ); ?>" class="regular-text" />
                <input type='button' class="button-primary" value="Upload Image" id="coverimage"/><br />
                <span class="description">Please upload your cover image.</span>
            </td>
        </tr>
    </table>
    <script type="text/javascript">
    (function( $ ) {
        $( 'input#coverimage' ).on('click', function() {
            tb_show('', 'media-upload.php?type=image&TB_iframe=true');

            window.send_to_editor = function( html ) 
            {
                imgurl = $( 'img', html ).attr( 'src' );
                $( '#mycoverimage' ).val(imgurl);
                tb_remove();
            }

            return false;
        });
    })(jQuery);
    </script>
}

To save my image:

add_action( 'personal_options_update', 'save_cover_image' );
add_action( 'edit_user_profile_update', 'save_cover_image' );
function save_cover_image( $user_id ) {
    if ( !current_user_can( 'edit_user', $user_id ) )
    {
        return false;
    }

    update_user_meta( $user_id, 'mycoverimage', $_POST[ 'mycoverimage' ] );
}

Everything works fine but I can't retrieve the attachment ID for generating the thumbnails and smaller sizes. For now I can just get the url like:

echo esc_attr( get_the_author_meta( 'mycoverimage', $user->ID ) );

I've even used the known method like in other questions:

function get_attachment_id($image_url) {
    global $wpdb;
    $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid='%s';", $image_url )); 
    return $attachment[0]; 
}

But It doesn't work. Is it possible that the image doesn't generate any attachment metadata, while uploading? And how Can I do it? Even suggestions, articles or questions already answered would be appreciated. Everything but a plugin, I want build a custom code. Thanks!

2
  • How does your form actually handle the image? What does $_POST[ 'mycoverimage' ] contain? Jul 26, 2016 at 9:23
  • Thanks @AndyMacaulay-Brook, I edit the question and insert the function details.
    – middlelady
    Jul 26, 2016 at 9:24

3 Answers 3

3

I suggest you to use the more newer media manager dialog; WordPress will hanlde all the image upload stuff, including generating intermediate sizes and attachement metadata.

Here a working example (it is a quick example built from a previous code, it may needs some tweaks to be used on production):

add_action( 'admin_enqueue_scripts', 'load_wp_media_files' );
function load_wp_media_files( $page ) {
  if( $page == 'profile.php' || $page == 'user-edit.php' ) {
    wp_enqueue_media();
    wp_enqueue_script( 'my_custom_script', plugins_url( '/js/myscript.js' , __FILE__ ), array('jquery'), '0.1' );
  }
}

add_action( 'show_user_profile', 'cover_image_function' );
add_action( 'edit_user_profile', 'cover_image_function' );
function cover_image_function( $user ) 
{
    $image_id = get_user_meta( $user->ID, 'mycoverimage', true );
    if( intval( $image_id ) > 0 ) {
        // Change with the image size you want to use
        $image = wp_get_attachment_image( $image_id, 'medium', false, array( 'id' => 'user-preview-image' ) );
    } else {
        $image = '<img id="user-preview-image" src="https://some.default.image.jpg" />';
    }
    ?>
   <h3>Cover Image</h3>
   <style type="text/css">
    .fh-profile-upload-options th,
    .fh-profile-upload-options td,
    .fh-profile-upload-options input {
        vertical-align: top;
    }
    .user-preview-image {
        display: block;
        height: auto;
        width: 300px;
    }
    </style>
    <table class="form-table fh-profile-upload-options">
        <tr>
            <th>
                <label for="image">Cover Image</label>
            </th>
            <td>
                <?php echo $image; ?>
                <input type="hidden" name="mycoverimage" id="mycoverimage" value="<?php echo esc_attr( get_the_author_meta( 'mycoverimage', $user->ID ) ); ?>" class="regular-text" />
                <input type='button' class="button-primary" value="Upload Image" id="coverimage"/><br />
                <span class="description">Please upload your cover image.</span>
            </td>
        </tr>
    </table>
    <?php
}

add_action( 'personal_options_update', 'save_cover_image' );
add_action( 'edit_user_profile_update', 'save_cover_image' );
function save_cover_image( $user_id ) {
    if ( ! current_user_can( 'edit_user', $user_id ) )
    {
        return false;
    }

    update_user_meta( $user_id, 'mycoverimage', $_POST[ 'mycoverimage' ] );
}  


// Ajax action to refresh the user image
add_action( 'wp_ajax_cyb_get_image_url', 'cyb_get_image_url'   );
function cyb_get_image_url() {
    if(isset($_GET['id']) ){
        $image = wp_get_attachment_image( filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT ), 'medium', false, array( 'id' => 'user-preview-image' ) );
        $data = array(
            'image'    => $image,
        );
        wp_send_json_success( $data );
    } else {
        wp_send_json_error();
    }
}

And myscript.js file:

jQuery(document).ready( function($) {

      jQuery('input#coverimage').click(function(e) {

             e.preventDefault();
             var image_frame;
             if(image_frame){
                 image_frame.open();
             }
             image_frame = wp.media({
                           title: 'Select Media',
                           multiple : false,
                           library : {
                                type : 'image',
                            }
                       });

                       image_frame.on('close',function() {
                          // get selections and save to hidden input plus other AJAX stuff etc.
                          var selection =  image_frame.state().get('selection');
                          var gallery_ids = new Array();
                          var my_index = 0;
                          selection.each(function(attachment) {
                             gallery_ids[my_index] = attachment['id'];
                             my_index++;
                          });
                          var ids = gallery_ids.join(",");
                          jQuery('input#mycoverimage').val(ids);
                          Refresh_Image(ids);
                       });

                      image_frame.on('open',function() {
                        var selection =  image_frame.state().get('selection');
                        ids = jQuery('input#mycoverimage').val().split(',');
                        ids.forEach(function(id) {
                          attachment = wp.media.attachment(id);
                          attachment.fetch();
                          selection.add( attachment ? [ attachment ] : [] );
                        });

                      });

                    image_frame.on('toolbar:create:select',function() {

                        image_frame.state().set('filterable', 'uploaded');

                    });

                    image_frame.open();
     });

});

function Refresh_Image(the_id){
        var data = {
            action: 'cyb_get_image_url',
            id: the_id
        };

        jQuery.get(ajaxurl, data, function(response) {

            if(response.success === true) {
                jQuery('#user-preview-image').replaceWith( response.data.image );
            }
        });
}

Note that this code stores image id on user meta field instead of full size image url as you was doing before, so you can get any image size form the user meta field:

$image_id = get_user_meta( $user->ID, 'mycoverimage', true );
$fulle_user_image = wp_get_attachment_image( $image_id, 'full' );
2
  • 1
    Yes, try it out. You will be using WordPress media manager to manage the image field. Let me know if you have some problems understanding what the code does.
    – cybmeta
    Jul 27, 2016 at 7:14
  • Years later I would use no JQuery, and at least typed php. Wordpress looks quite weird after working for years on Symfony.
    – middlelady
    Apr 11, 2021 at 12:21
2

I've finally solved! The problem was that simply using

update_user_meta( $user_id, 'mycoverimage', $_POST[ 'mycoverimage' ] );

The image was saved without generating attachment metadata. In fact, checking my table, it got only usermeta id which is not the attachment id. So I had to change a bit my uploading function according to codex with the use of wp_insert_attachment like:

add_action( 'personal_options_update', 'save_cover_image' );
add_action( 'edit_user_profile_update', 'save_cover_image' );
function save_cover_image( $user_id ) {
    if ( !current_user_can( 'edit_user', $user_id ) )
    {
        return false;
    }
    $filename = $_POST['mycoverimage'];
    $parent_post_id = 0;
    $filetype = wp_check_filetype( basename( $filename ), null );
    $wp_upload_dir = wp_upload_dir();
    $attachment = array(
        'guid'           => $wp_upload_dir['url'] . '/' . basename( $filename ), 
        'post_mime_type' => $filetype['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
        'post_content'   => '',
        'post_status'    => 'inherit',
        'post_author'    => $uid
    );
    $attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );
    require_once( ABSPATH . 'wp-admin/includes/image.php' );
    $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
    wp_update_attachment_metadata( $attach_id, $attach_data );
    update_user_meta( $user_id, 'mycoverimage', $_POST[ 'mycoverimage' ] );
}

At this point I have a usermeta id and an attachment id which I can easily retrieve for thumbs and other operations. Thanks to @majick anyway.

1

Not sure it will make a difference, but as you just want one value you can get get_var instead of get_col. I tweaked the query slightly to what I know works:

function get_attachment_id($image_url) {
    global $wpdb;
    $attachment = $wpdb->get_var($wpdb->prepare("SELECT ID FROM ".$wpdb->prefix."posts WHERE post_type='attachment' AND guid='%s'", $image_url )); 
    return $attachment; 
}

And making use you are not doing esc_attr on the URL value before sending it to the function or it won't match to it.

EDIT You could try this to (less strictly) just match the URL path to the guid instead of the full URL:

function get_attachment_id($image_url) {
    $parseurl = parse_url($image_url);
    $path = $parseurl['path'];

    global $wpdb;
    $attachments = $wpdb->get_results("SELECT ID,guid FROM ".$wpdb->prefix."posts WHERE post_type='attachment'");
    foreach ($attachments as $attachment) {
        if (strstr($attachment->guid,$path)) {return $attachment->ID;}
    }
    echo "<!-- All Attachments "; print_r($attachments); echo "-->"; // debug output
}
4
  • Thanks for your precious answer! Unfortunately echoing get_attachment_id($image_url) even with your changes doesn't give back any value. I'm desperate...
    – middlelady
    Jul 26, 2016 at 9:48
  • 1
    added an alternative, not be the most efficient way but it may work for you in the short term.
    – majick
    Jul 26, 2016 at 10:17
  • Thanks dude, I've solved! The attachment wasn't an attachment actually. I've just used wp_insert_attachment in my uploading function. Thanks anyway. Have a great day!
    – middlelady
    Jul 26, 2016 at 10:19
  • 1
    no problemo, yep that would do it. have a great one yourself. :-)
    – majick
    Jul 26, 2016 at 10:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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