, lang=, title/content/excerpt/status/model * * Ver issue gitea.feadulta.com/rafa/feadulta#222. */ if (!defined('ABSPATH')) exit; const FEA_TRANSLATION_LANGUAGES = ['en', 'fr', 'it', 'pt']; add_action('rest_api_init', function () { register_rest_route('fea/v1', '/crear-traduccion', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => 'fea_crear_traduccion_handle', 'permission_callback' => 'fea_crear_traduccion_can_call', // Se valida después de autorizar para que las llamadas anónimas // obtengan 401 aunque omitan parámetros. 'args' => [ 'es_id' => [ 'sanitize_callback' => 'absint', ], 'lang' => [ 'sanitize_callback' => 'sanitize_key', ], 'status' => [ 'sanitize_callback' => 'sanitize_key', ], 'model' => [ 'sanitize_callback' => 'sanitize_text_field', ], ], ]); }); /** Editor o superior: mismo nivel que los demás endpoints fea/v1 de escritura. */ function fea_crear_traduccion_can_call(WP_REST_Request $request) { if (!is_user_logged_in()) { return new WP_Error( 'fea_crear_traduccion_not_authenticated', 'Debes autenticarte para crear una traducción.', ['status' => 401] ); } if (!current_user_can('edit_others_posts')) { return new WP_Error( 'fea_crear_traduccion_forbidden', 'No tienes permiso para crear traducciones.', ['status' => 403] ); } return true; } function fea_crear_traduccion_handle(WP_REST_Request $request) { $es_id = absint($request->get_param('es_id')); if (!$es_id) { return new WP_Error( 'fea_crear_traduccion_invalid_source', 'es_id es obligatorio.', ['status' => 400] ); } $lang = (string) $request->get_param('lang'); if (!in_array($lang, FEA_TRANSLATION_LANGUAGES, true)) { return new WP_Error( 'fea_crear_traduccion_invalid_language', 'lang debe ser en, fr, it o pt.', ['status' => 400] ); } $status = (string) ($request->get_param('status') ?: 'draft'); if (!in_array($status, ['draft', 'publish'], true)) { return new WP_Error( 'fea_crear_traduccion_invalid_status', 'status debe ser draft o publish.', ['status' => 400] ); } $source = get_post($es_id); if (!$source) { return new WP_Error( 'fea_crear_traduccion_source_not_found', 'No existe el post español indicado.', ['status' => 404] ); } if (!function_exists('pll_get_post') || !function_exists('pll_set_post_language') || !function_exists('pll_save_post_translations')) { return new WP_Error( 'fea_crear_traduccion_polylang_unavailable', 'Polylang no está disponible.', ['status' => 500] ); } // Idempotencia dura: se responde antes de interpretar un payload nuevo. $existing_id = (int) pll_get_post($es_id, $lang); if ($existing_id && !get_post($existing_id)) $existing_id = 0; if ($existing_id) { return new WP_REST_Response([ 'es_id' => $es_id, 'lang' => $lang, 'translation_id' => $existing_id, 'created' => false, 'url' => get_permalink($existing_id), ], 200); } $title = (string) ($request->get_param('title') ?? ''); $new_id = wp_insert_post([ 'post_title' => wp_slash($title), 'post_content' => wp_slash((string) ($request->get_param('content') ?? '')), 'post_excerpt' => wp_slash((string) ($request->get_param('excerpt') ?? '')), 'post_name' => sanitize_title($title), 'post_status' => $status, 'post_type' => 'post', 'post_author' => (int) $source->post_author, 'post_date' => $source->post_date, 'to_ping' => '', 'pinged' => '', ], true); if (is_wp_error($new_id)) { return new WP_Error( 'fea_crear_traduccion_insert_failed', 'No se pudo crear la traducción: ' . $new_id->get_error_message(), ['status' => 500] ); } // El idioma se asigna antes de mapear categorías para que Polylang admita // los términos traducidos en el nuevo post. pll_set_post_language($new_id, $lang); $categories = wp_get_post_categories($es_id); $mapped_categories = []; foreach ($categories as $category_id) { $translated_category = function_exists('pll_get_term') ? (int) pll_get_term($category_id, $lang) : 0; $mapped_categories[] = $translated_category ?: $category_id; } if ($mapped_categories) { wp_set_post_categories($new_id, array_values(array_unique($mapped_categories))); } $translations = function_exists('pll_get_post_translations') ? pll_get_post_translations($es_id) : ['es' => $es_id]; if (!$translations) $translations = ['es' => $es_id]; $translations[$lang] = $new_id; pll_save_post_translations($translations); update_post_meta($new_id, 'traduccion_automatica', '1'); update_post_meta($new_id, 'traduccion_origen', $es_id); update_post_meta($new_id, 'traduccion_modelo', (string) ($request->get_param('model') ?? '')); update_post_meta($new_id, 'traduccion_fecha', gmdate('c')); return new WP_REST_Response([ 'es_id' => $es_id, 'lang' => $lang, 'translation_id' => (int) $new_id, 'created' => true, 'url' => get_permalink($new_id), ], 201); }