diff --git a/includes/Extensions/Batch12.php b/includes/Extensions/Batch12.php new file mode 100644 index 0000000..38c37d2 --- /dev/null +++ b/includes/Extensions/Batch12.php @@ -0,0 +1,143 @@ + 'object', 'properties' => $props]; + if ($required) $schema['required'] = $required; + return ['name' => $name, 'description' => $desc, 'scope' => $scope, + 'handler' => 'AskTamMCP\\Extensions\\Batch12::' . $method, 'inputSchema' => $schema]; + }; + + $registry->register($def('woodmart_detect', 'Report whether the Woodmart theme is active and its version.', + [], [], 'read', 'detect')); + + $registry->register($def('woodmart_get_option', 'Read one Woodmart theme option by key.', + ['key' => ['type' => 'string']], ['key'], 'read', 'getOpt')); + + $registry->register($def('woodmart_list_options', 'List Woodmart theme option keys (and value types), optionally filtered by prefix.', + ['prefix' => ['type' => 'string']], [], 'read', 'listOpts')); + + $registry->register($def('woodmart_set_option', 'Set one Woodmart theme option. value is parsed as JSON when valid (so arrays/booleans/numbers work), otherwise stored as a string. The prior value is auto-backed-up for woodmart_restore_option.', + ['key' => ['type' => 'string'], 'value' => ['type' => 'string']], ['key', 'value'], 'write', 'setOpt')); + + $registry->register($def('woodmart_restore_option', 'Restore one Woodmart option to the value saved before the last woodmart_set_option (or remove it if there was none).', + ['key' => ['type' => 'string']], ['key'], 'write', 'restoreOpt')); + } + + private static function isWoodmart(): bool { + if (function_exists('woodmart_get_opt')) return true; + $t = wp_get_theme(); + $cands = [$t->get('TextDomain'), $t->get_template(), strtolower((string) $t->get('Name'))]; + return in_array('woodmart', array_map('strtolower', array_filter($cands)), true); + } + + private static function store(): array { + $o = get_option(self::OPT, []); + return is_array($o) ? $o : []; + } + + private static function typeOf($v): string { + if (is_array($v)) return 'array'; + if (is_bool($v)) return 'bool'; + if (is_int($v)) return 'int'; + if (is_float($v)) return 'float'; + return 'string'; + } + + public static function detect(array $args): array { + $t = wp_get_theme(); + $ver = defined('WOODMART_VERSION') ? WOODMART_VERSION : (string) $t->get('Version'); + return [ + 'active' => self::isWoodmart(), + 'name' => (string) $t->get('Name'), + 'version' => $ver, + 'option_store' => self::OPT, + ]; + } + + public static function getOpt(array $args): array { + $key = (string) ($args['key'] ?? ''); + if ($key === '') throw new \RuntimeException('key required.'); + $store = self::store(); + $exists = array_key_exists($key, $store); + $val = $exists ? $store[$key] : (function_exists('woodmart_get_opt') ? woodmart_get_opt($key) : null); + return ['key' => $key, 'exists' => $exists, 'type' => self::typeOf($val), 'value' => $val]; + } + + public static function listOpts(array $args): array { + $prefix = isset($args['prefix']) ? (string) $args['prefix'] : ''; + $store = self::store(); + $keys = []; + foreach ($store as $k => $v) { + if ($prefix !== '' && strpos((string) $k, $prefix) !== 0) continue; + $keys[] = ['key' => (string) $k, 'type' => self::typeOf($v)]; + } + usort($keys, fn($a, $b) => strcmp($a['key'], $b['key'])); + return ['count' => count($keys), 'options' => $keys]; + } + + public static function setOpt(array $args): array { + $key = (string) ($args['key'] ?? ''); + if ($key === '') throw new \RuntimeException('key required.'); + $raw = (string) ($args['value'] ?? ''); + $decoded = json_decode($raw, true); + $value = (json_last_error() === JSON_ERROR_NONE && ($raw === 'null' || $decoded !== null)) ? $decoded : $raw; + + $store = self::store(); + $had = array_key_exists($key, $store); + $prior = $had ? $store[$key] : null; + + // Record a one-slot backup so the change is reversible. + $backup = get_option(self::BACKUP, []); + if (!is_array($backup)) $backup = []; + $backup[$key] = ['had' => $had, 'value' => $prior]; + update_option(self::BACKUP, $backup, false); + + $store[$key] = $value; + update_option(self::OPT, $store); + + return ['key' => $key, 'type' => self::typeOf($value), 'value' => $value, 'backed_up' => true, 'previously_set' => $had]; + } + + public static function restoreOpt(array $args): array { + $key = (string) ($args['key'] ?? ''); + if ($key === '') throw new \RuntimeException('key required.'); + $backup = get_option(self::BACKUP, []); + if (!is_array($backup) || !array_key_exists($key, $backup)) { + throw new \RuntimeException('No backup recorded for key: ' . $key); + } + $entry = $backup[$key]; + $store = self::store(); + if (!empty($entry['had'])) { + $store[$key] = $entry['value']; + $action = 'restored'; + } else { + unset($store[$key]); + $action = 'removed'; + } + update_option(self::OPT, $store); + unset($backup[$key]); + update_option(self::BACKUP, $backup, false); + return ['key' => $key, 'action' => $action]; + } +}