v2.0.0: ElementorTools — 30 tools, all unlocked, no pro gate
This commit is contained in:
@@ -0,0 +1,416 @@
|
||||
<?php
|
||||
namespace AskTamMCP\Elementor\Abilities;
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* All Elementor MCP tools — pages, layouts, widgets, templates, globals.
|
||||
* No Freemius, no pro gates. All tools always available when Elementor is active.
|
||||
*/
|
||||
class ElementorTools {
|
||||
|
||||
private \AskTamMCP\Elementor\Data\ElementorData $data;
|
||||
|
||||
public function __construct() {
|
||||
$this->data = new \AskTamMCP\Elementor\Data\ElementorData();
|
||||
}
|
||||
|
||||
public function getToolDefinitions(): array {
|
||||
return [
|
||||
$this->def('elementor_create_page','Create a new WordPress page with Elementor enabled. Returns post_id, edit_url, preview_url.',['title'=>['type'=>'string'],'status'=>['type'=>'string','default'=>'draft','enum'=>['draft','publish']],'post_type'=>['type'=>'string','default'=>'page'],'template'=>['type'=>'string'],'content'=>['type'=>'array','items'=>['type'=>'object']]],['title'],'write','createPage'),
|
||||
$this->def('elementor_get_page','Get the full Elementor element tree JSON for a page.',['post_id'=>['type'=>'integer']],['post_id'],'read','getPage'),
|
||||
$this->def('elementor_update_page_settings','Update page-level Elementor settings (background, padding, custom CSS, layout).',['post_id'=>['type'=>'integer'],'settings'=>['type'=>'object']],['post_id','settings'],'write','updatePageSettings'),
|
||||
$this->def('elementor_delete_page_content','Clear all Elementor content from a page, resetting it to blank.',['post_id'=>['type'=>'integer']],['post_id'],'write','deletePageContent'),
|
||||
$this->def('elementor_import_template','Import a JSON element structure into a page at an optional position.',['post_id'=>['type'=>'integer'],'template_json'=>['type'=>'array','items'=>['type'=>'object']],'position'=>['type'=>'integer']],['post_id','template_json'],'write','importTemplate'),
|
||||
$this->def('elementor_export_page','Export a page\'s full Elementor data as JSON.',['post_id'=>['type'=>'integer']],['post_id'],'read','exportPage'),
|
||||
$this->def('elementor_add_container','Add a flex or grid container to an Elementor page. Use parent_id for nesting, position for insertion index (-1 = append). Settings: flex_direction, flex_wrap, flex_justify_content, flex_align_items, gap, padding, background_color, border_border, etc.',['post_id'=>['type'=>'integer'],'parent_id'=>['type'=>'string'],'position'=>['type'=>'integer'],'settings'=>['type'=>'object']],['post_id'],'write','addContainer'),
|
||||
$this->def('elementor_update_container','Update settings on an existing container element.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string'],'settings'=>['type'=>'object']],['post_id','element_id'],'write','updateContainer'),
|
||||
$this->def('elementor_update_element','Update settings on any Elementor element by ID.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string'],'settings'=>['type'=>'object'],'merge'=>['type'=>'boolean','default'=>true]],['post_id','element_id','settings'],'write','updateElement'),
|
||||
$this->def('elementor_remove_element','Remove any element (container or widget) from a page by element ID.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string']],['post_id','element_id'],'write','removeElement'),
|
||||
$this->def('elementor_duplicate_element','Duplicate an element (and its children) within the same page.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string'],'position'=>['type'=>'integer']],['post_id','element_id'],'write','duplicateElement'),
|
||||
$this->def('elementor_move_element','Move an element to a different parent or position within the page.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string'],'target_parent_id'=>['type'=>'string'],'position'=>['type'=>'integer']],['post_id','element_id'],'write','moveElement'),
|
||||
$this->def('elementor_add_widget','Add any Elementor widget to a container. widget_type: heading, text-editor, image, button, video, icon, divider, spacer, google_maps, html, shortcode, accordion, tabs, toggle, icon-list, counter, progress, testimonial, alert, social-icons, star-rating, image-box, icon-box, basic-gallery, image-carousel, reviews, posts, nav-menu, search-form, woocommerce-product-images, etc.',['post_id'=>['type'=>'integer'],'container_id'=>['type'=>'string'],'widget_type'=>['type'=>'string'],'settings'=>['type'=>'object'],'position'=>['type'=>'integer']],['post_id','container_id','widget_type'],'write','addWidget'),
|
||||
$this->def('elementor_update_widget','Update an existing widget\'s settings.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string'],'settings'=>['type'=>'object'],'merge'=>['type'=>'boolean','default'=>true]],['post_id','element_id','settings'],'write','updateWidget'),
|
||||
$this->def('elementor_add_heading','Add a heading widget.',['post_id'=>['type'=>'integer'],'container_id'=>['type'=>'string'],'text'=>['type'=>'string'],'tag'=>['type'=>'string','default'=>'h2'],'align'=>['type'=>'string'],'color'=>['type'=>'string'],'size'=>['type'=>'string'],'position'=>['type'=>'integer']],['post_id','container_id','text'],'write','addHeading'),
|
||||
$this->def('elementor_add_text','Add a text editor widget.',['post_id'=>['type'=>'integer'],'container_id'=>['type'=>'string'],'content'=>['type'=>'string'],'position'=>['type'=>'integer']],['post_id','container_id','content'],'write','addText'),
|
||||
$this->def('elementor_add_image','Add an image widget.',['post_id'=>['type'=>'integer'],'container_id'=>['type'=>'string'],'url'=>['type'=>'string'],'alt'=>['type'=>'string'],'link'=>['type'=>'string'],'position'=>['type'=>'integer']],['post_id','container_id','url'],'write','addImage'),
|
||||
$this->def('elementor_add_button','Add a button widget.',['post_id'=>['type'=>'integer'],'container_id'=>['type'=>'string'],'text'=>['type'=>'string'],'url'=>['type'=>'string'],'type'=>['type'=>'string','default'=>'default'],'align'=>['type'=>'string'],'position'=>['type'=>'integer']],['post_id','container_id','text','url'],'write','addButton'),
|
||||
$this->def('elementor_save_as_template','Save the current page content as a reusable Elementor template.',['post_id'=>['type'=>'integer'],'template_name'=>['type'=>'string'],'type'=>['type'=>'string','default'=>'page']],['post_id','template_name'],'write','saveAsTemplate'),
|
||||
$this->def('elementor_apply_template','Apply a saved template to a page (replaces existing content).',['post_id'=>['type'=>'integer'],'template_id'=>['type'=>'integer']],['post_id','template_id'],'write','applyTemplate'),
|
||||
$this->def('elementor_list_templates','List saved Elementor templates.',['type'=>['type'=>'string'],'per_page'=>['type'=>'integer','default'=>50]],[],'read','listTemplates'),
|
||||
$this->def('elementor_get_global_colors','Get Elementor global color palette.',[],[],'read','getGlobalColors'),
|
||||
$this->def('elementor_set_global_color','Add or update a color in the Elementor global palette.',['id'=>['type'=>'string'],'title'=>['type'=>'string'],'value'=>['type'=>'string']],['title','value'],'write','setGlobalColor'),
|
||||
$this->def('elementor_get_global_fonts','Get Elementor global font groups.',[],[],'read','getGlobalFonts'),
|
||||
$this->def('elementor_get_kit_settings','Get Elementor Site Kit settings (colors, fonts, button styles, form styles, etc.).',[],[],'read','getKitSettings'),
|
||||
$this->def('elementor_update_kit_settings','Update Elementor Site Kit settings.',['settings'=>['type'=>'object']],['settings'],'write','updateKitSettings'),
|
||||
$this->def('elementor_list_widgets','List all registered Elementor widget types.',[],[],'read','listWidgets'),
|
||||
$this->def('elementor_get_element','Get a single element by ID from a page\'s element tree.',['post_id'=>['type'=>'integer'],'element_id'=>['type'=>'string']],['post_id','element_id'],'read','getElement'),
|
||||
$this->def('elementor_clone_page','Duplicate an existing Elementor page as a new draft.',['post_id'=>['type'=>'integer'],'title'=>['type'=>'string']],['post_id'],'write','clonePage'),
|
||||
$this->def('elementor_replace_text','Replace all occurrences of a text string across all widgets in a page.',['post_id'=>['type'=>'integer'],'search'=>['type'=>'string'],'replace'=>['type'=>'string'],'case_sensitive'=>['type'=>'boolean','default'=>false]],['post_id','search','replace'],'write','replaceText'),
|
||||
$this->def('elementor_get_page_outline','Get a simplified structural outline of an Elementor page (containers + widget types).',['post_id'=>['type'=>'integer']],['post_id'],'read','getPageOutline'),
|
||||
];
|
||||
}
|
||||
|
||||
private function def(string $name, string $desc, array $props, array $required, string $scope, string $method): array {
|
||||
$schema = ['type'=>'object','properties'=>$props];
|
||||
if ($required) $schema['required'] = $required;
|
||||
return ['name'=>$name,'description'=>$desc,'scope'=>$scope,'handler'=>[$this,$method],'inputSchema'=>$schema];
|
||||
}
|
||||
|
||||
public function createPage(array $args): array {
|
||||
$title = sanitize_text_field($args['title'] ?? '');
|
||||
$status = sanitize_key($args['status'] ?? 'draft');
|
||||
$post_type = sanitize_key($args['post_type'] ?? 'page');
|
||||
if (empty($title)) throw new \RuntimeException('title is required.');
|
||||
$post_id = wp_insert_post(['post_title'=>$title,'post_status'=>$status,'post_type'=>$post_type,'meta_input'=>['_elementor_edit_mode'=>'builder','_elementor_template_type'=>'wp-'.$post_type]], true);
|
||||
if (is_wp_error($post_id)) throw new \RuntimeException($post_id->get_error_message());
|
||||
if (!empty($args['template'])) update_post_meta($post_id, '_wp_page_template', sanitize_text_field($args['template']));
|
||||
$content = !empty($args['content']) && is_array($args['content']) ? $args['content'] : [];
|
||||
$this->data->save_page_data($post_id, $content);
|
||||
return ['post_id'=>$post_id,'title'=>$title,'edit_url'=>admin_url("post.php?post={$post_id}&action=elementor"),'preview_url'=>get_permalink($post_id)?:''];
|
||||
}
|
||||
|
||||
public function getPage(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
return ['post_id'=>$post_id,'elements'=>$data,'count'=>$this->data->count_elements($data)];
|
||||
}
|
||||
|
||||
public function updatePageSettings(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$result = $this->data->save_page_settings($post_id, $args['settings'] ?? []);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'post_id'=>$post_id];
|
||||
}
|
||||
|
||||
public function deletePageContent(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$result = $this->data->save_page_data($post_id, []);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true];
|
||||
}
|
||||
|
||||
public function importTemplate(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$template_json = $args['template_json'] ?? [];
|
||||
$position = (int)($args['position'] ?? -1);
|
||||
if (empty($template_json)) throw new \RuntimeException('template_json is required.');
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$template_json = $this->data->reassign_ids($template_json);
|
||||
$count = $this->data->count_elements($template_json);
|
||||
if ($position < 0 || $position >= count($data)) $data = array_merge($data, $template_json);
|
||||
else array_splice($data, $position, 0, $template_json);
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'elements_count'=>$count];
|
||||
}
|
||||
|
||||
public function exportPage(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
return ['json'=>$data,'count'=>$this->data->count_elements($data)];
|
||||
}
|
||||
|
||||
public function addContainer(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$parent_id = $args['parent_id'] ?? null;
|
||||
$position = (int)($args['position'] ?? -1);
|
||||
$settings = $args['settings'] ?? [];
|
||||
foreach (['justify_content'=>'flex_justify_content','align_items'=>'flex_align_items','align_content'=>'flex_align_content'] as $from=>$to) {
|
||||
if (isset($settings[$from]) && !isset($settings[$to])) { $settings[$to] = $settings[$from]; unset($settings[$from]); }
|
||||
}
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$element_id = $this->data->generate_id();
|
||||
$container = ['id'=>$element_id,'elType'=>'container','settings'=>array_merge(['flex_direction'=>'row'],$settings),'elements'=>[],'isInner'=>false];
|
||||
if ($parent_id) {
|
||||
$data = $this->insertIntoParent($data, $parent_id, $container, $position);
|
||||
} else {
|
||||
if ($position < 0 || $position >= count($data)) $data[] = $container;
|
||||
else array_splice($data, $position, 0, [$container]);
|
||||
}
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['element_id'=>$element_id,'post_id'=>$post_id];
|
||||
}
|
||||
|
||||
public function updateContainer(array $args): array { return $this->updateElement($args); }
|
||||
|
||||
public function updateElement(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$element_id = $args['element_id'] ?? '';
|
||||
$settings = $args['settings'] ?? [];
|
||||
$merge = (bool)($args['merge'] ?? true);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$data = $this->data->update_element_settings($data, $element_id, $settings, $merge);
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'post_id'=>$post_id,'element_id'=>$element_id];
|
||||
}
|
||||
|
||||
public function removeElement(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$element_id = $args['element_id'] ?? '';
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$data = $this->data->remove_element($data, $element_id);
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'removed_id'=>$element_id];
|
||||
}
|
||||
|
||||
public function duplicateElement(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$element_id = $args['element_id'] ?? '';
|
||||
$position = (int)($args['position'] ?? -1);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$element = $this->data->find_element($data, $element_id);
|
||||
if (!$element) throw new \RuntimeException("Element not found: {$element_id}");
|
||||
$clone = $this->data->reassign_ids([$element])[0];
|
||||
if ($position < 0 || $position >= count($data)) $data[] = $clone;
|
||||
else array_splice($data, $position, 0, [$clone]);
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'new_element_id'=>$clone['id']];
|
||||
}
|
||||
|
||||
public function moveElement(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$element_id = $args['element_id'] ?? '';
|
||||
$target_parent_id = $args['target_parent_id'] ?? null;
|
||||
$position = (int)($args['position'] ?? -1);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$element = $this->data->find_element($data, $element_id);
|
||||
if (!$element) throw new \RuntimeException("Element not found: {$element_id}");
|
||||
$data = $this->data->remove_element($data, $element_id);
|
||||
if ($target_parent_id) {
|
||||
$data = $this->insertIntoParent($data, $target_parent_id, $element, $position);
|
||||
} else {
|
||||
if ($position < 0 || $position >= count($data)) $data[] = $element;
|
||||
else array_splice($data, $position, 0, [$element]);
|
||||
}
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'element_id'=>$element_id];
|
||||
}
|
||||
|
||||
public function addWidget(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$container_id = $args['container_id'] ?? '';
|
||||
$widget_type = $args['widget_type'] ?? '';
|
||||
$settings = $args['settings'] ?? [];
|
||||
$position = (int)($args['position'] ?? -1);
|
||||
if (empty($widget_type)) throw new \RuntimeException('widget_type is required.');
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$element_id = $this->data->generate_id();
|
||||
$widget = ['id'=>$element_id,'elType'=>'widget','widgetType'=>$widget_type,'settings'=>$settings,'elements'=>[]];
|
||||
$data = $this->insertIntoParent($data, $container_id, $widget, $position);
|
||||
$result = $this->data->save_page_data($post_id, $data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['element_id'=>$element_id,'post_id'=>$post_id,'widget_type'=>$widget_type];
|
||||
}
|
||||
|
||||
public function updateWidget(array $args): array { return $this->updateElement($args); }
|
||||
|
||||
public function addHeading(array $args): array {
|
||||
$settings = ['title'=>$args['text']??''];
|
||||
if (!empty($args['tag'])) $settings['header_size'] = $args['tag'];
|
||||
if (!empty($args['align'])) $settings['align'] = $args['align'];
|
||||
if (!empty($args['color'])) $settings['title_color'] = $args['color'];
|
||||
if (!empty($args['size'])) $settings['typography_font_size'] = ['size'=>(int)$args['size'],'unit'=>'px'];
|
||||
return $this->addWidget(array_merge($args,['widget_type'=>'heading','settings'=>$settings]));
|
||||
}
|
||||
|
||||
public function addText(array $args): array {
|
||||
return $this->addWidget(array_merge($args,['widget_type'=>'text-editor','settings'=>['editor'=>$args['content']??'']]));
|
||||
}
|
||||
|
||||
public function addImage(array $args): array {
|
||||
$settings = ['image'=>['url'=>$args['url']??''],'alt'=>$args['alt']??''];
|
||||
if (!empty($args['link'])) $settings['link'] = ['url'=>$args['link'],'is_external'=>false];
|
||||
return $this->addWidget(array_merge($args,['widget_type'=>'image','settings'=>$settings]));
|
||||
}
|
||||
|
||||
public function addButton(array $args): array {
|
||||
$settings = ['text'=>$args['text']??'','link'=>['url'=>$args['url']??''],'button_type'=>$args['type']??'default'];
|
||||
if (!empty($args['align'])) $settings['align'] = $args['align'];
|
||||
return $this->addWidget(array_merge($args,['widget_type'=>'button','settings'=>$settings]));
|
||||
}
|
||||
|
||||
public function saveAsTemplate(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$name = sanitize_text_field($args['template_name'] ?? '');
|
||||
$type = sanitize_key($args['type'] ?? 'page');
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$template_id = wp_insert_post(['post_title'=>$name,'post_type'=>'elementor_library','post_status'=>'publish','meta_input'=>['_elementor_data'=>wp_json_encode($data),'_elementor_template_type'=>$type,'_elementor_edit_mode'=>'builder']],true);
|
||||
if (is_wp_error($template_id)) throw new \RuntimeException($template_id->get_error_message());
|
||||
wp_set_object_terms($template_id, $type, 'elementor_library_type');
|
||||
return ['success'=>true,'template_id'=>$template_id,'name'=>$name];
|
||||
}
|
||||
|
||||
public function applyTemplate(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$template_id = (int)($args['template_id'] ?? 0);
|
||||
$template_data = get_post_meta($template_id, '_elementor_data', true);
|
||||
if (empty($template_data)) throw new \RuntimeException("Template {$template_id} has no Elementor data.");
|
||||
$elements = $this->data->reassign_ids(json_decode($template_data, true) ?: []);
|
||||
$result = $this->data->save_page_data($post_id, $elements);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'post_id'=>$post_id,'template_id'=>$template_id,'elements_count'=>$this->data->count_elements($elements)];
|
||||
}
|
||||
|
||||
public function listTemplates(array $args): array {
|
||||
$query_args = ['post_type'=>'elementor_library','post_status'=>'publish','posts_per_page'=>(int)($args['per_page']??50),'orderby'=>'title','order'=>'ASC'];
|
||||
if (!empty($args['type'])) $query_args['tax_query'] = [['taxonomy'=>'elementor_library_type','field'=>'slug','terms'=>[$args['type']]]];
|
||||
$templates = get_posts($query_args);
|
||||
return ['templates'=>array_map(fn($t)=>['id'=>$t->ID,'title'=>$t->post_title,'type'=>get_post_meta($t->ID,'_elementor_template_type',true),'date'=>$t->post_date],$templates),'total'=>count($templates)];
|
||||
}
|
||||
|
||||
public function getGlobalColors(array $args): array {
|
||||
$kit = $this->getActiveKit();
|
||||
if (!$kit) return ['colors'=>[],'note'=>'No active Elementor kit found.'];
|
||||
$settings = get_post_meta($kit->ID, '_elementor_page_settings', true);
|
||||
$palette = [];
|
||||
if (is_array($settings) && !empty($settings['system_colors'])) {
|
||||
foreach ($settings['system_colors'] as $color) {
|
||||
$palette[] = ['id'=>$color['_id']??'','title'=>$color['title']??'','value'=>$color['color']??''];
|
||||
}
|
||||
}
|
||||
return ['colors'=>$palette,'kit_id'=>$kit->ID];
|
||||
}
|
||||
|
||||
public function setGlobalColor(array $args): array {
|
||||
$kit = $this->getActiveKit();
|
||||
if (!$kit) throw new \RuntimeException('No active Elementor kit found.');
|
||||
$settings = get_post_meta($kit->ID, '_elementor_page_settings', true) ?: [];
|
||||
$colors = $settings['system_colors'] ?? [];
|
||||
$id = $args['id'] ?? ('color_'.substr(md5($args['title']??uniqid()),0,6));
|
||||
$found = false;
|
||||
foreach ($colors as &$color) {
|
||||
if (($color['_id']??'') === $id) { $color['title']=$args['title']??$color['title']; $color['color']=$args['value']??$color['color']; $found=true; break; }
|
||||
}
|
||||
if (!$found) $colors[] = ['_id'=>$id,'title'=>$args['title']??$id,'color'=>$args['value']??''];
|
||||
$settings['system_colors'] = $colors;
|
||||
update_post_meta($kit->ID, '_elementor_page_settings', $settings);
|
||||
return ['success'=>true,'id'=>$id];
|
||||
}
|
||||
|
||||
public function getGlobalFonts(array $args): array {
|
||||
$kit = $this->getActiveKit();
|
||||
if (!$kit) return ['fonts'=>[]];
|
||||
$settings = get_post_meta($kit->ID, '_elementor_page_settings', true) ?: [];
|
||||
$fonts = [];
|
||||
if (!empty($settings['system_typography'])) {
|
||||
foreach ($settings['system_typography'] as $font) {
|
||||
$fonts[] = ['id'=>$font['_id']??'','title'=>$font['title']??'','family'=>$font['typography_font_family']??''];
|
||||
}
|
||||
}
|
||||
return ['fonts'=>$fonts,'kit_id'=>$kit->ID];
|
||||
}
|
||||
|
||||
public function getKitSettings(array $args): array {
|
||||
$kit = $this->getActiveKit();
|
||||
if (!$kit) return ['settings'=>[],'note'=>'No active Elementor kit.'];
|
||||
return ['settings'=>get_post_meta($kit->ID,'_elementor_page_settings',true)?:[],'kit_id'=>$kit->ID];
|
||||
}
|
||||
|
||||
public function updateKitSettings(array $args): array {
|
||||
$kit = $this->getActiveKit();
|
||||
if (!$kit) throw new \RuntimeException('No active Elementor kit found.');
|
||||
$current = get_post_meta($kit->ID, '_elementor_page_settings', true) ?: [];
|
||||
update_post_meta($kit->ID, '_elementor_page_settings', array_merge($current, $args['settings'] ?? []));
|
||||
return ['success'=>true,'kit_id'=>$kit->ID];
|
||||
}
|
||||
|
||||
public function listWidgets(array $args): array {
|
||||
$widgets = $this->data->get_registered_widgets();
|
||||
return ['widgets'=>$widgets,'total'=>count($widgets)];
|
||||
}
|
||||
|
||||
public function getElement(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$element_id = $args['element_id'] ?? '';
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$element = $this->data->find_element($data, $element_id);
|
||||
if (!$element) throw new \RuntimeException("Element not found: {$element_id}");
|
||||
return ['element'=>$element];
|
||||
}
|
||||
|
||||
public function clonePage(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$orig = get_post($post_id);
|
||||
if (!$orig) throw new \RuntimeException("Post not found: {$post_id}");
|
||||
$title = $args['title'] ?? ('Copy of '.$orig->post_title);
|
||||
$new_id = wp_insert_post(['post_title'=>$title,'post_type'=>$orig->post_type,'post_status'=>'draft','meta_input'=>['_elementor_edit_mode'=>'builder','_elementor_template_type'=>get_post_meta($post_id,'_elementor_template_type',true)]],true);
|
||||
if (is_wp_error($new_id)) throw new \RuntimeException($new_id->get_error_message());
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (!is_wp_error($data)) $this->data->save_page_data($new_id, $this->data->reassign_ids($data));
|
||||
return ['post_id'=>$new_id,'title'=>$title,'edit_url'=>admin_url("post.php?post={$new_id}&action=elementor")];
|
||||
}
|
||||
|
||||
public function replaceText(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$search = $args['search'] ?? '';
|
||||
$replace = $args['replace'] ?? '';
|
||||
$case_sensitive = (bool)($args['case_sensitive'] ?? false);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
$encoded = wp_json_encode($data);
|
||||
$count = 0;
|
||||
$new = $case_sensitive ? str_replace($search, $replace, $encoded, $count) : str_ireplace($search, $replace, $encoded, $count);
|
||||
$new_data = json_decode($new, true);
|
||||
if (!is_array($new_data)) throw new \RuntimeException('Failed to re-encode data after replacement.');
|
||||
$result = $this->data->save_page_data($post_id, $new_data);
|
||||
if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message());
|
||||
return ['success'=>true,'replacements'=>$count];
|
||||
}
|
||||
|
||||
public function getPageOutline(array $args): array {
|
||||
$post_id = (int)($args['post_id'] ?? 0);
|
||||
$data = $this->data->get_page_data($post_id);
|
||||
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
||||
return ['post_id'=>$post_id,'outline'=>$this->buildOutline($data)];
|
||||
}
|
||||
|
||||
private function buildOutline(array $elements, int $depth = 0): array {
|
||||
$result = [];
|
||||
foreach ($elements as $el) {
|
||||
$entry = ['id'=>$el['id']??'','type'=>$el['elType']??'','depth'=>$depth];
|
||||
if (($el['elType']??'') === 'widget') $entry['widget_type'] = $el['widgetType']??'';
|
||||
if (!empty($el['elements'])) $entry['children'] = $this->buildOutline($el['elements'], $depth+1);
|
||||
$result[] = $entry;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function insertIntoParent(array $elements, string $parent_id, array $element, int $position): array {
|
||||
foreach ($elements as &$el) {
|
||||
if (($el['id'] ?? '') === $parent_id) {
|
||||
$children = $el['elements'] ?? [];
|
||||
if ($position < 0 || $position >= count($children)) $children[] = $element;
|
||||
else array_splice($children, $position, 0, [$element]);
|
||||
$el['elements'] = $children;
|
||||
return $elements;
|
||||
}
|
||||
if (!empty($el['elements'])) {
|
||||
$el['elements'] = $this->insertIntoParent($el['elements'], $parent_id, $element, $position);
|
||||
}
|
||||
}
|
||||
return $elements;
|
||||
}
|
||||
|
||||
private function getActiveKit(): ?\WP_Post {
|
||||
if (!class_exists('\Elementor\Plugin')) return null;
|
||||
$kit_id = get_option('elementor_active_kit');
|
||||
if (!$kit_id) return null;
|
||||
return get_post((int)$kit_id) ?: null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user