3

I have some section where user can upload CV and profile images,

I'm using the native attachment functions,

$attachment_cv_id = media_handle_upload( 'candidate_cv', 0 );
if ( ! is_wp_error( $attachment_cv_id ) ) {
    // We link this file to the post 
    // add_post_meta( $result , 'wpcf-cv-file', wp_get_attachment_url($attachment_cv_id));
} else {
    $submit_candidate_errors[] = lang("Hubo error subiendo la CV");
}

Is there any way I can hide this files from the media section in the wp-admin? ( perhaps changing its folder )

Thanks

-EDIT-

i'm trying like Dave suggested, adding a meta: 'rrhh-file'

$attachment_id = media_handle_upload( 'apply_file', 0 );

if ( ! is_wp_error( $attachment_id ) ) {
    // The image was uploaded successfully!
    add_post_meta($attachment_id, 'rrhh-file', true);
}

And even that it has the attribute:

var_dump(get_post_meta(1200)); // last id I uploaded
die();

Prints out:

array(4) {
  ["_wp_attached_file"]=>
  array(1) {
    [0]=>
    string(20) "2017/06/image001.jpg"
  }
  ["_wp_attachment_metadata"]=>
  array(1) {
    [0]=>
    string(666) "a:5:{s:5:"width";i:523;s:6:"height";i:122;s:4:"file";s:20:"2017/06/image001.jpg";s:5:"sizes";a:2:{s:9:"thumbnail";a:4:{s:4:"file";s:20:"image001-150x122.jpg";s:5:"width";i:150;s:6:"height";i:122;s:9:"mime-type";s:10:"image/jpeg";}s:6:"medium";a:4:{s:4:"file";s:19:"image001-300x70.jpg";s:5:"width";i:300;s:6:"height";i:70;s:9:"mime-type";s:10:"image/jpeg";}}s:10:"image_meta";a:12:{s:8:"aperture";s:1:"0";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption";s:0:"";s:17:"created_timestamp";s:1:"0";s:9:"copyright";s:0:"";s:12:"focal_length";s:1:"0";s:3:"iso";s:1:"0";s:13:"shutter_speed";s:1:"0";s:5:"title";s:0:"";s:11:"orientation";s:1:"1";s:8:"keywords";a:0:{}}}"
  }
  ["rrhh-file"]=> // <-- here
  array(1) {
    [0]=>
    string(1) "1"
  }
  ["_edit_lock"]=>
  array(1) {
    [0]=>
    string(12) "1498731595:1"
  }
}

With this action this attachment still shows up in the media library

add_action( 'pre_get_posts', 'wpse_hide_cv_media_list_view' );
function wpse_hide_cv_media_list_view( $query ) {
    // Bail if this is not the admin area.
    if ( ! is_admin() ) {
        return;
    }

    // Bail if this is not the main query.
    if ( ! $query->is_main_query() ) {
        return;
    }

    // Only proceed if this the attachment upload screen.
    $screen = get_current_screen();
    if ( ! $screen || 'upload' !== $screen->id || 'attachment' !== $screen->post_type ) {
        return;
    }

    // Modify the query.
    $query->set( 'meta_query', [
        [
            'key'     => 'rrhh-file',
            'compare' => 'NOT EXISTS',
        ]
    ]);

    return;
}

Any idea what i'm missing?

1 Answer 1

8

WordPress has two different ways of displaying media. There's the media overlay/modal view and also the list view, which is triggered by navigating to Admin > Media > Library then by clicking the list view icon next to the filter select box. To filter attachments in both locations, we will need to use two separate hooks.

Filtering attachments in the Media Library (modal view)

The ajax_query_attachments_args filter can be used to adjust the query used for getting attachments on the media overlay screens. (Adapted from this answer from birgire.)

/**
 * Hide attachment files from the Media Library's overlay (modal) view
 * if they have a certain meta key set.
 * 
 * @param array $args An array of query variables.
 */
add_filter( 'ajax_query_attachments_args', 'wpse_hide_cv_media_overlay_view' );
function wpse_hide_cv_media_overlay_view( $args ) {
    // Bail if this is not the admin area.
    if ( ! is_admin() ) {
        return $args;
    }

    // Modify the query.
    $args['meta_query'] = [
        [
            'key'     => 'rrhh-file',
            'compare' => 'NOT EXISTS',
        ]
    ];
   
    return $args;
}

Filtering attachments in the Media Library (list view)

