36fae4ae22
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8t9GEyyLZbUQu26na1JQg
113 lines
5.9 KiB
PHP
113 lines
5.9 KiB
PHP
<?php
|
|
/**
|
|
* Batch 19 — WPBakery deep (Pro-equivalent, net-new).
|
|
*
|
|
* Extends b7 (detect/list/get/add/replace) with: saved templates, full
|
|
* shortcode-param mapping for one element, server-side render, raw content
|
|
* set, and a row/column wrapper builder. WPBakery stores page content as
|
|
* shortcodes in post_content. Guarded by WPB_VC_VERSION — inert unless
|
|
* WPBakery (js_composer) is active. GPL-2.0-or-later. See NOTICE.md.
|
|
*/
|
|
|
|
namespace AskTamMCP\Extensions;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class Batch19 {
|
|
|
|
public static function register($registry): void {
|
|
if (!defined('WPB_VC_VERSION')) return;
|
|
|
|
$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\\Batch19::' . $method, 'inputSchema' => $schema];
|
|
};
|
|
|
|
$registry->register($def('wpbakery_list_templates', 'List saved WPBakery templates (default templates option + Templatera CPT if present).',
|
|
[], [], 'read', 'listTemplates'));
|
|
|
|
$registry->register($def('wpbakery_get_mapping', 'Get the full parameter mapping of one WPBakery element (shortcode tag): its params, types, and defaults.',
|
|
['tag' => ['type' => 'string']], ['tag'], 'read', 'getMapping'));
|
|
|
|
$registry->register($def('wpbakery_render', 'Render a WPBakery shortcode string to HTML via do_shortcode, optionally in the context of a post.',
|
|
['shortcode' => ['type' => 'string'], 'post_id' => ['type' => 'integer']], ['shortcode'], 'read', 'render'));
|
|
|
|
$registry->register($def('wpbakery_set_content', 'Replace a post\'s WPBakery content (raw shortcode markup in post_content). Marks the post as WPBakery-edited. Use export/get first to back up.',
|
|
['post_id' => ['type' => 'integer'], 'content' => ['type' => 'string']], ['post_id', 'content'], 'write', 'setContent'));
|
|
|
|
$registry->register($def('wpbakery_wrap', 'Build a WPBakery row/column wrapper string around inner shortcode/HTML content. columns = number of equal columns (default 1).',
|
|
['content' => ['type' => 'string'], 'columns' => ['type' => 'integer', 'default' => 1], 'row_attrs' => ['type' => 'string']],
|
|
['content'], 'read', 'wrap'));
|
|
}
|
|
|
|
public static function listTemplates(array $args): array {
|
|
$out = [];
|
|
$defaults = get_option('wpb_js_templates', []);
|
|
if (is_array($defaults)) {
|
|
foreach ($defaults as $i => $t) {
|
|
$out[] = ['source' => 'wpbakery', 'index' => $i, 'name' => is_array($t) ? ($t['name'] ?? ('template_' . $i)) : (string) $t];
|
|
}
|
|
}
|
|
if (post_type_exists('templatera')) {
|
|
$tpls = get_posts(['post_type' => 'templatera', 'post_status' => 'publish', 'numberposts' => 100, 'fields' => 'ids']);
|
|
foreach ((array) $tpls as $id) $out[] = ['source' => 'templatera', 'id' => (int) $id, 'name' => get_the_title($id)];
|
|
}
|
|
return ['count' => count($out), 'templates' => $out];
|
|
}
|
|
|
|
public static function getMapping(array $args): array {
|
|
$tag = (string) ($args['tag'] ?? '');
|
|
if ($tag === '') throw new \RuntimeException('tag required.');
|
|
if (!class_exists('WPBMap')) throw new \RuntimeException('WPBMap unavailable; WPBakery mapping not loaded.');
|
|
if (method_exists('WPBMap', 'getShortCode')) {
|
|
$sc = \WPBMap::getShortCode($tag);
|
|
} else {
|
|
$all = \WPBMap::getAllShortCodes();
|
|
$sc = $all[$tag] ?? null;
|
|
}
|
|
if (!$sc) throw new \RuntimeException('Unknown WPBakery element: ' . $tag);
|
|
$params = [];
|
|
foreach ((array) ($sc['params'] ?? []) as $p) {
|
|
$params[] = ['param_name' => $p['param_name'] ?? '', 'type' => $p['type'] ?? '',
|
|
'heading' => $p['heading'] ?? '', 'value' => $p['value'] ?? null, 'std' => $p['std'] ?? null];
|
|
}
|
|
return ['tag' => $tag, 'name' => $sc['name'] ?? $tag, 'category' => $sc['category'] ?? '', 'params' => $params];
|
|
}
|
|
|
|
public static function render(array $args): array {
|
|
$code = (string) ($args['shortcode'] ?? '');
|
|
if ($code === '') throw new \RuntimeException('shortcode required.');
|
|
if (!empty($args['post_id'])) {
|
|
global $post;
|
|
$post = get_post((int) $args['post_id']);
|
|
if ($post) setup_postdata($post);
|
|
}
|
|
$html = do_shortcode($code);
|
|
if (!empty($args['post_id'])) wp_reset_postdata();
|
|
return ['rendered' => $html, 'length' => strlen($html)];
|
|
}
|
|
|
|
public static function setContent(array $args): array {
|
|
$id = (int) ($args['post_id'] ?? 0);
|
|
if (!get_post($id)) throw new \RuntimeException('Post not found: ' . $id);
|
|
$content = (string) ($args['content'] ?? '');
|
|
$res = wp_update_post(['ID' => $id, 'post_content' => $content], true);
|
|
if (is_wp_error($res)) throw new \RuntimeException('Update failed: ' . $res->get_error_message());
|
|
update_post_meta($id, '_wpb_vc_js_status', 'true'); // mark as WPBakery frontend-edited
|
|
return ['post_id' => $id, 'bytes' => strlen($content), 'updated' => true];
|
|
}
|
|
|
|
public static function wrap(array $args): array {
|
|
$content = (string) ($args['content'] ?? '');
|
|
$cols = max(1, (int) ($args['columns'] ?? 1));
|
|
$rowAttrs = isset($args['row_attrs']) ? ' ' . trim((string) $args['row_attrs']) : '';
|
|
$width = $cols === 1 ? '1/1' : '1/' . $cols;
|
|
$col = '[vc_column width="' . $width . '"]' . $content . '[/vc_column]';
|
|
$inner = str_repeat($col, $cols);
|
|
$markup = '[vc_row' . $rowAttrs . ']' . $inner . '[/vc_row]';
|
|
return ['markup' => $markup, 'columns' => $cols];
|
|
}
|
|
}
|