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 / workspace / wdesignkit-workspace-items.php

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

427 lines 17.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Abilities: Add, remove, copy, and move templates, widgets, and code snippets within WDesignKit workspaces.
4 */
5
6 declare(strict_types=1);
7
8 if (!defined('ABSPATH')) {
9 exit();
10 }
11
12 wp_register_ability('wdesignkit/manage-workspace-template', [
13 'label' => __('Manage Template in WDesignKit Workspace', 'wdesignkit'),
14 'description' => __(
15 'Adds, removes, copies, or moves a cloud template within WDesignKit workspaces. Covers "Add Template to Workspace", "Remove Template from Workspace", "Copy / Move Template in Workspace", and "Delete Template from Workspace". Requires cloud login.',
16 'wdesignkit',
17 ),
18 'category' => 'wdesignkit',
19 'input_schema' => [
20 'type' => 'object',
21 'properties' => [
22 'action' => [
23 'type' => 'string',
24 'description' => '"add" to add template to workspace, "remove" to remove it, "copy" to copy to another workspace, "move" to move to another workspace.',
25 'enum' => ['add', 'remove', 'copy', 'move'],
26 ],
27 'template_id' => [
28 'type' => 'integer',
29 'description' => 'Cloud template ID to operate on.',
30 ],
31 'wid' => [
32 'type' => 'integer',
33 'description' => 'Target workspace ID (for add/copy/move: the destination workspace; for remove: the workspace to remove from).',
34 ],
35 'current_wid' => [
36 'type' => 'integer',
37 'description' => 'Source workspace ID. Required for copy and move actions.',
38 ],
39 ],
40 'required' => ['action', 'template_id', 'wid'],
41 'additionalProperties' => false,
42 ],
43 'output_schema' => [
44 'type' => 'object',
45 'properties' => [
46 'success' => ['type' => 'boolean'],
47 'message' => ['type' => 'string'],
48 'response' => ['type' => ['object', 'array']],
49 ],
50 ],
51 'execute_callback' => 'wdesignkit_mcp_manage_workspace_template',
52 'permission_callback' => 'wdesignkit_mcp_permission_callback',
53 'meta' => [
54 'public' => true,
55 'show_in_rest' => true,
56 'mcp' => ['public' => true],
57 'annotations' => [
58 'instructions' => implode("\n", [
59 'Manages templates inside WDesignKit workspaces. Requires cloud login.',
60 'action "add": adds template_id to workspace wid.',
61 'action "remove": removes template_id from workspace wid (template still exists in cloud).',
62 'action "copy": copies template_id from current_wid to wid (current_wid required).',
63 'action "move": moves template_id from current_wid to wid (current_wid required).',
64 'Get template_id and wid from wdesignkit/get-workspace-data.',
65 ]),
66 'readonly' => false,
67 'destructive' => false,
68 'idempotent' => false,
69 ],
70 ],
71 ]);
72
73 wp_register_ability('wdesignkit/manage-workspace-widget', [
74 'label' => __('Manage Widget in WDesignKit Workspace', 'wdesignkit'),
75 'description' => __(
76 'Adds, removes, copies, or moves a cloud widget within WDesignKit workspaces. Covers "Copy / Move Widget in Workspace" and "Delete Widget from Workspace". Requires cloud login.',
77 'wdesignkit',
78 ),
79 'category' => 'wdesignkit',
80 'input_schema' => [
81 'type' => 'object',
82 'properties' => [
83 'action' => [
84 'type' => 'string',
85 'description' => '"add" to add widget to workspace, "remove" to remove it, "copy" to copy to another workspace, "move" to move to another workspace.',
86 'enum' => ['add', 'remove', 'copy', 'move'],
87 ],
88 'widget_id' => [
89 'type' => 'integer',
90 'description' => 'Cloud widget ID to operate on.',
91 ],
92 'wid' => [
93 'type' => 'integer',
94 'description' => 'Target workspace ID (for copy/move: the destination; for remove: the workspace to remove from).',
95 ],
96 'current_wid' => [
97 'type' => 'integer',
98 'description' => 'Source workspace ID. Required for copy and move actions.',
99 ],
100 ],
101 'required' => ['action', 'widget_id', 'wid'],
102 'additionalProperties' => false,
103 ],
104 'output_schema' => [
105 'type' => 'object',
106 'properties' => [
107 'success' => ['type' => 'boolean'],
108 'message' => ['type' => 'string'],
109 'response' => ['type' => ['object', 'array']],
110 ],
111 ],
112 'execute_callback' => 'wdesignkit_mcp_manage_workspace_widget',
113 'permission_callback' => 'wdesignkit_mcp_permission_callback',
114 'meta' => [
115 'public' => true,
116 'show_in_rest' => true,
117 'mcp' => ['public' => true],
118 'annotations' => [
119 'instructions' => implode("\n", [
120 'Manages widgets inside WDesignKit workspaces. Requires cloud login.',
121 'action "add": adds widget_id to workspace wid.',
122 'action "remove": removes widget_id from workspace wid (widget still exists in cloud).',
123 'action "copy": copies widget_id from current_wid to wid (current_wid required).',
124 'action "move": moves widget_id from current_wid to wid (current_wid required).',
125 'Get widget_id and wid from wdesignkit/get-workspace-data.',
126 ]),
127 'readonly' => false,
128 'destructive' => false,
129 'idempotent' => false,
130 ],
131 ],
132 ]);
133
134 wp_register_ability('wdesignkit/manage-workspace-snippet', [
135 'label' => __('Manage Code Snippet in WDesignKit Workspace', 'wdesignkit'),
136 'description' => __(
137 'Adds, removes, copies, or moves a cloud code snippet within WDesignKit workspaces. Covers "Copy / Move Code Snippet in Workspace". Requires cloud login.',
138 'wdesignkit',
139 ),
140 'category' => 'wdesignkit',
141 'input_schema' => [
142 'type' => 'object',
143 'properties' => [
144 'action' => [
145 'type' => 'string',
146 'description' => '"add" to add snippet to workspace, "remove" to remove it, "copy" to copy to another workspace, "move" to move to another workspace.',
147 'enum' => ['add', 'remove', 'copy', 'move'],
148 ],
149 'snippet_id' => [
150 'type' => 'string',
151 'description' => 'Cloud snippet ID to operate on (from wdesignkit/get-workspace-data code_snippets).',
152 ],
153 'wid' => [
154 'type' => 'integer',
155 'description' => 'Target workspace ID (for copy/move: the destination; for remove: the workspace to remove from).',
156 ],
157 'current_wid' => [
158 'type' => 'integer',
159 'description' => 'Source workspace ID. Required for copy and move actions.',
160 ],
161 ],
162 'required' => ['action', 'snippet_id', 'wid'],
163 'additionalProperties' => false,
164 ],
165 'output_schema' => [
166 'type' => 'object',
167 'properties' => [
168 'success' => ['type' => 'boolean'],
169 'message' => ['type' => 'string'],
170 'response' => ['type' => ['object', 'array']],
171 ],
172 ],
173 'execute_callback' => 'wdesignkit_mcp_manage_workspace_snippet',
174 'permission_callback' => 'wdesignkit_mcp_permission_callback',
175 'meta' => [
176 'public' => true,
177 'show_in_rest' => true,
178 'mcp' => ['public' => true],
179 'annotations' => [
180 'instructions' => implode("\n", [
181 'Manages code snippets inside WDesignKit workspaces. Requires cloud login.',
182 'action "add": adds snippet_id to workspace wid.',
183 'action "remove": removes snippet_id from workspace wid (snippet still exists in cloud).',
184 'action "copy": copies snippet_id from current_wid to wid (current_wid required).',
185 'action "move": moves snippet_id from current_wid to wid (current_wid required).',
186 'Get snippet_id and wid from wdesignkit/get-workspace-data.',
187 ]),
188 'readonly' => false,
189 'destructive' => false,
190 'idempotent' => false,
191 ],
192 ],
193 ]);
194
195 function wdesignkit_mcp_manage_workspace_template(array $input): array {
196 // Timeout guard: cloud workspace management call uses the default timeout.
197 set_time_limit(90);
198
199 if (!defined('WDKIT_SERVER_API_URL')) {
200 return ['success' => false, 'message' => 'WDesignKit plugin is not active.'];
201 }
202
203 $auth = wdesignkit_mcp_template_get_auth();
204 if (empty($auth['logged_in'])) {
205 return ['success' => false, 'message' => $auth['message'] ?? 'Not logged in to WDesignKit cloud.'];
206 }
207
208 $action = sanitize_text_field((string) ($input['action'] ?? ''));
209 $template_id = (int) ($input['template_id'] ?? 0);
210 $wid = (int) ($input['wid'] ?? 0);
211 $current_wid = (int) ($input['current_wid'] ?? 0);
212
213 if ($action === '' || $template_id <= 0 || $wid <= 0) {
214 return ['success' => false, 'message' => 'action, template_id, and wid are required.'];
215 }
216
217 // Server ManageWorkspace wstype values — 'copy' is the server's handler for
218 // adding a template to a workspace. 'temp_add' is not implemented server-side.
219 $wstype_map = [
220 'add' => 'copy',
221 'remove' => 'temp_remove',
222 'copy' => 'copy',
223 'move' => 'move',
224 ];
225
226 $wstype = $wstype_map[$action] ?? '';
227 if ($wstype === '') {
228 return ['success' => false, 'message' => "Unknown action '{$action}'."];
229 }
230
231 if (in_array($action, ['copy', 'move'], true) && $current_wid <= 0) {
232 return ['success' => false, 'message' => "current_wid is required for action '{$action}'."];
233 }
234
235 $args = [
236 'token' => $auth['token'],
237 'template_id' => $template_id,
238 'wid' => $wid,
239 'wstype' => $wstype,
240 ];
241
242 if ($current_wid > 0) {
243 $args['current_wid'] = $current_wid;
244 }
245
246 // Template workspace uses JSON POST (mirrors WDesignKit_Data_Query::get_data)
247 $cloud = wdesignkit_mcp_template_cloud_call('manage_workspace', $args, 'json');
248
249 // The cloud returns HTTP 200 with an empty body for template operations on
250 // invalid/non-owned IDs or when the account lacks workspace permissions.
251 // An empty body cannot confirm the operation succeeded; surface the ambiguity.
252 if (array_key_exists('raw', $cloud) && ($cloud['raw'] === '' || $cloud['raw'] === null)) {
253 return [
254 'success' => false,
255 'message' => "Cloud returned no confirmation for template {$action}. The workspace ID or template ID may be invalid, or the operation is not permitted. Verify with wdesignkit/get-workspace-data.",
256 'response' => $cloud,
257 ];
258 }
259
260 return [
261 'success' => !empty($cloud['success']),
262 'message' => $cloud['message'] ?? $cloud['massage'] ?? ($cloud['success'] ? "Template {$action} succeeded." : "Failed to {$action} template."),
263 'response' => $cloud,
264 ];
265 }
266
267 function wdesignkit_mcp_manage_workspace_widget(array $input): array {
268 // Timeout guard: cloud workspace management call uses the default timeout.
269 set_time_limit(90);
270
271 if (!defined('WDKIT_SERVER_API_URL')) {
272 return ['success' => false, 'message' => 'WDesignKit plugin is not active.'];
273 }
274
275 $auth = wdesignkit_mcp_template_get_auth();
276 if (empty($auth['logged_in'])) {
277 return ['success' => false, 'message' => $auth['message'] ?? 'Not logged in to WDesignKit cloud.'];
278 }
279
280 $action = sanitize_text_field((string) ($input['action'] ?? ''));
281 $widget_id = (int) ($input['widget_id'] ?? 0);
282 $wid = (int) ($input['wid'] ?? 0);
283 $current_wid = (int) ($input['current_wid'] ?? 0);
284
285 if ($action === '' || $widget_id <= 0 || $wid <= 0) {
286 return ['success' => false, 'message' => 'action, widget_id, and wid are required.'];
287 }
288
289 // Widget workspace wstype values — 'wd-copy' is the server's handler for
290 // adding a widget to a workspace. 'wd_ws_add' is not implemented server-side.
291 // 'copy' goes to 'ws-wd-copy', the workspace-to-workspace handler: unlike
292 // 'wd-copy' it validates the source workspace and that the widget is in it,
293 // which is what this ability's copy contract (current_wid required) promises.
294 $wstype_map = [
295 'add' => 'wd-copy',
296 'remove' => 'wd_ws_remove',
297 'copy' => 'ws-wd-copy',
298 'move' => 'wd-move',
299 ];
300
301 $wstype = $wstype_map[$action] ?? '';
302 if ($wstype === '') {
303 return ['success' => false, 'message' => "Unknown action '{$action}'."];
304 }
305
306 if (in_array($action, ['copy', 'move'], true) && $current_wid <= 0) {
307 return ['success' => false, 'message' => "current_wid is required for action '{$action}'."];
308 }
309
310 $args = [
311 'token' => $auth['token'],
312 'widget_id' => $widget_id,
313 'wid' => $wid,
314 'wstype' => $wstype,
315 ];
316
317 if ($current_wid > 0) {
318 $args['current_wid'] = $current_wid;
319 }
320
321 // Widget workspace uses form-encoded POST (mirrors wdkit_manage_widget_workspace() in class-api.php)
322 $cloud = wdesignkit_mcp_template_cloud_call('manage_workspace', $args, 'form');
323
324 // The cloud returns HTTP 200 with an empty body for widget-add operations on
325 // invalid/non-owned IDs — it does not validate the widget_id or wid before
326 // returning. An empty body cannot confirm the operation succeeded; treat it as
327 // an unverifiable result and surface the ambiguity to the caller.
328 if (array_key_exists('raw', $cloud) && ($cloud['raw'] === '' || $cloud['raw'] === null)) {
329 return [
330 'success' => false,
331 'message' => "Cloud returned no confirmation for widget {$action}. The workspace ID or widget ID may be invalid, or the operation is not permitted. Verify with wdesignkit/get-workspace-data.",
332 'response' => $cloud,
333 ];
334 }
335
336 // The cloud splits its reason across message ("Permission Denied") and description
337 // ("You are unable to perform this action since you are a subscriber."). Returning
338 // the message alone leaves the caller with no idea what to change — join both.
339 $message = $cloud['message'] ?? $cloud['massage'] ?? ($cloud['success'] ? "Widget {$action} succeeded." : "Failed to {$action} widget.");
340 $description = isset($cloud['description']) && is_string($cloud['description']) ? trim($cloud['description']) : '';
341
342 if ($description !== '' && stripos($message, $description) === false) {
343 $message = rtrim($message, '.! ') . ' — ' . $description;
344 }
345
346 return [
347 'success' => !empty($cloud['success']),
348 'message' => $message,
349 'response' => $cloud,
350 ];
351 }
352
353 function wdesignkit_mcp_manage_workspace_snippet(array $input): array {
354 // Timeout guard: cloud workspace management call uses the default timeout.
355 set_time_limit(90);
356
357 if (!defined('WDKIT_SERVER_API_URL')) {
358 return ['success' => false, 'message' => 'WDesignKit plugin is not active.'];
359 }
360
361 $auth = wdesignkit_mcp_template_get_auth();
362 if (empty($auth['logged_in'])) {
363 return ['success' => false, 'message' => $auth['message'] ?? 'Not logged in to WDesignKit cloud.'];
364 }
365
366 $action = sanitize_text_field((string) ($input['action'] ?? ''));
367 $snippet_id = sanitize_text_field((string) ($input['snippet_id'] ?? ''));
368 $wid = (int) ($input['wid'] ?? 0);
369 $current_wid = (int) ($input['current_wid'] ?? 0);
370
371 if ($action === '' || $snippet_id === '' || $wid <= 0) {
372 return ['success' => false, 'message' => 'action, snippet_id, and wid are required.'];
373 }
374
375 // The cloud resolves snippet_id as an integer row id — fail fast on anything else
376 // instead of sending a request that can only come back as "Snippet Not Found".
377 if (!ctype_digit($snippet_id) || (int) $snippet_id <= 0) {
378 return ['success' => false, 'message' => 'snippet_id must be a numeric cloud snippet ID (from wdesignkit/get-workspace-data code_snippets).'];
379 }
380
381 $wstype_map = [
382 'add' => 'snippet_add',
383 'remove' => 'snippet_remove',
384 'copy' => 'snippet_copy',
385 'move' => 'snippet_move',
386 ];
387
388 $wstype = $wstype_map[$action] ?? '';
389 if ($wstype === '') {
390 return ['success' => false, 'message' => "Unknown action '{$action}'."];
391 }
392
393 if (in_array($action, ['copy', 'move'], true) && $current_wid <= 0) {
394 return ['success' => false, 'message' => "current_wid is required for action '{$action}'."];
395 }
396
397 $args = [
398 'token' => $auth['token'],
399 'snippet_id' => $snippet_id,
400 'wid' => $wid,
401 'wstype' => $wstype,
402 ];
403
404 if ($current_wid > 0) {
405 $args['current_wid'] = $current_wid;
406 }
407
408 $cloud = wdesignkit_mcp_template_cloud_call('manage_workspace', $args, 'form');
409
410 // Safety net for older cloud builds: before the snippet_* wstype handlers existed
411 // server-side, manage_workspace fell through and answered HTTP 200 with an empty
412 // body. An empty body cannot confirm the operation succeeded; surface the ambiguity.
413 if (array_key_exists('raw', $cloud) && ($cloud['raw'] === '' || $cloud['raw'] === null)) {
414 return [
415 'success' => false,
416 'message' => "Cloud returned no confirmation for snippet {$action}. The workspace ID or snippet ID may be invalid, or the operation is not permitted. Verify with wdesignkit/get-workspace-data.",
417 'response' => $cloud,
418 ];
419 }
420
421 return [
422 'success' => !empty($cloud['success']),
423 'message' => $cloud['message'] ?? $cloud['massage'] ?? ($cloud['success'] ? "Snippet {$action} succeeded." : "Failed to {$action} snippet."),
424 'response' => $cloud,
425 ];
426 }
427