wp_ajax_query_attachments()
云策文档标注
概述
wp_ajax_query_attachments() 是一个 WordPress AJAX 处理函数,用于查询附件。它通过 WP_Query 执行查询,并返回 JSON 格式的附件数据,支持分页和权限检查。
关键要点
- 函数处理 AJAX 请求,查询附件,要求用户具有 upload_files 权限。
- 从 $_REQUEST['query'] 中提取查询参数,包括 s、order、orderby、posts_per_page 等标准 WP_Query 键,并自动包含附件相关的分类法查询变量。
- 设置查询的 post_type 为 'attachment',post_status 默认为 'inherit',支持 'trash' 状态(如果 MEDIA_TRASH 启用)和 'private' 状态(基于用户权限)。
- 当查询中包含搜索词(s 参数)时,启用 wp_allow_query_attachment_by_filename 过滤器以允许按文件名搜索。
- 使用 ajax_query_attachments_args 过滤器允许开发者修改查询参数。
- 通过 WP_Query 执行查询,使用 wp_prepare_attachment_for_js 准备附件数据,并发送 JSON 响应,包含附件列表、总数和分页信息。
代码示例
if ( ! current_user_can( 'upload_files' ) ) {
wp_send_json_error();
}
$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
$keys = array(
's',
'order',
'orderby',
'posts_per_page',
'paged',
'post_mime_type',
'post_parent',
'author',
'post__in',
'post__not_in',
'year',
'monthnum',
);
foreach ( get_taxonomies_for_attachments( 'objects' ) as $t ) {
if ( $t->query_var && isset( $query[ $t->query_var ] ) ) {
$keys[] = $t->query_var;
}
}
$query = array_intersect_key( $query, array_flip( $keys ) );
$query['post_type'] = 'attachment';
if (
MEDIA_TRASH &&
! empty( $_REQUEST['query']['post_status'] ) &&
'trash' === $_REQUEST['query']['post_status']
) {
$query['post_status'] = 'trash';
} else {
$query['post_status'] = 'inherit';
}
if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) ) {
$query['post_status'] .= ',private';
}
if ( isset( $query['s'] ) ) {
add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' );
}
$query = apply_filters( 'ajax_query_attachments_args', $query );
$attachments_query = new WP_Query( $query );
update_post_parent_caches( $attachments_query->posts );
$posts = array_map( 'wp_prepare_attachment_for_js', $attachments_query->posts );
$posts = array_filter( $posts );
$total_posts = $attachments_query->found_posts;
if ( $total_posts < $attachments_query->get( 'posts_per_page' ) ) {
$count_query = new WP_Query( $query );
$total_posts = $count_query->found_posts;
}
$posts_per_page = (int) $attachments_query->get( 'posts_per_page' );
$max_pages = $posts_per_page ? (int) ceil( $total_posts / $posts_per_page ) : 0;
header( 'X-WP-Total: ' . (int) $total_posts );
header( 'X-WP-TotalPages: ' . $max_pages );
wp_send_json_success( $posts );注意事项
- 函数依赖于 WordPress 的 AJAX 处理机制,通常通过 admin-ajax.php 调用。
- 权限检查基于 current_user_can('upload_files'),确保只有授权用户能访问。
- 查询参数过滤使用 array_intersect_key 和预定义键数组,增强安全性。
- post_status 处理考虑了 MEDIA_TRASH 常量和用户权限,以支持不同状态。
- 响应头包含 X-WP-Total 和 X-WP-TotalPages,便于前端分页处理。
原文内容
Handles querying attachments via AJAX.
Source
function wp_ajax_query_attachments() {
if ( ! current_user_can( 'upload_files' ) ) {
wp_send_json_error();
}
$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
$keys = array(
's',
'order',
'orderby',
'posts_per_page',
'paged',
'post_mime_type',
'post_parent',
'author',
'post__in',
'post__not_in',
'year',
'monthnum',
);
foreach ( get_taxonomies_for_attachments( 'objects' ) as $t ) {
if ( $t->query_var && isset( $query[ $t->query_var ] ) ) {
$keys[] = $t->query_var;
}
}
$query = array_intersect_key( $query, array_flip( $keys ) );
$query['post_type'] = 'attachment';
if (
MEDIA_TRASH &&
! empty( $_REQUEST['query']['post_status'] ) &&
'trash' === $_REQUEST['query']['post_status']
) {
$query['post_status'] = 'trash';
} else {
$query['post_status'] = 'inherit';
}
if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) ) {
$query['post_status'] .= ',private';
}
// Filter query clauses to include filenames.
if ( isset( $query['s'] ) ) {
add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' );
}
/**
* Filters the arguments passed to WP_Query during an Ajax
* call for querying attachments.
*
* @since 3.7.0
*
* @see WP_Query::parse_query()
*
* @param array $query An array of query variables.
*/
$query = apply_filters( 'ajax_query_attachments_args', $query );
$attachments_query = new WP_Query( $query );
update_post_parent_caches( $attachments_query->posts );
$posts = array_map( 'wp_prepare_attachment_for_js', $attachments_query->posts );
$posts = array_filter( $posts );
$total_posts = $attachments_query->found_posts;
if ( $total_posts < 1 ) {
// Out-of-bounds, run the query again without LIMIT for total count.
unset( $query['paged'] );
$count_query = new WP_Query();
$count_query->query( $query );
$total_posts = $count_query->found_posts;
}
$posts_per_page = (int) $attachments_query->get( 'posts_per_page' );
$max_pages = $posts_per_page ? (int) ceil( $total_posts / $posts_per_page ) : 0;
header( 'X-WP-Total: ' . (int) $total_posts );
header( 'X-WP-TotalPages: ' . $max_pages );
wp_send_json_success( $posts );
}
Hooks
- apply_filters( ‘ajax_query_attachments_args’, array $query )
-
Filters the arguments passed to WP_Query during an Ajax call for querying attachments.
Changelog
| Version | Description |
|---|---|
| 3.5.0 | Introduced. |