PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.14
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.14
2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 All 139 releases
metasync / wp-mcp-server / tools / class-mcp-tool-media.php

class-mcp-tool-media.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.14, at wp-mcp-server/tools/class-mcp-tool-media.php

490 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MCP Tools for Media Operations
4 *
5 * Provides MCP tools for managing featured images and media library.
6 *
7 * @package MetaSync
8 * @subpackage MCP_Server/Tools
9 */
10
11 if (!defined('ABSPATH')) {
12 exit;
13 }
14
15 require_once plugin_dir_path(dirname(__FILE__)) . 'class-mcp-tool-base.php';
16
17 /**
18 * Get Featured Image Tool
19 *
20 * Gets featured image for a post
21 */
22 class MCP_Tool_Get_Featured_Image extends MCP_Tool_Base {
23
24 public function get_name() {
25 return 'wordpress_get_featured_image';
26 }
27
28 public function get_description() {
29 return 'Get featured image details for a post';
30 }
31
32 public function get_input_schema() {
33 return [
34 'type' => 'object',
35 'properties' => [
36 'post_id' => [
37 'type' => 'integer',
38 'description' => 'Post ID',
39 ],
40 ],
41 'required' => ['post_id'],
42 ];
43 }
44
45 public function execute($params) {
46 $this->validate_params($params);
47 $this->require_capability('edit_posts');
48
49 $post_id = intval($params['post_id']);
50
51 // Validate post exists
52 $post = $this->verify_post_exists($post_id);
53
54 $thumbnail_id = get_post_thumbnail_id($post_id);
55
56 if (!$thumbnail_id) {
57 return $this->success([
58 'post_id' => $post_id,
59 'post_title' => $post->post_title,
60 'has_featured_image' => false,
61 'featured_image' => null,
62 ]);
63 }
64
65 $attachment = get_post($thumbnail_id);
66 $metadata = wp_get_attachment_metadata($thumbnail_id);
67
68 return $this->success([
69 'post_id' => $post_id,
70 'post_title' => $post->post_title,
71 'has_featured_image' => true,
72 'featured_image' => [
73 'attachment_id' => $thumbnail_id,
74 'url' => wp_get_attachment_url($thumbnail_id),
75 'title' => $attachment->post_title,
76 'alt_text' => get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true),
77 'caption' => $attachment->post_excerpt,
78 'description' => $attachment->post_content,
79 'mime_type' => $attachment->post_mime_type,
80 'width' => isset($metadata['width']) ? $metadata['width'] : null,
81 'height' => isset($metadata['height']) ? $metadata['height'] : null,
82 'file_size' => isset($metadata['filesize']) ? $metadata['filesize'] : filesize(get_attached_file($thumbnail_id)),
83 ],
84 ]);
85 }
86 }
87
88 /**
89 * Set Featured Image Tool
90 *
91 * Sets featured image for a post by attachment ID
92 */
93 class MCP_Tool_Set_Featured_Image extends MCP_Tool_Base {
94
95 public function get_name() {
96 return 'wordpress_set_featured_image';
97 }
98
99 public function get_description() {
100 return 'Set featured image for a post using an existing attachment ID';
101 }
102
103 public function get_input_schema() {
104 return [
105 'type' => 'object',
106 'properties' => [
107 'post_id' => [
108 'type' => 'integer',
109 'description' => 'Post ID',
110 ],
111 'attachment_id' => [
112 'type' => 'integer',
113 'description' => 'Attachment ID of the image',
114 ],
115 ],
116 'required' => ['post_id', 'attachment_id'],
117 ];
118 }
119
120 public function execute($params) {
121 $this->validate_params($params);
122 $this->require_capability('edit_posts');
123
124 $post_id = intval($params['post_id']);
125 $attachment_id = intval($params['attachment_id']);
126
127 // Validate post exists and user can edit it
128 $post = $this->verify_post_exists($post_id);
129
130 $this->check_post_permission($post_id);
131
132 // Validate attachment exists and is an image
133 $attachment = get_post($attachment_id);
134 if (!$attachment || $attachment->post_type !== 'attachment') {
135 throw new Exception(sprintf("Attachment not found: %d", absint($attachment_id)));
136 }
137
138 if (!wp_attachment_is_image($attachment_id)) {
139 throw new Exception('Attachment must be an image');
140 }
141
142 // Set featured image
143 $result = set_post_thumbnail($post_id, $attachment_id);
144
145 if (!$result) {
146 throw new Exception('Failed to set featured image');
147 }
148
149 return $this->success([
150 'post_id' => $post_id,
151 'post_title' => $post->post_title,
152 'attachment_id' => $attachment_id,
153 'image_url' => wp_get_attachment_url($attachment_id),
154 'message' => 'Featured image set successfully',
155 ]);
156 }
157 }
158
159 /**
160 * Upload Featured Image Tool
161 *
162 * Uploads a new image and sets it as featured image
163 */
164 class MCP_Tool_Upload_Featured_Image extends MCP_Tool_Base {
165
166 public function get_name() {
167 return 'wordpress_upload_featured_image';
168 }
169
170 public function get_description() {
171 return 'Upload a new image from URL and set it as featured image for a post';
172 }
173
174 public function get_input_schema() {
175 return [
176 'type' => 'object',
177 'properties' => [
178 'post_id' => [
179 'type' => 'integer',
180 'description' => 'Post ID',
181 ],
182 'image_url' => [
183 'type' => 'string',
184 'description' => 'URL of the image to upload',
185 ],
186 'title' => [
187 'type' => 'string',
188 'description' => 'Image title (optional, defaults to filename)',
189 ],
190 'alt_text' => [
191 'type' => 'string',
192 'description' => 'Image alt text (optional)',
193 ],
194 ],
195 'required' => ['post_id', 'image_url'],
196 ];
197 }
198
199 public function execute($params) {
200 $this->validate_params($params);
201 $this->require_capability('upload_files');
202
203 $post_id = intval($params['post_id']);
204 $image_url = esc_url_raw($params['image_url']);
205
206 // Validate post exists and user can edit it
207 $post = $this->verify_post_exists($post_id);
208
209 $this->check_post_permission($post_id);
210
211 // Validate image URL
212 if (empty($image_url)) {
213 throw new Exception('Invalid image URL');
214 }
215
216 // Download image
217 require_once ABSPATH . 'wp-admin/includes/media.php';
218 require_once ABSPATH . 'wp-admin/includes/file.php';
219 require_once ABSPATH . 'wp-admin/includes/image.php';
220
221 $tmp = download_url($image_url);
222
223 if (is_wp_error($tmp)) {
224 throw new Exception('Failed to download image: ' . $tmp->get_error_message());
225 }
226
227 // Prepare file array
228 $file_array = [
229 'name' => basename($image_url),
230 'tmp_name' => $tmp,
231 ];
232
233 // Upload to media library
234 $attachment_id = media_handle_sideload($file_array, $post_id);
235
236 if (is_wp_error($attachment_id)) {
237 @unlink($tmp);
238 throw new Exception('Failed to upload image: ' . $attachment_id->get_error_message());
239 }
240
241 // Set title if provided
242 if (isset($params['title'])) {
243 wp_update_post([
244 'ID' => $attachment_id,
245 'post_title' => sanitize_text_field($params['title']),
246 ]);
247 }
248
249 // Set alt text if provided
250 if (isset($params['alt_text'])) {
251 update_post_meta($attachment_id, '_wp_attachment_image_alt', sanitize_text_field($params['alt_text']));
252 }
253
254 // Set as featured image
255 set_post_thumbnail($post_id, $attachment_id);
256
257 return $this->success([
258 'post_id' => $post_id,
259 'post_title' => $post->post_title,
260 'attachment_id' => $attachment_id,
261 'image_url' => wp_get_attachment_url($attachment_id),
262 'message' => 'Image uploaded and set as featured image successfully',
263 ]);
264 }
265 }
266
267 /**
268 * Remove Featured Image Tool
269 *
270 * Removes featured image from a post
271 */
272 class MCP_Tool_Remove_Featured_Image extends MCP_Tool_Base {
273
274 public function get_name() {
275 return 'wordpress_remove_featured_image';
276 }
277
278 public function get_description() {
279 return 'Remove featured image from a post';
280 }
281
282 public function get_input_schema() {
283 return [
284 'type' => 'object',
285 'properties' => [
286 'post_id' => [
287 'type' => 'integer',
288 'description' => 'Post ID',
289 ],
290 ],
291 'required' => ['post_id'],
292 ];
293 }
294
295 public function execute($params) {
296 $this->validate_params($params);
297 $this->require_capability('edit_posts');
298
299 $post_id = intval($params['post_id']);
300
301 // Validate post exists and user can edit it
302 $post = $this->verify_post_exists($post_id);
303
304 $this->check_post_permission($post_id);
305
306 $thumbnail_id = get_post_thumbnail_id($post_id);
307
308 if (!$thumbnail_id) {
309 return $this->success([
310 'post_id' => $post_id,
311 'post_title' => $post->post_title,
312 'message' => 'Post has no featured image',
313 ]);
314 }
315
316 // Remove featured image
317 $result = delete_post_thumbnail($post_id);
318
319 if (!$result) {
320 throw new Exception('Failed to remove featured image');
321 }
322
323 return $this->success([
324 'post_id' => $post_id,
325 'post_title' => $post->post_title,
326 'message' => 'Featured image removed successfully',
327 ]);
328 }
329 }
330
331 /**
332 * List Media Tool
333 *
334 * Lists media library items
335 */
336 class MCP_Tool_List_Media extends MCP_Tool_Base {
337
338 public function get_name() {
339 return 'wordpress_list_media';
340 }
341
342 public function get_description() {
343 return 'List media library items with optional filters';
344 }
345
346 public function get_input_schema() {
347 return [
348 'type' => 'object',
349 'properties' => [
350 'mime_type' => [
351 'type' => 'string',
352 'description' => 'Filter by MIME type (e.g., image/jpeg, image/png, image)',
353 ],
354 'per_page' => [
355 'type' => 'integer',
356 'description' => 'Number of items per page (default: 20, max: 100)',
357 ],
358 'page' => [
359 'type' => 'integer',
360 'description' => 'Page number (default: 1)',
361 ],
362 'orderby' => [
363 'type' => 'string',
364 'enum' => ['date', 'title', 'name'],
365 'description' => 'Order by field (default: date)',
366 ],
367 'order' => [
368 'type' => 'string',
369 'enum' => ['ASC', 'DESC'],
370 'description' => 'Sort order (default: DESC)',
371 ],
372 ],
373 ];
374 }
375
376 public function execute($params) {
377 $this->validate_params($params);
378 $this->require_capability('upload_files');
379
380 $args = [
381 'post_type' => 'attachment',
382 'post_status' => 'inherit',
383 'posts_per_page' => isset($params['per_page']) ? min(intval($params['per_page']), 100) : 20,
384 'paged' => isset($params['page']) ? intval($params['page']) : 1,
385 'orderby' => isset($params['orderby']) ? sanitize_text_field($params['orderby']) : 'date',
386 'order' => isset($params['order']) ? sanitize_text_field($params['order']) : 'DESC',
387 ];
388
389 if (isset($params['mime_type'])) {
390 $args['post_mime_type'] = sanitize_text_field($params['mime_type']);
391 }
392
393 $query = new WP_Query($args);
394
395 $media_items = [];
396 foreach ($query->posts as $attachment) {
397 $metadata = wp_get_attachment_metadata($attachment->ID);
398
399 $media_items[] = [
400 'attachment_id' => $attachment->ID,
401 'url' => wp_get_attachment_url($attachment->ID),
402 'title' => $attachment->post_title,
403 'alt_text' => get_post_meta($attachment->ID, '_wp_attachment_image_alt', true),
404 'caption' => $attachment->post_excerpt,
405 'mime_type' => $attachment->post_mime_type,
406 'width' => isset($metadata['width']) ? $metadata['width'] : null,
407 'height' => isset($metadata['height']) ? $metadata['height'] : null,
408 'file_size' => isset($metadata['filesize']) ? $metadata['filesize'] : null,
409 'uploaded_at' => $attachment->post_date,
410 ];
411 }
412
413 return $this->success([
414 'total' => $query->found_posts,
415 'page' => $args['paged'],
416 'per_page' => $args['posts_per_page'],
417 'total_pages' => $query->max_num_pages,
418 'media' => $media_items,
419 ]);
420 }
421 }
422
423 /**
424 * Get Media Details Tool
425 *
426 * Gets detailed information about a media attachment
427 */
428 class MCP_Tool_Get_Media_Details extends MCP_Tool_Base {
429
430 public function get_name() {
431 return 'wordpress_get_media_details';
432 }
433
434 public function get_description() {
435 return 'Get detailed information about a media attachment';
436 }
437
438 public function get_input_schema() {
439 return [
440 'type' => 'object',
441 'properties' => [
442 'attachment_id' => [
443 'type' => 'integer',
444 'description' => 'Attachment ID',
445 ],
446 ],
447 'required' => ['attachment_id'],
448 ];
449 }
450
451 public function execute($params) {
452 $this->validate_params($params);
453 $this->require_capability('upload_files');
454
455 $attachment_id = intval($params['attachment_id']);
456
457 $attachment = get_post($attachment_id);
458 if (!$attachment || $attachment->post_type !== 'attachment') {
459 throw new Exception(sprintf("Attachment not found: %d", absint($attachment_id)));
460 }
461
462 $metadata = wp_get_attachment_metadata($attachment_id);
463 $file_path = get_attached_file($attachment_id);
464
465 $result = [
466 'attachment_id' => $attachment_id,
467 'url' => wp_get_attachment_url($attachment_id),
468 'title' => $attachment->post_title,
469 'alt_text' => get_post_meta($attachment_id, '_wp_attachment_image_alt', true),
470 'caption' => $attachment->post_excerpt,
471 'description' => $attachment->post_content,
472 'mime_type' => $attachment->post_mime_type,
473 'file_name' => basename($file_path),
474 'file_path' => $file_path,
475 'file_size' => file_exists($file_path) ? filesize($file_path) : null,
476 'uploaded_at' => $attachment->post_date,
477 'uploaded_by' => $attachment->post_author,
478 ];
479
480 // Add image-specific data
481 if (wp_attachment_is_image($attachment_id)) {
482 $result['width'] = isset($metadata['width']) ? $metadata['width'] : null;
483 $result['height'] = isset($metadata['height']) ? $metadata['height'] : null;
484 $result['sizes'] = isset($metadata['sizes']) ? $metadata['sizes'] : [];
485 }
486
487 return $this->success($result);
488 }
489 }
490