feat(batch16): WPML write — set post language, create translation, connect group (guarded)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8t9GEyyLZbUQu26na1JQg
This commit is contained in:
@@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Batch 16 — WPML write/deep (Pro-equivalent, net-new).
|
||||||
|
*
|
||||||
|
* Writes that complement b4's read/audit WPML tools: set a post's language,
|
||||||
|
* create a translation copy into a target language, and connect two posts into
|
||||||
|
* one translation group. Uses the official WPML filter/action API.
|
||||||
|
* Guarded by ICL_SITEPRESS_VERSION — inert unless WPML is active.
|
||||||
|
* GPL-2.0-or-later. See NOTICE.md.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AskTamMCP\Extensions;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
class Batch16 {
|
||||||
|
|
||||||
|
public static function register($registry): void {
|
||||||
|
if (!defined('ICL_SITEPRESS_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\\Batch16::' . $method, 'inputSchema' => $schema];
|
||||||
|
};
|
||||||
|
|
||||||
|
$registry->register($def('wpml_set_post_language', 'Set (or change) the WPML language of a post. Optionally join an existing translation group via trid and source language.',
|
||||||
|
['post_id' => ['type' => 'integer'], 'language_code' => ['type' => 'string'],
|
||||||
|
'trid' => ['type' => 'integer'], 'source_language' => ['type' => 'string']],
|
||||||
|
['post_id', 'language_code'], 'write', 'setLanguage'));
|
||||||
|
|
||||||
|
$registry->register($def('wpml_copy_to_language', 'Create a translation of a post into a target language (copies title/content/type/status) and links it to the source translation group. Returns the new post id.',
|
||||||
|
['source_id' => ['type' => 'integer'], 'target_language' => ['type' => 'string'], 'status' => ['type' => 'string', 'enum' => ['publish', 'draft']]],
|
||||||
|
['source_id', 'target_language'], 'write', 'copyToLanguage'));
|
||||||
|
|
||||||
|
$registry->register($def('wpml_connect_translation', 'Connect an existing post as the translation of a source post (joins the source trid) in the given language.',
|
||||||
|
['source_id' => ['type' => 'integer'], 'translated_id' => ['type' => 'integer'], 'language_code' => ['type' => 'string']],
|
||||||
|
['source_id', 'translated_id', 'language_code'], 'write', 'connect'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function etype(int $postId): string {
|
||||||
|
return 'post_' . get_post_type($postId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function trid(int $postId): ?int {
|
||||||
|
$trid = apply_filters('wpml_element_trid', null, $postId, self::etype($postId));
|
||||||
|
return $trid ? (int) $trid : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function langOf(int $postId): ?string {
|
||||||
|
$d = apply_filters('wpml_element_language_code', null, ['element_id' => $postId, 'element_type' => self::etype($postId)]);
|
||||||
|
return $d ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setLanguage(array $args): array {
|
||||||
|
$id = (int) ($args['post_id'] ?? 0);
|
||||||
|
if (!get_post($id)) throw new \RuntimeException('Post not found: ' . $id);
|
||||||
|
$lang = (string) ($args['language_code'] ?? '');
|
||||||
|
if ($lang === '') throw new \RuntimeException('language_code required.');
|
||||||
|
$args_set = [
|
||||||
|
'element_id' => $id,
|
||||||
|
'element_type' => self::etype($id),
|
||||||
|
'trid' => isset($args['trid']) ? (int) $args['trid'] : self::trid($id),
|
||||||
|
'language_code' => $lang,
|
||||||
|
'source_language_code' => $args['source_language'] ?? null,
|
||||||
|
];
|
||||||
|
do_action('wpml_set_element_language_details', $args_set);
|
||||||
|
return ['post_id' => $id, 'language_code' => self::langOf($id), 'trid' => self::trid($id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function copyToLanguage(array $args): array {
|
||||||
|
$src = (int) ($args['source_id'] ?? 0);
|
||||||
|
$p = get_post($src);
|
||||||
|
if (!$p) throw new \RuntimeException('Source post not found: ' . $src);
|
||||||
|
$target = (string) ($args['target_language'] ?? '');
|
||||||
|
if ($target === '') throw new \RuntimeException('target_language required.');
|
||||||
|
$status = ($args['status'] ?? 'draft') === 'publish' ? 'publish' : 'draft';
|
||||||
|
|
||||||
|
$newId = wp_insert_post([
|
||||||
|
'post_title' => $p->post_title,
|
||||||
|
'post_content' => $p->post_content,
|
||||||
|
'post_excerpt' => $p->post_excerpt,
|
||||||
|
'post_type' => $p->post_type,
|
||||||
|
'post_status' => $status,
|
||||||
|
], true);
|
||||||
|
if (is_wp_error($newId)) throw new \RuntimeException('Copy failed: ' . $newId->get_error_message());
|
||||||
|
|
||||||
|
$srcLang = self::langOf($src);
|
||||||
|
$trid = self::trid($src);
|
||||||
|
do_action('wpml_set_element_language_details', [
|
||||||
|
'element_id' => $newId,
|
||||||
|
'element_type' => 'post_' . $p->post_type,
|
||||||
|
'trid' => $trid,
|
||||||
|
'language_code' => $target,
|
||||||
|
'source_language_code' => $srcLang,
|
||||||
|
]);
|
||||||
|
return ['source_id' => $src, 'new_id' => $newId, 'language_code' => self::langOf($newId), 'trid' => self::trid($newId), 'status' => $status];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function connect(array $args): array {
|
||||||
|
$src = (int) ($args['source_id'] ?? 0);
|
||||||
|
$tr = (int) ($args['translated_id'] ?? 0);
|
||||||
|
if (!get_post($src) || !get_post($tr)) throw new \RuntimeException('Source or translated post not found.');
|
||||||
|
$lang = (string) ($args['language_code'] ?? '');
|
||||||
|
if ($lang === '') throw new \RuntimeException('language_code required.');
|
||||||
|
$trid = self::trid($src);
|
||||||
|
if (!$trid) throw new \RuntimeException('Source has no WPML trid; set its language first.');
|
||||||
|
do_action('wpml_set_element_language_details', [
|
||||||
|
'element_id' => $tr,
|
||||||
|
'element_type' => 'post_' . get_post_type($tr),
|
||||||
|
'trid' => $trid,
|
||||||
|
'language_code' => $lang,
|
||||||
|
'source_language_code' => self::langOf($src),
|
||||||
|
]);
|
||||||
|
return ['source_id' => $src, 'translated_id' => $tr, 'trid' => $trid, 'language_code' => self::langOf($tr)];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user