PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
elementor / modules / mcp / abilities / list-assets-ability.php

list-assets-ability.php in Elementor Website Builder – more than just a page builder 4.3.0-beta3, at modules/mcp/abilities/list-assets-ability.php

201 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\Mcp\Abilities;
4
5 use Elementor\Modules\Mcp\Abilities\Utils\Prompt_Loader;
6
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit;
9 }
10
11 class List_Assets_Ability extends Abstract_Ability {
12
13 const MAX_PER_PAGE = 50;
14 const DEFAULT_PER_PAGE = 20;
15
16 const TYPE_ALL = 'all';
17 const TYPE_IMAGE = 'image';
18 const TYPE_SVG = 'svg';
19 const TYPE_VIDEO = 'video';
20
21 const IMAGE_MIME_TYPES = [
22 'image/jpeg',
23 'image/png',
24 'image/gif',
25 'image/webp',
26 'image/avif',
27 'image/svg+xml',
28 ];
29
30 const SVG_MIME_TYPE = 'image/svg+xml';
31
32 const VIDEO_MIME_TYPES = [
33 'video/mp4',
34 'video/webm',
35 'video/ogg',
36 'video/quicktime',
37 'video/x-m4v',
38 'video/avi',
39 'video/x-ms-wmv',
40 'video/mpeg',
41 'video/3gpp',
42 'video/3gpp2',
43 ];
44
45 const EMPTY_RESULT_HINT = 'No matching assets are in the Media Library. Ask the user to upload the images or SVG icons they want to use (WP Admin → Media → Add New), then call this tool again. Do not fabricate attachment ids.';
46
47 protected function get_ability_id(): string {
48 return 'elementor/list-assets';
49 }
50
51 protected function get_definition(): Ability_Definition {
52 return new Ability_Definition(
53 __( 'List Media Library Assets', 'elementor' ),
54 Prompt_Loader::load( 'list-assets' ),
55 'elementor',
56 [
57 'type' => 'object',
58 'properties' => [
59 'assets' => [
60 'type' => 'array',
61 'items' => [
62 'type' => 'object',
63 'properties' => [
64 'id' => [ 'type' => 'integer' ],
65 'url' => [ 'type' => 'string' ],
66 'title' => [ 'type' => 'string' ],
67 'alt' => [ 'type' => 'string' ],
68 'mime_type' => [ 'type' => 'string' ],
69 'width' => [ 'type' => [ 'integer', 'null' ] ],
70 'height' => [ 'type' => [ 'integer', 'null' ] ],
71 ],
72 ],
73 ],
74 'total' => [ 'type' => 'integer' ],
75 'page' => [ 'type' => 'integer' ],
76 'per_page' => [ 'type' => 'integer' ],
77 'llm_instructions' => [ 'type' => 'string' ],
78 ],
79 ],
80 [
81 'annotations' => [
82 'readonly' => true,
83 'idempotent' => true,
84 'destructive' => false,
85 ],
86 ],
87 fn() => current_user_can( 'edit_posts' ),
88 [
89 'type' => 'object',
90 'properties' => [
91 'search' => [
92 'type' => 'string',
93 'description' => 'Optional keyword matched against attachment title and filename.',
94 ],
95 'type' => [
96 'type' => 'string',
97 'enum' => [ self::TYPE_ALL, self::TYPE_IMAGE, self::TYPE_SVG, self::TYPE_VIDEO ],
98 'default' => self::TYPE_ALL,
99 'description' => 'Filter by asset kind. "svg" returns only SVG assets, which are required to reference from an e-svg widget. "video" returns only uploaded videos for e-self-hosted-video and e-background-video.',
100 ],
101 'page' => [
102 'type' => 'integer',
103 'minimum' => 1,
104 'default' => 1,
105 ],
106 'per_page' => [
107 'type' => 'integer',
108 'minimum' => 1,
109 'maximum' => self::MAX_PER_PAGE,
110 'default' => self::DEFAULT_PER_PAGE,
111 ],
112 ],
113 ]
114 );
115 }
116
117 public function execute( $input = [] ) {
118 if ( ! current_user_can( 'edit_posts' ) ) {
119 return new \WP_Error(
120 'rest_forbidden',
121 __( 'You do not have permission to list media assets.', 'elementor' ),
122 [ 'status' => \WP_Http::FORBIDDEN ]
123 );
124 }
125
126 $input = is_array( $input ) ? $input : [];
127
128 $page = $this->resolve_page( $input );
129 $per_page = $this->resolve_per_page( $input );
130 $mime_types = $this->resolve_mime_types( $input );
131 $search = isset( $input['search'] ) && is_string( $input['search'] ) ? trim( $input['search'] ) : '';
132
133 $query = new \WP_Query( [
134 'post_type' => 'attachment',
135 'post_status' => 'inherit',
136 'post_mime_type' => $mime_types,
137 'orderby' => 'date',
138 'order' => 'DESC',
139 'paged' => $page,
140 'posts_per_page' => $per_page,
141 's' => $search,
142 'no_found_rows' => false,
143 ] );
144
145 $assets = array_map( [ $this, 'format_attachment' ], $query->posts );
146
147 $response = [
148 'assets' => $assets,
149 'total' => (int) $query->found_posts,
150 'page' => $page,
151 'per_page' => $per_page,
152 ];
153
154 if ( 0 === $response['total'] ) {
155 $response['llm_instructions'] = self::EMPTY_RESULT_HINT;
156 }
157
158 return $response;
159 }
160
161 private function resolve_page( array $input ): int {
162 $page = isset( $input['page'] ) ? (int) $input['page'] : 1;
163
164 return max( 1, $page );
165 }
166
167 private function resolve_per_page( array $input ): int {
168 $per_page = isset( $input['per_page'] ) ? (int) $input['per_page'] : self::DEFAULT_PER_PAGE;
169
170 return max( 1, min( self::MAX_PER_PAGE, $per_page ) );
171 }
172
173 private function resolve_mime_types( array $input ): array {
174 $type = isset( $input['type'] ) && is_string( $input['type'] ) ? $input['type'] : self::TYPE_ALL;
175
176 if ( self::TYPE_SVG === $type ) {
177 return [ self::SVG_MIME_TYPE ];
178 }
179
180 if ( self::TYPE_VIDEO === $type ) {
181 return self::VIDEO_MIME_TYPES;
182 }
183
184 return self::IMAGE_MIME_TYPES;
185 }
186
187 private function format_attachment( \WP_Post $attachment ): array {
188 $metadata = wp_get_attachment_metadata( $attachment->ID );
189
190 return [
191 'id' => (int) $attachment->ID,
192 'url' => (string) wp_get_attachment_url( $attachment->ID ),
193 'title' => (string) $attachment->post_title,
194 'alt' => (string) get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ),
195 'mime_type' => (string) $attachment->post_mime_type,
196 'width' => isset( $metadata['width'] ) ? (int) $metadata['width'] : null,
197 'height' => isset( $metadata['height'] ) ? (int) $metadata['height'] : null,
198 ];
199 }
200 }
201