Indicaciones del cliente: adopción solo Perros/Gatos, fichas nuevas y todo configurable

- Adopción sin filtros ni etiquetas: acceso a Perros y Gatos, tarjetas de foto y nombre.
- Ficha nueva: galería, vídeo, fecha de nacimiento o edad aproximada, carácter,
  necesidades, convivencia y hogar que buscamos (textos por idioma, datos compartidos).
- Estados disponible / en proceso / adoptado y animales destacados.
- Botón «Quiero conocerlo/la» con formulario breve (animal incluido) y confirmación.
- Botones para compartir cada ficha (WhatsApp, Facebook, copiar enlace).
- Portada corta según la propuesta del cliente; donaciones, cifras, etc. ocultas.
- Páginas Acoge y Preguntas frecuentes, menú con submenús, sin hotel.
- Aviso de cita previa y lista de ayuda material editables desde el panel.
- Plugin núcleo dividido en módulos (i18n, animales, formularios, APIs).
- Migración 5 idempotente: respeta las páginas editadas por el cliente.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 22:16:24 +02:00
parent 532bc620de
commit 4acc8b62d1
41 changed files with 1985 additions and 1533 deletions

View File

@@ -0,0 +1,113 @@
<?php
/**
* APIs: REST (/wp-json/wp/v2/animales) y GraphQL (/graphql). Documentación Swagger protegida.
*/
defined( 'ABSPATH' ) || exit;
/** Ficha de un animal lista para las APIs: valores internos + textos legibles en su idioma. */
function ga_animal_api_data( $post_id ) {
$lang = function_exists( 'pll_get_post_language' ) ? ( pll_get_post_language( $post_id ) ?: 'es' ) : 'es';
$data = array(
'estado' => ga_status( $post_id ),
'destacado' => (bool) ga_get( $post_id, 'destacado' ),
'sexo' => ga_get( $post_id, 'sexo' ),
'nacimiento' => ga_get( $post_id, 'nacimiento' ),
'edad' => '' === ga_get( $post_id, 'edad' ) ? null : (float) ga_get( $post_id, 'edad' ),
'edad_unidad' => ga_get( $post_id, 'edad_unidad' ),
'tamano' => ga_get( $post_id, 'tamano' ),
'llegada' => ga_get( $post_id, 'llegada' ),
'galeria' => array_map( fn( $id ) => wp_get_attachment_image_url( $id, 'large' ), ga_gallery_ids( $post_id ) ),
'video' => ga_get( $post_id, 'video' ),
'caracter' => ga_get( $post_id, 'caracter' ),
'necesidades' => ga_get( $post_id, 'necesidades' ),
'convivencia' => ga_get( $post_id, 'convivencia' ),
'hogar' => ga_get( $post_id, 'hogar' ),
'idioma' => $lang,
);
$data['textos'] = ga_with_lang( $lang, fn() => array(
'estado' => ga_label( $post_id, 'estado' ),
'sexo' => ga_label( $post_id, 'sexo' ),
'edad' => ga_age( $post_id ),
'tamano' => ga_label( $post_id, 'tamano' ),
) );
return $data;
}
add_action( 'rest_api_init', function () {
register_rest_field( 'animal', 'ficha', array(
'get_callback' => fn( $post ) => ga_animal_api_data( $post['id'] ),
'schema' => array(
'description' => 'Ficha del animal (valores internos y textos legibles en su idioma).',
'type' => 'object',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'properties' => array(
'estado' => array( 'type' => 'string', 'enum' => array( 'disponible', 'proceso', 'adoptado' ) ),
'destacado' => array( 'type' => 'boolean' ),
'sexo' => array( 'type' => 'string' ),
'nacimiento' => array( 'type' => 'string' ),
'edad' => array( 'type' => array( 'number', 'null' ) ),
'edad_unidad' => array( 'type' => 'string' ),
'tamano' => array( 'type' => 'string' ),
'llegada' => array( 'type' => 'string' ),
'galeria' => array( 'type' => 'array', 'items' => array( 'type' => 'string', 'format' => 'uri' ) ),
'video' => array( 'type' => 'string' ),
'caracter' => array( 'type' => 'string' ),
'necesidades' => array( 'type' => 'string' ),
'convivencia' => array( 'type' => 'string' ),
'hogar' => array( 'type' => 'string' ),
'idioma' => array( 'type' => 'string' ),
'textos' => array( 'type' => 'object' ),
),
),
) );
} );
add_action( 'graphql_register_types', function () {
register_graphql_object_type( 'AnimalFichaTextos', array(
'description' => 'Textos legibles de la ficha, en el idioma del animal.',
'fields' => array(
'estado' => array( 'type' => 'String' ),
'sexo' => array( 'type' => 'String' ),
'edad' => array( 'type' => 'String' ),
'tamano' => array( 'type' => 'String' ),
),
) );
register_graphql_object_type( 'AnimalFicha', array(
'description' => 'Ficha del animal en adopción.',
'fields' => array(
'estado' => array( 'type' => 'String', 'description' => 'disponible, proceso o adoptado' ),
'destacado' => array( 'type' => 'Boolean' ),
'sexo' => array( 'type' => 'String' ),
'nacimiento' => array( 'type' => 'String' ),
'edad' => array( 'type' => 'Float' ),
'edadUnidad' => array( 'type' => 'String' ),
'tamano' => array( 'type' => 'String' ),
'llegada' => array( 'type' => 'String' ),
'galeria' => array( 'type' => array( 'list_of' => 'String' ) ),
'video' => array( 'type' => 'String' ),
'caracter' => array( 'type' => 'String' ),
'necesidades' => array( 'type' => 'String' ),
'convivencia' => array( 'type' => 'String' ),
'hogar' => array( 'type' => 'String' ),
'idioma' => array( 'type' => 'String' ),
'textos' => array( 'type' => 'AnimalFichaTextos' ),
),
) );
register_graphql_field( 'Animal', 'ficha', array(
'type' => 'AnimalFicha',
'resolve' => function ( $post ) {
$data = ga_animal_api_data( $post->databaseId );
$data['edadUnidad'] = $data['edad_unidad'];
return $data;
},
) );
} );
/* Documentación Swagger (/rest-api/docs/): solo para usuarios conectados, salvo API_DOCS_PUBLIC=true */
add_action( 'template_redirect', function () {
if ( 'docs' === get_query_var( 'swagger_api' ) && 'true' !== getenv( 'API_DOCS_PUBLIC' ) && ! is_user_logged_in() ) {
auth_redirect();
}
}, 1 );