We need an additional, separate approach for modifying the attachment query on the Media Library screen in list view (older list mode, non-modal view). The pre_get_posts hook will do the trick:

/**
 * Hide attachment files from the Media Library's list view
 * if they have a certain meta key set.
 * 
 * @param WP_Query $query The WP_Query instance (passed by reference).
 */
add_action( 'pre_get_posts', 'wpse_hide_cv_media_list_view' );
function wpse_hide_cv_media_list_view( $query ) {
    // Bail if this is not the admin area.
    if ( ! is_admin() ) {
        return;
    }

    // Bail if this is not the main query.
    if ( ! $query->is_main_query() ) {
        return;
    }

    // Only proceed if this the attachment upload screen.
    $screen = get_current_screen();
    if ( ! $screen || 'upload' !== $screen->id || 'attachment' !== $screen->post_type ) {
        return;
    }
    
    // Modify the query.
    $query->set( 'meta_query', [
        [
            'key'     => 'rrhh-file',
            'compare' => 'NOT EXISTS',
        ]
    ]   );

    return;
}

In both cases, we're setting up a meta query to exclude any attachments that have the meta key rrhh-file set. You can change the meta query or conditions to suit your needs.

Note that meta queries are slow. One alternative approach would be to assign these special media items to a custom taxonomy when they are uploaded/created, then alter the query to exclude these items using a tax query.

Edit: Debugging info

I'm using the following functions to allow me to more easily edit our custom attachment field:

/**
 * Add custom field to media
 */
add_filter( 'attachment_fields_to_edit', 'wpse_cv_attachment_fields', 10, 2 );
function wpse_cv_attachment_fields( $fields, $post ) {
    $meta = get_post_meta( $post->ID, 'rrhh-file', true );

    $fields['rrhh-file'] = array(
            'label' =>  __( 'RRHH File', 'text-domain' ),
            'input' => 'text',
            'value' => $meta,
            'show_in_edit' => true,
    );

    return $fields;
}

/**
 * Update custom field within media overlay (via ajax)
 */
add_action( 'wp_ajax_save-attachment-compat', 'wpse_cv_media_fields', 0, 1 );
function wpse_cv_media_fields() {
    $post_id = $_POST['id'];
    $value = isset( $_POST['attachments'][ $post_id ]['rrhh-file'] ) ? $_POST['attachments'][ $post_id ]['rrhh-file'] : false;
    
    if ( '1' === $value ) {
        update_post_meta( $post_id, 'rrhh-file', $value );
    } else {
        delete_post_meta( $post_id, 'rrhh-file' );
    }

    clean_post_cache( $post_id );
}

/**
 * Update media custom field from edit media page (non ajax).
 */
add_action( 'edit_attachment', 'wpse_cv_update_attachment_meta', 1 );
function wpse_cv_update_attachment_meta( $post_id ) {
    $value = isset( $_POST['attachments'][ $post_id ]['rrhh-file'] ) ? $_POST['attachments'][ $post_id ]['rrhh-file'] : false;
    //exit ( var_dump( $value ) );
    if ( '1' === $value ) {
        update_post_meta( $post_id, 'rrhh-file', $value );
    } else {
        delete_post_meta( $post_id, 'rrhh-file' );
    }

    return;
}

I use the following SQL to check if the rrhh-file field is set:

SELECT * FROM wp_postmeta w where meta_key = 'rrhh-file';

When viewing the media library in list mode, which should be affected by our pre_get_posts hook, $query->is_main_query() is returning true and $screen, the WP_Screen object, looks like this:

WP_Screen Object
(
    [action] => 
    [base] => upload
    [columns:WP_Screen:private] => 0
    [id] => upload
    [in_admin:protected] => site
    [is_network] => 
    [is_user] => 
    [parent_base] => 
    [parent_file] => 
    [post_type] => attachment
    [taxonomy] => 
    [_help_tabs:WP_Screen:private] => Array
        (
        )

    [_help_sidebar:WP_Screen:private] => 
    [_screen_reader_content:WP_Screen:private] => Array
        (
        )

    [_options:WP_Screen:private] => Array
        (
        )

    [_show_screen_options:WP_Screen:private] => 
    [_screen_settings:WP_Screen:private] => 
)

and the $query, the WP_Query object looks like this:

