Sincronizar mu-plugins/ y scripts/ con el estado real del sitio (2026-07-16)

Este repo llevaba desde el 28-jun sin actualizarse (salvo sync_carta_from_prod.py).
Se pone al dia con 3 semanas de trabajo que solo vivian en el checkout local
completo del proyecto:

- Fix del buscador (issue #178): AND obligatorio en FULLTEXT (antes devolvia
  practicamente todo el sitio con cualquier busqueda), exclusion de paginas
  indice residuales de la migracion K2, soporte de frase exacta entre comillas.
- Nuevos mu-plugins ya desplegados a prod: fea-carta-id-api, fea-cloudflare-realip,
  fea-crear-autor-api, fea-gsc-verification, fea-legacy-redirect (cutover
  Joomla->WP, ver issue #162).
- TTS multi-voz por autor, scripts de traduccion, sync de audio a prod,
  homenajes Mardones/Galarreta.

Se mantiene la estructura plana del repo (mu-plugins/ + scripts/, sin el
wordpress/wp-content/ del checkout completo) tal y como documenta el README:
es la convencion establecida para este repo, mas limpia para quien solo
necesita leer el codigo. Anadido .gitignore (cache de Python que no debia
commitearse).

Fuente: checkout local completo del proyecto, rama main (commit 69e849d).
This commit is contained in:
2026-07-15 20:26:43 -04:00
parent d044e229dc
commit 6b61250b0b
35 changed files with 1482 additions and 45 deletions
+109
View File
@@ -0,0 +1,109 @@
<?php
/**
* Plugin Name: Fe Adulta — API crear-autor
* Description: Endpoint REST acotado para que Mixbot (Inma) dé de alta autores
* nuevos sin depender de que Rafa esté disponible, sin necesitar
* el permiso sensible create_users de WP. El rol siempre es
* 'author' (fijo en el código, no lo decide quien llama).
* Idempotente: si el slug ya existe, devuelve el usuario existente.
* Version: 1.0
*
* Ver issue gitea.feadulta.com/rafa/feadulta#166.
*/
if (!defined('ABSPATH')) exit;
add_action('rest_api_init', function () {
register_rest_route('fea/v1', '/crear-autor', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => 'fea_crear_autor_handle',
'permission_callback' => 'fea_crear_autor_can_call',
'args' => [
'nombre' => ['required' => true],
'slug' => ['required' => false],
],
]);
});
/** Editor o superior (mismo nivel que ya usan Inma/Mixbot para editar posts). */
function fea_crear_autor_can_call(WP_REST_Request $request) {
if (!is_user_logged_in()) {
return new WP_Error(
'fea_crear_autor_not_authenticated',
'Debes autenticarte para crear un autor.',
['status' => 401]
);
}
if (!current_user_can('edit_others_posts')) {
return new WP_Error(
'fea_crear_autor_forbidden',
'No tienes permiso para crear autores.',
['status' => 403]
);
}
return true;
}
function fea_crear_autor_handle(WP_REST_Request $request) {
$nombre = trim((string) $request->get_param('nombre'));
if ($nombre === '') {
return new WP_Error(
'fea_crear_autor_invalid',
'nombre es obligatorio.',
['status' => 400]
);
}
$slug_input = trim((string) $request->get_param('slug'));
$login = sanitize_user(sanitize_title($slug_input !== '' ? $slug_input : $nombre), true);
if ($login === '') {
return new WP_Error(
'fea_crear_autor_invalid',
'No se pudo derivar un slug válido de nombre/slug.',
['status' => 400]
);
}
// Idempotencia: si el login/slug ya existe, se devuelve tal cual (created=false).
$existing = get_user_by('login', $login);
if ($existing) {
return fea_crear_autor_response($existing, false);
}
$email = $login . '@feadulta.com';
$i = 2;
while (email_exists($email)) {
$email = $login . $i . '@feadulta.com';
$i++;
}
$user_id = wp_insert_user([
'user_login' => $login,
'user_pass' => wp_generate_password(20),
'user_email' => $email,
'display_name' => $nombre,
'nickname' => $nombre,
'role' => 'author', // fijo: este endpoint nunca crea otro rol.
]);
if (is_wp_error($user_id)) {
return new WP_Error(
'fea_crear_autor_failed',
'No se pudo crear el usuario: ' . $user_id->get_error_message(),
['status' => 500]
);
}
return fea_crear_autor_response(get_userdata($user_id), true);
}
function fea_crear_autor_response(WP_User $user, bool $created) {
return rest_ensure_response([
'id' => $user->ID,
'login' => $user->user_login,
'slug' => $user->user_nicename,
'display_name' => $user->display_name,
'role' => 'author',
'created' => $created,
]);
}