Files
advanced-mcp-plugin/includes/Extensions/Batch1.php
T

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];
}
}