PluginProbe
WDesignKit – AI Templates, Widget Builder & MCP Workflow / 2.7.1
WDesignKit – AI Templates, Widget Builder & MCP Workflow v2.7.1
2.7.1 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 All 130 releases
← All changes | includes/abilities/widgets/wdesignkit-widget-preview.php +22 -6 2.5.5 → 2.7.1 View file →
@@ -9,12 +9,12 @@
9 9 exit();
10 10 }
11 11
12 12 wp_register_ability('wdesignkit/widget-preview', [
13 - 'label' => __('WDesignKit Widget Preview', 'sprout-mcp'),
13 + 'label' => __('WDesignKit Widget Preview', 'wdesignkit'),
14 14 'description' => __(
15 15 'Creates (or reuses) a temporary WordPress page to preview a widget and returns its editor URL. For Elementor widgets the page opens in the Elementor canvas editor. For Gutenberg/gutenberg_core widgets the page opens in the block editor. No page is created for builder types other than those two.',
16 - 'sprout-mcp',
16 + 'wdesignkit',
17 17 ),
18 18 'category' => 'wdesignkit',
19 19 'input_schema' => [
20 20 'type' => 'object',
@@ -45,10 +45,11 @@
45 45 'page_id' => ['type' => 'integer'],
46 46 ],
47 47 ],
48 48 'execute_callback' => 'wdesignkit_mcp_widget_preview',
49 - 'permission_callback' => 'sprout_mcp_permission_callback',
49 + 'permission_callback' => 'wdesignkit_mcp_permission_callback',
50 50 'meta' => [
51 + 'public' => true,
51 52 'show_in_rest' => true,
52 53 'mcp' => ['public' => true],
53 54 'annotations' => [
54 55 'instructions' => implode("\n", [
@@ -81,10 +82,13 @@
81 82 if ($folder === '') {
82 83 return ['success' => false, 'message' => 'folder is required.'];
83 84 }
84 85
85 - // Normalise gutenberg_core → gutenberg for filesystem lookup
86 - $fs_builder = ($builder === 'gutenberg_core') ? 'gutenberg' : $builder;
86 + // gutenberg_core widgets live under their own gutenberg_core/ directory — create-widget,
87 + // list-widgets, and the gutenberg_core loader all use the raw builder name. Resolve the
88 + // folder under the actual builder dir; collapsing gutenberg_core → gutenberg made the
89 + // lookup fail with "Widget folder not found" for every Core Gutenberg widget. (bug: 86d3rc7nf)
90 + $fs_builder = $builder;
87 91
88 92 $widget_dir = WDKIT_BUILDER_PATH . '/' . $fs_builder . '/' . $folder;
89 93
90 94 if (!is_dir($widget_dir)) {
@@ -90,8 +94,15 @@
90 94 if (!is_dir($widget_dir)) {
91 95 return ['success' => false, 'message' => "Widget folder not found: {$fs_builder}/{$folder}"];
92 96 }
93 97
98 + // Realpath validation — ensure we're still inside WDKIT_BUILDER_PATH.
99 + $real_widget = realpath($widget_dir);
100 + $real_base = realpath(WDKIT_BUILDER_PATH);
101 + if (!$real_widget || !$real_base || strpos($real_widget, $real_base . DIRECTORY_SEPARATOR) !== 0) {
102 + return ['success' => false, 'message' => 'Invalid widget path.'];
103 + }
104 +
94 105 // Read widget metadata from JSON
95 106 $widget_name = $folder;
96 107 $widget_id = '';
97 108 $files = array_diff(@scandir($widget_dir) ?: [], ['.', '..']);
@@ -187,9 +198,14 @@
187 198 return ['success' => false, 'message' => 'Failed to create preview page.'];
188 199 }
189 200
190 201 if (function_exists('serialize_blocks')) {
191 - $blocks = [['blockName' => 'wdkit/' . $page_data, 'attrs' => [], 'innerHTML' => '', 'innerContent' => []]];
202 + // Generated Gutenberg widgets register their block as wdkit/wb-<widget_id>
203 + // (see gutenberg_file.js / gutenberg_core_file.js). Ensure the wb- prefix so
204 + // the inserted block matches the registered name and renders instead of
205 + // showing WordPress's "invalid content" recovery error.
206 + $block_suffix = (strpos($page_data, 'wb-') === 0) ? $page_data : 'wb-' . $page_data;
207 + $blocks = [['blockName' => 'wdkit/' . $block_suffix, 'attrs' => [], 'innerHTML' => '', 'innerContent' => []]];
192 208 $updated_content = serialize_blocks($blocks);
193 209 wp_update_post(['ID' => $page_id, 'post_content' => $updated_content]);
194 210 }
195 211