149 lines
7.6 KiB
PHP
149 lines
7.6 KiB
PHP
<?php
|
|
/**
|
|
* Batch 1 — Elementor completeness gaps (net-new tools).
|
|
*
|
|
* Part of the full-parity merge (elementor-mcp + wordpress-mcp). These are
|
|
* capabilities the plugin did not already expose. Registered via the plugin's
|
|
* own `asktam_mcp_register_tools` extension hook — no existing file is modified.
|
|
*
|
|
* License: GPL-2.0-or-later. Behaviour modelled on the GPL-2.0 elementor-mcp
|
|
* project; implemented independently against the Elementor data layer. See NOTICE.md.
|
|
*/
|
|
|
|
namespace AskTamMCP\Extensions;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class Batch1 {
|
|
|
|
public static function register($registry): void {
|
|
if (!defined('ELEMENTOR_VERSION')) return; // Elementor-only batch; stay inert otherwise.
|
|
|
|
$def = function (string $name, string $desc, array $props, array $required, string $scope, string $method) {
|
|
$schema = ['type' => 'object', 'properties' => $props];
|
|
if ($required) $schema['required'] = $required;
|
|
return ['name' => $name, 'description' => $desc, 'scope' => $scope,
|
|
'handler' => 'AskTamMCP\\Extensions\\Batch1::' . $method, 'inputSchema' => $schema];
|
|
};
|
|
|
|
$registry->register($def('elementor_add_section',
|
|
'Add a classic Elementor section (legacy row layout). Optional parent_id nests it; settings accepts gap, content_width, background_color, padding, etc.',
|
|
['post_id' => ['type' => 'integer'], 'parent_id' => ['type' => 'string'], 'position' => ['type' => 'integer'], 'settings' => ['type' => 'object']],
|
|
['post_id'], 'write', 'addSection'));
|
|
|
|
$registry->register($def('elementor_add_column',
|
|
'Add a column inside a section. size is the column width in percent (1-100, default 100).',
|
|
['post_id' => ['type' => 'integer'], 'section_id' => ['type' => 'string'], 'size' => ['type' => 'integer', 'default' => 100], 'position' => ['type' => 'integer'], 'settings' => ['type' => 'object']],
|
|
['post_id', 'section_id'], 'write', 'addColumn'));
|
|
|
|
$registry->register($def('elementor_set_global_font',
|
|
'Add or update a typography entry in the Elementor global font palette (system_typography).',
|
|
['id' => ['type' => 'string'], 'title' => ['type' => 'string'], 'font_family' => ['type' => 'string'], 'font_weight' => ['type' => 'string']],
|
|
['title', 'font_family'], 'write', 'setGlobalFont'));
|
|
|
|
$registry->register($def('elementor_delete_global_color',
|
|
'Remove a colour from the Elementor global palette by its id.',
|
|
['id' => ['type' => 'string']],
|
|
['id'], 'write', 'deleteGlobalColor'));
|
|
|
|
$registry->register($def('elementor_delete_template',
|
|
'Delete a saved Elementor library template permanently.',
|
|
['template_id' => ['type' => 'integer']],
|
|
['template_id'], 'write', 'deleteTemplate'));
|
|
}
|
|
|
|
private static function data(): \AskTamMCP\Elementor\Data\ElementorData {
|
|
return new \AskTamMCP\Elementor\Data\ElementorData();
|
|
}
|
|
|
|
private static function activeKitId(): int {
|
|
return (int) get_option('elementor_active_kit', 0);
|
|
}
|
|
|
|
public static function addSection(array $args): array {
|
|
$post_id = (int) ($args['post_id'] ?? 0);
|
|
$parent_id = $args['parent_id'] ?? '';
|
|
$position = (int) ($args['position'] ?? -1);
|
|
$settings = is_array($args['settings'] ?? null) ? $args['settings'] : [];
|
|
$ed = self::data();
|
|
$data = $ed->get_page_data($post_id);
|
|
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
|
$id = $ed->generate_id();
|
|
$section = ['id' => $id, 'elType' => 'section', 'settings' => $settings, 'elements' => [], 'isInner' => !empty($parent_id)];
|
|
$ed->insert_element($data, $parent_id, $section, $position);
|
|
$saved = $ed->save_page_data($post_id, $data);
|
|
if (is_wp_error($saved)) throw new \RuntimeException($saved->get_error_message());
|
|
return ['element_id' => $id, 'post_id' => $post_id];
|
|
}
|
|
|
|
public static function addColumn(array $args): array {
|
|
$post_id = (int) ($args['post_id'] ?? 0);
|
|
$section_id = $args['section_id'] ?? '';
|
|
$size = max(1, min(100, (int) ($args['size'] ?? 100)));
|
|
$position = (int) ($args['position'] ?? -1);
|
|
$settings = is_array($args['settings'] ?? null) ? $args['settings'] : [];
|
|
if (empty($section_id)) throw new \RuntimeException('section_id is required.');
|
|
$ed = self::data();
|
|
$data = $ed->get_page_data($post_id);
|
|
if (is_wp_error($data)) throw new \RuntimeException($data->get_error_message());
|
|
$id = $ed->generate_id();
|
|
$column = ['id' => $id, 'elType' => 'column',
|
|
'settings' => array_merge(['_column_size' => $size, '_inline_size' => $size], $settings),
|
|
'elements' => [], 'isInner' => false];
|
|
$ok = $ed->insert_element($data, $section_id, $column, $position);
|
|
if (!$ok) throw new \RuntimeException("Section not found: {$section_id}");
|
|
$saved = $ed->save_page_data($post_id, $data);
|
|
if (is_wp_error($saved)) throw new \RuntimeException($saved->get_error_message());
|
|
return ['element_id' => $id, 'post_id' => $post_id, 'section_id' => $section_id];
|
|
}
|
|
|
|
public static function setGlobalFont(array $args): array {
|
|
$kit = self::activeKitId();
|
|
if (!$kit) throw new \RuntimeException('No active Elementor kit found.');
|
|
$s = get_post_meta($kit, '_elementor_page_settings', true) ?: [];
|
|
$fonts = $s['system_typography'] ?? [];
|
|
$id = $args['id'] ?? ('font_' . substr(md5(($args['title'] ?? '') . uniqid()), 0, 6));
|
|
$entry = [
|
|
'_id' => $id,
|
|
'title' => $args['title'] ?? $id,
|
|
'typography_typography' => 'custom',
|
|
'typography_font_family' => $args['font_family'] ?? '',
|
|
'typography_font_weight' => $args['font_weight'] ?? '',
|
|
];
|
|
$found = false;
|
|
foreach ($fonts as &$f) {
|
|
if (($f['_id'] ?? '') === $id) { $f = array_merge($f, $entry); $found = true; break; }
|
|
}
|
|
unset($f);
|
|
if (!$found) $fonts[] = $entry;
|
|
$s['system_typography'] = $fonts;
|
|
update_post_meta($kit, '_elementor_page_settings', $s);
|
|
return ['success' => true, 'id' => $id, 'kit_id' => $kit];
|
|
}
|
|
|
|
public static function deleteGlobalColor(array $args): array {
|
|
$kit = self::activeKitId();
|
|
if (!$kit) throw new \RuntimeException('No active Elementor kit found.');
|
|
$id = (string) ($args['id'] ?? '');
|
|
$s = get_post_meta($kit, '_elementor_page_settings', true) ?: [];
|
|
$colors = $s['system_colors'] ?? [];
|
|
$before = count($colors);
|
|
$colors = array_values(array_filter($colors, fn($c) => ($c['_id'] ?? '') !== $id));
|
|
if (count($colors) === $before) throw new \RuntimeException("Global colour not found: {$id}");
|
|
$s['system_colors'] = $colors;
|
|
update_post_meta($kit, '_elementor_page_settings', $s);
|
|
return ['success' => true, 'deleted_id' => $id, 'kit_id' => $kit];
|
|
}
|
|
|
|
public static function deleteTemplate(array $args): array {
|
|
$tid = (int) ($args['template_id'] ?? 0);
|
|
$p = $tid ? get_post($tid) : null;
|
|
if (!$p || $p->post_type !== 'elementor_library') {
|
|
throw new \RuntimeException("Not an Elementor template: {$tid}");
|
|
}
|
|
$res = wp_delete_post($tid, true);
|
|
if (!$res) throw new \RuntimeException("Failed to delete template {$tid}");
|
|
return ['success' => true, 'deleted_template_id' => $tid];
|
|
}
|
|
}
|