PluginProbe
WDesignKit – AI Templates, Widget Builder & MCP Workflow / 2.7.0
WDesignKit – AI Templates, Widget Builder & MCP Workflow v2.7.0
2.7.0 2.6.6 2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.4.0 2.3.3 2.3.2 2.3.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 All 129 releases
wdesignkit / includes / abilities / widgets / wdesignkit-export-widget.php

wdesignkit-export-widget.php in WDesignKit – AI Templates, Widget Builder & MCP Workflow 2.7.0, at includes/abilities/widgets/wdesignkit-export-widget.php

141 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Ability: Export a local WDesignKit widget as a ZIP archive and return its download URL.
4 */
5
6 declare(strict_types=1);
7
8 if (!defined('ABSPATH')) {
9 exit();
10 }
11
12 wp_register_ability('wdesignkit/export-widget', [
13 'label' => __('Export WDesignKit Widget', 'wdesignkit'),
14 'description' => __(
15 'Packages a local widget\'s JSON config (and thumbnail image if present) into a ZIP archive inside the same builder directory and returns the download URL. The resulting .zip can be imported on another site via wdesignkit/import-widget.',
16 'wdesignkit',
17 ),
18 'category' => 'wdesignkit',
19 'input_schema' => [
20 'type' => 'object',
21 'properties' => [
22 'builder' => [
23 'type' => 'string',
24 'description' => 'Builder type the widget belongs to.',
25 'enum' => ['elementor', 'gutenberg', 'gutenberg_core', 'bricks'],
26 ],
27 'folder' => [
28 'type' => 'string',
29 'description' => 'Widget folder name (from wdesignkit/list-widgets).',
30 ],
31 ],
32 'required' => ['builder', 'folder'],
33 'additionalProperties' => false,
34 ],
35 'output_schema' => [
36 'type' => 'object',
37 'properties' => [
38 'success' => ['type' => 'boolean'],
39 'message' => ['type' => 'string'],
40 'download_url' => ['type' => 'string'],
41 'zip_path' => ['type' => 'string'],
42 ],
43 ],
44 'execute_callback' => 'wdesignkit_mcp_export_widget',
45 'permission_callback' => 'wdesignkit_mcp_permission_callback',
46 'meta' => [
47 'public' => true,
48 'show_in_rest' => true,
49 'mcp' => ['public' => true],
50 'annotations' => [
51 'instructions' => implode("\n", [
52 'Creates a .wdk ZIP archive (JSON + thumbnail) for the named widget.',
53 'Does NOT require cloud login — this is purely local.',
54 'Returns a direct download_url (within the WP uploads directory) the user can click to save the file.',
55 'Use wdesignkit/list-widgets to find the correct folder and builder values.',
56 ]),
57 'readonly' => false,
58 'destructive' => false,
59 'idempotent' => true,
60 ],
61 ],
62 ]);
63
64 function wdesignkit_mcp_export_widget(array $input): array {
65 // Timeout guard: local ZipArchive creation — purely filesystem, should be fast.
66 set_time_limit(30);
67
68 if (!defined('WDKIT_BUILDER_PATH') || !defined('WDKIT_SERVER_PATH')) {
69 return ['success' => false, 'message' => 'WDesignKit plugin is not active.'];
70 }
71
72 if (!class_exists('ZipArchive')) {
73 return ['success' => false, 'message' => 'PHP ZipArchive extension is not available on this server.'];
74 }
75
76 $builder = sanitize_text_field((string) ($input['builder'] ?? ''));
77 $folder = sanitize_file_name((string) ($input['folder'] ?? ''));
78
79 $allowed_builders = ['elementor', 'gutenberg', 'gutenberg_core', 'bricks'];
80 if (!in_array($builder, $allowed_builders, true)) {
81 return ['success' => false, 'message' => 'Invalid builder type.'];
82 }
83
84 $widget_dir = WDKIT_BUILDER_PATH . '/' . $builder . '/' . $folder;
85
86 if (!is_dir($widget_dir)) {
87 return ['success' => false, 'message' => "Widget folder not found: {$builder}/{$folder}"];
88 }
89
90 $real_widget = realpath($widget_dir);
91 $real_base = realpath(WDKIT_BUILDER_PATH);
92 if (!$real_widget || !$real_base || strpos($real_widget, $real_base . DIRECTORY_SEPARATOR) !== 0) {
93 return ['success' => false, 'message' => 'Invalid widget path.'];
94 }
95
96 $files = array_diff(@scandir($widget_dir) ?: [], ['.', '..']);
97
98 $json_file = null;
99 $img_file = null;
100 $img_ext = null;
101
102 foreach ($files as $f) {
103 $ext = pathinfo($f, PATHINFO_EXTENSION);
104 if ($ext === 'json') {
105 $json_file = $widget_dir . '/' . $f;
106 } elseif (in_array($ext, ['jpg', 'jpeg', 'png', 'webp'], true) && $img_file === null) {
107 $img_file = $widget_dir . '/' . $f;
108 $img_ext = $ext;
109 }
110 }
111
112 if (!$json_file || !file_exists($json_file)) {
113 return ['success' => false, 'message' => "No JSON config found in widget folder {$builder}/{$folder}"];
114 }
115
116 $archive_name = str_replace('-', '_', $folder) . '.zip';
117 $archive_path = WDKIT_BUILDER_PATH . '/' . $builder . '/' . $archive_name;
118
119 $zip = new ZipArchive();
120 if ($zip->open($archive_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
121 return ['success' => false, 'message' => 'Could not create ZIP archive. Check filesystem permissions.'];
122 }
123
124 $zip->addFile($json_file, str_replace('-', '_', $folder) . '.json');
125
126 if ($img_file && file_exists($img_file)) {
127 $zip->addFile($img_file, str_replace('-', '_', $folder) . '.' . $img_ext);
128 }
129
130 $zip->close();
131
132 $download_url = WDKIT_SERVER_PATH . '/' . $builder . '/' . $archive_name;
133
134 return [
135 'success' => true,
136 'message' => "Widget '{$folder}' packaged as {$archive_name}.",
137 'download_url' => $download_url,
138 'zip_path' => $archive_path,
139 ];
140 }
141