| 1 |
<?php |
| 2 |
/** |
| 3 |
* Ability: wpdatatables/list-media |
| 4 |
* |
| 5 |
* Lists media items from the WordPress media library for use in tables. |
| 6 |
* Returns attachment IDs, URLs, and metadata so AI can reference images in cells. |
| 7 |
* |
| 8 |
* @package wpDataTables_MCP_Server |
| 9 |
* @since 0.2.0 |
| 10 |
*/ |
| 11 |
|
| 12 |
defined( 'ABSPATH' ) or die('Access denied.'); |
| 13 |
|
| 14 |
add_action( 'wp_abilities_api_init', 'wdtmcp_register_list_media_ability' ); |
| 15 |
|
| 16 |
function wdtmcp_register_list_media_ability() { |
| 17 |
wp_register_ability( |
| 18 |
'wpdatatables/list-media', |
| 19 |
array( |
| 20 |
'label' => __( 'List Media Library', 'wpdatatables' ), |
| 21 |
'description' => __( 'Lists media items from the WordPress media library. Returns attachment_id, source_url, alt_text, title for use in table cells. Use search to find images by title, or media_type to filter (image, video, etc.). Use attachment_id in cell data with create-simple-table or update-simple-table-styles to insert images. WHEN TO CALL: before putting images into Simple table cells — when you need an existing attachment_id from the Media Library. OPTIONAL INPUT: search (string, match title/filename), media_type (image|video|audio|application), page (default 1), per_page (default 20, max 100). RETURNS: { media: [{ attachment_id, source_url, alt_text, title, mime_type }], total, page }. IF NO MATCH: use upload-media-from-url to import a remote image first. TYPICAL WORKFLOW: list-media → use attachment_id in create-simple-table or update-simple-table-styles cell data as {"attachment_id":123,"size":"medium","alt":"..."}.', 'wpdatatables' ), |
| 22 |
'category' => 'wpdatatables-data', |
| 23 |
|
| 24 |
'input_schema' => array( |
| 25 |
'type' => 'object', |
| 26 |
'properties' => array( |
| 27 |
'search' => array( |
| 28 |
'type' => 'string', |
| 29 |
'description' => 'Search media by title or filename.', |
| 30 |
), |
| 31 |
'media_type' => array( |
| 32 |
'type' => 'string', |
| 33 |
'description' => 'Filter by type: image, video, audio, application.', |
| 34 |
), |
| 35 |
'per_page' => array( |
| 36 |
'type' => 'integer', |
| 37 |
'description' => 'Number of items to return (default 20, max 100).', |
| 38 |
), |
| 39 |
'page' => array( |
| 40 |
'type' => 'integer', |
| 41 |
'description' => 'Page number for pagination (default 1).', |
| 42 |
), |
| 43 |
), |
| 44 |
), |
| 45 |
|
| 46 |
'output_schema' => array( |
| 47 |
'type' => 'object', |
| 48 |
'properties' => array( |
| 49 |
'media' => array( |
| 50 |
'type' => 'array', |
| 51 |
'description' => 'Array of media items.', |
| 52 |
'items' => array( |
| 53 |
'type' => 'object', |
| 54 |
'properties' => array( |
| 55 |
'attachment_id' => array( 'type' => 'integer', 'description' => 'WordPress attachment ID.' ), |
| 56 |
'source_url' => array( 'type' => 'string', 'description' => 'URL to the media file.' ), |
| 57 |
'title' => array( 'type' => 'string', 'description' => 'Attachment title.' ), |
| 58 |
'alt_text' => array( 'type' => 'string', 'description' => 'Alt text for images.' ), |
| 59 |
'media_type' => array( 'type' => 'string', 'description' => 'image, video, audio, etc.' ), |
| 60 |
'mime_type' => array( 'type' => 'string', 'description' => 'MIME type.' ), |
| 61 |
), |
| 62 |
), |
| 63 |
), |
| 64 |
'total' => array( 'type' => 'integer', 'description' => 'Total matching items.' ), |
| 65 |
'page' => array( 'type' => 'integer', 'description' => 'Current page number.' ), |
| 66 |
|
| 67 |
), |
| 68 |
), |
| 69 |
|
| 70 |
'execute_callback' => 'wdtmcp_execute_list_media', |
| 71 |
|
| 72 |
'permission_callback' => function () { |
| 73 |
return current_user_can( 'manage_options' ); |
| 74 |
}, |
| 75 |
|
| 76 |
'meta' => array( |
| 77 |
'annotations' => array( |
| 78 |
'instructions' => __( 'Optional search and media_type filters. Use returned attachment_id in create-simple-table or update-simple-table-styles cell objects.', 'wpdatatables' ), |
| 79 |
'readonly' => true, |
| 80 |
'destructive' => false, |
| 81 |
'idempotent' => true, |
| 82 |
), |
| 83 |
), |
| 84 |
) |
| 85 |
); |
| 86 |
} |
| 87 |
|
| 88 |
/** |
| 89 |
* Execute callback for wpdatatables/list-media. |
| 90 |
* |
| 91 |
* @param array $input |
| 92 |
* @return array|WP_Error |
| 93 |
*/ |
| 94 |
function wdtmcp_execute_list_media( $input ) { |
| 95 |
$search = isset( $input['search'] ) ? sanitize_text_field( $input['search'] ) : ''; |
| 96 |
$type = isset( $input['media_type'] ) ? sanitize_text_field( $input['media_type'] ) : ''; |
| 97 |
$per_page = isset( $input['per_page'] ) ? min( 100, max( 1, (int) $input['per_page'] ) ) : 20; |
| 98 |
$page = isset( $input['page'] ) ? max( 1, (int) $input['page'] ) : 1; |
| 99 |
|
| 100 |
$args = array( |
| 101 |
'post_type' => 'attachment', |
| 102 |
'post_status' => 'inherit', |
| 103 |
'posts_per_page' => $per_page, |
| 104 |
'paged' => $page, |
| 105 |
'orderby' => 'date', |
| 106 |
'order' => 'DESC', |
| 107 |
); |
| 108 |
|
| 109 |
if ( '' !== $search ) { |
| 110 |
$args['s'] = $search; |
| 111 |
} |
| 112 |
|
| 113 |
if ( '' !== $type ) { |
| 114 |
$args['post_mime_type'] = $type; |
| 115 |
if ( 'image' === $type ) { |
| 116 |
$args['post_mime_type'] = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml' ); |
| 117 |
} |
| 118 |
} |
| 119 |
|
| 120 |
$query = new \WP_Query( $args ); |
| 121 |
$posts = $query->posts; |
| 122 |
$total = (int) $query->found_posts; |
| 123 |
|
| 124 |
$media = array(); |
| 125 |
foreach ( $posts as $post ) { |
| 126 |
$url = wp_get_attachment_url( $post->ID ); |
| 127 |
if ( ! $url ) { |
| 128 |
continue; |
| 129 |
} |
| 130 |
$media[] = array( |
| 131 |
'attachment_id' => (int) $post->ID, |
| 132 |
'source_url' => $url, |
| 133 |
'title' => $post->post_title, |
| 134 |
'alt_text' => (string) get_post_meta( $post->ID, '_wp_attachment_image_alt', true ), |
| 135 |
'media_type' => (string) ( wp_attachment_is_image( $post->ID ) ? 'image' : $post->post_mime_type ), |
| 136 |
'mime_type' => (string) $post->post_mime_type, |
| 137 |
); |
| 138 |
} |
| 139 |
|
| 140 |
return array( |
| 141 |
'media' => $media, |
| 142 |
'total' => $total, |
| 143 |
'page' => $page, |
| 144 |
); |
| 145 |
} |
| 146 |
|