WP_Query Object
(
    [query] => Array
        (
            [m] => 0
            [cat] => 0
            [post_type] => attachment
            [posts_per_page] => 20
            [post_status] => inherit,private
        )

    [query_vars] => Array
        (
            [m] => 0
            [cat] => 0
            [post_type] => attachment
            [posts_per_page] => 20
            [post_status] => inherit,private
            [error] => 
            [p] => 0
            [post_parent] => 
            [subpost] => 
            [subpost_id] => 
            [attachment] => 
            [attachment_id] => 0
            [name] => 
            [static] => 
            [pagename] => 
            [page_id] => 0
            [second] => 
            [minute] => 
            [hour] => 
            [day] => 0
            [monthnum] => 0
            [year] => 0
            [w] => 0
            [category_name] => 
            [tag] => 
            [tag_id] => 
            [author] => 
            [author_name] => 
            [feed] => 
            [tb] => 
            [paged] => 0
            [meta_key] => 
            [meta_value] => 
            [preview] => 
            [s] => 
            [sentence] => 
            [title] => 
            [fields] => 
            [menu_order] => 
            [embed] => 
            [category__in] => Array
                (
                )

            [category__not_in] => Array
                (
                )

            [category__and] => Array
                (
                )

            [post__in] => Array
                (
                )

            [post__not_in] => Array
                (
                )

            [post_name__in] => Array
                (
                )

            [tag__in] => Array
                (
                )

            [tag__not_in] => Array
                (
                )

            [tag__and] => Array
                (
                )

            [tag_slug__in] => Array
                (
                )

            [tag_slug__and] => Array
                (
                )

            [post_parent__in] => Array
                (
                )

            [post_parent__not_in] => Array
                (
                )

            [author__in] => Array
                (
                )

            [author__not_in] => Array
                (
                )

        )

    [tax_query] => WP_Tax_Query Object
        (
            [queries] => Array
                (
                )

            [relation] => AND
            [table_aliases:protected] => Array
                (
                )

            [queried_terms] => Array
                (
                )

            [primary_table] => 
            [primary_id_column] => 
        )

    [meta_query] => 
    [date_query] => 
    [post_count] => 0
    [current_post] => -1
    [in_the_loop] => 
    [comment_count] => 0
    [current_comment] => -1
    [found_posts] => 0
    [max_num_pages] => 0
    [max_num_comment_pages] => 0
    [is_single] => 
    [is_preview] => 
    [is_page] => 
    [is_archive] => 
    [is_date] => 
    [is_year] => 
    [is_month] => 
    [is_day] => 
    [is_time] => 
    [is_author] => 
    [is_category] => 
    [is_tag] => 
    [is_tax] => 
    [is_search] => 
    [is_feed] => 
    [is_comment_feed] => 
    [is_trackback] => 
    [is_home] => 
    [is_404] => 
    [is_embed] => 
    [is_paged] => 
    [is_admin] => 1
    [is_attachment] => 
    [is_singular] => 
    [is_robots] => 
    [is_posts_page] => 
    [is_post_type_archive] => 
    [query_vars_hash:WP_Query:private] => b01f0d78a3a985d46374d4384bba30b7
    [query_vars_changed:WP_Query:private] => 
    [thumbnails_cached] => 
    [stopwords:WP_Query:private] => 
    [compat_fields:WP_Query:private] => Array
        (
            [0] => query_vars_hash
            [1] => query_vars_changed
        )

    [compat_methods:WP_Query:private] => Array
        (
            [0] => init_query_flags
            [1] => parse_tax_query
        )

)
10
  • oh, now that I realise, the add_post_meta is applied to another entity.. ( the cv_submission, not the cv_file ), i'll remove it from the question. that changes everyting, right? Thanks for your input :) Commented Jun 28, 2017 at 10:24
  • Yes, but the overall concept still applies. We'll need to set some meta data or assign a custom taxonomy term or use some other way to identify these attachments and then exclude them. Commented Jun 28, 2017 at 10:27
  • 1
    Ok, I think I understand; I'll give it a shot and let you know. Thanks! Commented Jun 28, 2017 at 13:07
  • I had some tests ( and made sure that the postmeta was saved ), but it shows up in the media library ( updating the question with details ), any idea? Commented Jun 29, 2017 at 10:34
  • 1
    Works great for me! One note though: In your wpse_hide_cv_media_overlay_view, you return void if ! is_admin() is true. In order to not break the filter, you should however return always $args. I suggested this as edit.
    – KittMedia
    Commented Oct 8, 2021 at 12:37

Your Answer

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

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