'object', 'properties' => $props]; if ($required) $schema['required'] = $required; return ['name' => $name, 'description' => $desc, 'scope' => $scope, 'handler' => 'AskTamMCP\\Extensions\\Batch13::' . $method, 'inputSchema' => $schema]; }; $registry->register($def('woodmart_list_widgets', 'List Woodmart Elementor widgets (wd_* and Woodmart WP widgets) with name and title. group = wd | wp | all (default all).', ['group' => ['type' => 'string', 'enum' => ['wd', 'wp', 'all']]], [], 'read', 'listWidgets')); $registry->register($def('woodmart_list_layouts', 'List Woodmart Layout Builder entries (woodmart_layout CPT: headers, footers, page/shop layouts). Returns id, title, status, and the meta keys present on each.', ['status' => ['type' => 'string'], 'per_page' => ['type' => 'integer', 'default' => 50]], [], 'read', 'listLayouts')); $registry->register($def('woodmart_list_html_blocks', 'List Woodmart HTML Blocks (cms_block CPT), each with its id, title, status, and ready-to-use shortcode.', ['status' => ['type' => 'string'], 'per_page' => ['type' => 'integer', 'default' => 50]], [], 'read', 'listBlocks')); $registry->register($def('woodmart_get_block', 'Get one Woodmart HTML Block or Layout by id: title, status, whether it is Elementor-built, a content/length summary, and its shortcode.', ['id' => ['type' => 'integer']], ['id'], 'read', 'getBlock')); $registry->register($def('woodmart_create_html_block', 'Create a Woodmart HTML Block (cms_block). Returns the new id and its [woodmart_html_block] shortcode. content is classic HTML/shortcode markup; status defaults to publish.', ['title' => ['type' => 'string'], 'content' => ['type' => 'string'], 'status' => ['type' => 'string', 'enum' => ['publish', 'draft']]], ['title'], 'write', 'createBlock')); } private static function isWoodmart(): bool { if (function_exists('woodmart_get_opt')) return true; $t = wp_get_theme(); $cands = [$t->get('TextDomain'), $t->get_template(), strtolower((string) $t->get('Name'))]; return in_array('woodmart', array_map('strtolower', array_filter($cands)), true); } public static function listWidgets(array $args): array { $group = isset($args['group']) ? (string) $args['group'] : 'all'; if (!class_exists('\Elementor\Plugin')) { throw new \RuntimeException('Elementor is not active; Woodmart Elementor widgets are unavailable.'); } $types = \Elementor\Plugin::instance()->widgets_manager->get_widget_types(); $out = []; foreach ($types as $name => $w) { $isWd = strpos($name, 'wd_') === 0 || strpos($name, 'woodmart') !== false; $isWpWd = strpos($name, 'wp-widget-woodmart') === 0; if (!$isWd && !$isWpWd) continue; $kind = $isWpWd ? 'wp' : 'wd'; if ($group !== 'all' && $group !== $kind) continue; $title = ''; if (is_object($w) && method_exists($w, 'get_title')) { try { $title = (string) $w->get_title(); } catch (\Throwable $e) {} } $out[] = ['name' => $name, 'title' => $title, 'kind' => $kind]; } usort($out, fn($a, $b) => strcmp($a['name'], $b['name'])); return ['count' => count($out), 'widgets' => $out]; } private static function queryCpt(string $cpt, array $args): array { $q = get_posts([ 'post_type' => $cpt, 'post_status' => isset($args['status']) ? (string) $args['status'] : ['publish', 'draft', 'pending', 'private'], 'numberposts' => (int) ($args['per_page'] ?? 50), 'orderby' => 'date', 'order' => 'DESC', ]); return is_array($q) ? $q : []; } public static function listLayouts(array $args): array { if (!post_type_exists('woodmart_layout')) { return ['supported' => false, 'note' => 'woodmart_layout CPT not registered on this site.', 'count' => 0, 'layouts' => []]; } $posts = self::queryCpt('woodmart_layout', $args); $out = []; foreach ($posts as $p) { $meta = get_post_meta($p->ID); $keys = array_values(array_filter(array_keys($meta), fn($k) => $k !== '' && strpos($k, '_edit') !== 0)); $out[] = ['id' => $p->ID, 'title' => $p->post_title, 'status' => $p->post_status, 'meta_keys' => $keys]; } return ['supported' => true, 'count' => count($out), 'layouts' => $out]; } public static function listBlocks(array $args): array { if (!post_type_exists('cms_block')) { return ['supported' => false, 'note' => 'cms_block CPT not registered on this site.', 'count' => 0, 'blocks' => []]; } $posts = self::queryCpt('cms_block', $args); $out = []; foreach ($posts as $p) { $out[] = [ 'id' => $p->ID, 'title' => $p->post_title, 'status' => $p->post_status, 'shortcode' => '[woodmart_html_block id="' . $p->ID . '"]', ]; } return ['supported' => true, 'count' => count($out), 'blocks' => $out]; } public static function getBlock(array $args): array { $id = (int) ($args['id'] ?? 0); $p = get_post($id); if (!$p) throw new \RuntimeException('Post not found: ' . $id); $isElementor = get_post_meta($id, '_elementor_edit_mode', true) === 'builder'; $content = (string) $p->post_content; $shortcode = $p->post_type === 'cms_block' ? '[woodmart_html_block id="' . $id . '"]' : null; return [ 'id' => $id, 'post_type' => $p->post_type, 'title' => $p->post_title, 'status' => $p->post_status, 'elementor_built' => $isElementor, 'content_length' => strlen($content), 'content_preview' => mb_substr(wp_strip_all_tags($content), 0, 300), 'shortcode' => $shortcode, ]; } public static function createBlock(array $args): array { if (!post_type_exists('cms_block')) { throw new \RuntimeException('cms_block CPT not registered; Woodmart HTML Blocks unavailable on this site.'); } $title = trim((string) ($args['title'] ?? '')); if ($title === '') throw new \RuntimeException('title required.'); $status = ($args['status'] ?? 'publish') === 'draft' ? 'draft' : 'publish'; $id = wp_insert_post([ 'post_type' => 'cms_block', 'post_title' => $title, 'post_content' => (string) ($args['content'] ?? ''), 'post_status' => $status, ], true); if (is_wp_error($id)) throw new \RuntimeException('Create failed: ' . $id->get_error_message()); return ['id' => $id, 'title' => $title, 'status' => $status, 'shortcode' => '[woodmart_html_block id="' . $id . '"]']; } }