'object', 'properties' => $props]; if ($required) $schema['required'] = $required; return ['name' => $name, 'description' => $desc, 'scope' => $scope, 'handler' => 'AskTamMCP\\Extensions\\Batch9::' . $method, 'inputSchema' => $schema]; }; $registry->register($def('export_elementor_page', 'Export a page\'s Elementor data: parsed elements, page settings, and template. Use as a backup or to clone into another page.', ['post_id' => ['type' => 'integer']], ['post_id'], 'read', 'exportPage')); $registry->register($def('import_elementor_page', 'Import Elementor data into a target post. Provide elementor_data (JSON string or array). regenerate_ids=true gives every element a fresh id.', ['post_id' => ['type' => 'integer'], 'elementor_data' => ['type' => ['array', 'string']], 'regenerate_ids' => ['type' => 'boolean', 'default' => false]], ['post_id', 'elementor_data'], 'write', 'importPage')); $registry->register($def('export_global_styles', 'Export the active Elementor kit\'s global styles (colors, typography, and other page settings).', [], [], 'read', 'exportStyles')); $registry->register($def('import_global_styles', 'Write global styles into the active Elementor kit. merge=true (default) merges into existing settings; false replaces them.', ['settings' => ['type' => 'object'], 'merge' => ['type' => 'boolean', 'default' => true]], ['settings'], 'write', 'importStyles')); $registry->register($def('duplicate_elementor_page', 'Duplicate a page including its Elementor data into a new post (default draft).', ['source_id' => ['type' => 'integer'], 'title' => ['type' => 'string'], 'status' => ['type' => 'string', 'default' => 'draft']], ['source_id'], 'write', 'duplicatePage')); } private static function regenerateIds(array $elements): array { foreach ($elements as &$el) { if (isset($el['id'])) $el['id'] = substr(md5(uniqid('', true)), 0, 7); if (!empty($el['elements']) && is_array($el['elements'])) $el['elements'] = self::regenerateIds($el['elements']); } unset($el); return $elements; } public static function exportPage(array $args): array { $id = (int) ($args['post_id'] ?? 0); $post = $id ? get_post($id) : null; if (!$post) throw new \RuntimeException("Post not found: {$id}"); $raw = get_post_meta($id, '_elementor_data', true); $data = is_string($raw) && $raw !== '' ? json_decode($raw, true) : []; return [ 'post_id' => $id, 'title' => $post->post_title, 'template' => get_post_meta($id, '_wp_page_template', true), 'page_settings' => get_post_meta($id, '_elementor_page_settings', true) ?: [], 'elementor_data' => is_array($data) ? $data : [], 'element_count' => is_array($data) ? count($data) : 0, ]; } public static function importPage(array $args): array { $id = (int) ($args['post_id'] ?? 0); $post = $id ? get_post($id) : null; if (!$post) throw new \RuntimeException("Post not found: {$id}"); $data = $args['elementor_data'] ?? null; if (is_string($data)) $data = json_decode($data, true); if (!is_array($data)) throw new \RuntimeException('elementor_data must be a JSON array/string of elements.'); if (!empty($args['regenerate_ids'])) $data = self::regenerateIds($data); $json = wp_json_encode($data); update_post_meta($id, '_elementor_data', wp_slash($json)); update_post_meta($id, '_elementor_edit_mode', 'builder'); if (defined('ELEMENTOR_VERSION')) update_post_meta($id, '_elementor_version', ELEMENTOR_VERSION); if (class_exists('\Elementor\Plugin')) { try { \Elementor\Plugin::$instance->files_manager->clear_cache(); } catch (\Throwable $e) {} } return ['post_id' => $id, 'elements_imported' => count($data), 'regenerated_ids' => !empty($args['regenerate_ids'])]; } private static function activeKit(): int { return (int) get_option('elementor_active_kit', 0); } public static function exportStyles(array $args): array { $kit = self::activeKit(); if (!$kit) throw new \RuntimeException('No active Elementor kit.'); return ['kit_id' => $kit, 'settings' => get_post_meta($kit, '_elementor_page_settings', true) ?: []]; } public static function importStyles(array $args): array { $kit = self::activeKit(); if (!$kit) throw new \RuntimeException('No active Elementor kit.'); $incoming = is_array($args['settings'] ?? null) ? $args['settings'] : []; if (!$incoming) throw new \RuntimeException('settings (object) is required.'); $merge = !isset($args['merge']) || !empty($args['merge']); $current = get_post_meta($kit, '_elementor_page_settings', true) ?: []; $new = $merge ? array_merge((array) $current, $incoming) : $incoming; update_post_meta($kit, '_elementor_page_settings', $new); return ['kit_id' => $kit, 'merged' => $merge, 'keys_written' => array_keys($incoming)]; } public static function duplicatePage(array $args): array { $src = (int) ($args['source_id'] ?? 0); $post = $src ? get_post($src) : null; if (!$post) throw new \RuntimeException("Source post not found: {$src}"); $title = sanitize_text_field((string) ($args['title'] ?? ($post->post_title . ' (copy)'))); $status = in_array(($args['status'] ?? 'draft'), ['draft', 'publish', 'pending', 'private'], true) ? $args['status'] : 'draft'; $new = wp_insert_post([ 'post_title' => $title, 'post_status' => $status, 'post_type' => $post->post_type, 'post_content' => $post->post_content, ], true); if (is_wp_error($new)) throw new \RuntimeException($new->get_error_message()); foreach (['_elementor_data', '_elementor_page_settings', '_wp_page_template', '_elementor_edit_mode', '_elementor_version'] as $k) { $v = get_post_meta($src, $k, true); if ($v !== '') update_post_meta($new, $k, is_string($v) ? wp_slash($v) : $v); } return ['new_post_id' => (int) $new, 'source_id' => $src, 'title' => $title, 'status' => $status]; } }