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
)
)