Files
gureametsabilagun/wp-content/mu-plugins/gure-ametsa-core.php
Josep Piguillem 0b2c9f271f Web de Gure Ametsa Bi Lagun en WordPress para Dokploy
- Docker Compose (WordPress + MariaDB) listo para Dokploy, con instalación
  automática por etapas: idiomas, páginas, menús y plugins recomendados.
- Web bilingüe castellano / euskera con Polylang.
- Tema propio «gure-ametsa»: diseño inspirado en Beargrass Animal Rescue,
  personalizable desde Apariencia → Personalizar (paletas, tipografías,
  secciones de portada ordenables) y patrones de bloques propios.
- Plugin mu «gure-ametsa-core»: animales en adopción con ficha y filtros,
  carrusel y formulario de contacto/adopción.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 16:21:26 +02:00

635 lines
24 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: Gure Ametsa – Núcleo
* Description: Animales en adopción, fichas, listados y formulario de contacto/adopción de Gure Ametsa Bi Lagun. Bilingüe castellano/euskera (con Polylang).
* Version: 1.1.0
* Author: Gure Ametsa Bi Lagun
*/
defined( 'ABSPATH' ) || exit;
/* -------------------------------------------------------------------------
* Idioma (castellano / euskera)
* ---------------------------------------------------------------------- */
/** Idioma actual: 'es' o 'eu'. El panel de administración siempre en castellano. */
function ga_lang() {
if ( is_admin() && ! wp_doing_ajax() ) {
return 'es';
}
$lang = function_exists( 'pll_current_language' ) ? pll_current_language() : '';
return 'eu' === $lang ? 'eu' : 'es';
}
/** Devuelve el texto en el idioma actual. */
function ga__( $es, $eu ) {
return 'eu' === ga_lang() ? $eu : $es;
}
/** Imprime el texto escapado en el idioma actual. */
function ga_e( $es, $eu ) {
echo esc_html( ga__( $es, $eu ) );
}
/** URL de una página por su slug en castellano, en el idioma actual. */
function ga_page_url( $slug_es, $fragment = '' ) {
$page = get_page_by_path( $slug_es );
if ( ! $page ) {
return home_url( "/$slug_es/" ) . $fragment;
}
$id = $page->ID;
if ( function_exists( 'pll_get_post' ) ) {
$id = pll_get_post( $id, ga_lang() ) ?: $id;
}
return get_permalink( $id ) . $fragment;
}
/* Animales y especies son traducibles; los mensajes no. */
add_filter( 'pll_get_post_types', function ( $types, $is_settings ) {
$types['animal'] = 'animal';
unset( $types['ga_mensaje'] );
return $types;
}, 10, 2 );
add_filter( 'pll_get_taxonomies', function ( $taxonomies ) {
$taxonomies['especie'] = 'especie';
return $taxonomies;
} );
/* -------------------------------------------------------------------------
* Datos de la protectora
* ---------------------------------------------------------------------- */
function ga_info( $key = null ) {
$info = apply_filters( 'ga_info', array(
'nombre' => 'Gure Ametsa Bi Lagun',
'direccion' => 'Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa)',
'telefono' => '943 64 52 79',
'email' => 'hola@gureametsabilagun.org',
'horario' => ga__( 'Lunes a viernes: 10:00–13:00 y 14:00–19:00', 'Astelehenetik ostiralera: 10:00–13:00 eta 14:00–19:00' ),
'instagram' => 'https://www.instagram.com/gureametsabilagun/',
'facebook' => 'https://www.facebook.com/gureametsabilagun/',
'maps' => 'https://www.google.com/maps/search/?api=1&query=Jaizubia+44+Hondarribia',
) );
return $key ? ( $info[ $key ] ?? '' ) : $info;
}
function ga_contact_email() {
$email = getenv( 'GA_CONTACT_EMAIL' );
return is_email( $email ) ? $email : get_option( 'admin_email' );
}
/* -------------------------------------------------------------------------
* Tipos de contenido y taxonomías
* ---------------------------------------------------------------------- */
add_action( 'init', function () {
register_post_type( 'animal', array(
'labels' => array(
'name' => 'Animales',
'singular_name' => 'Animal',
'add_new' => 'Añadir animal',
'add_new_item' => 'Añadir nuevo animal',
'edit_item' => 'Editar animal',
'new_item' => 'Nuevo animal',
'view_item' => 'Ver ficha',
'search_items' => 'Buscar animales',
'not_found' => 'No hay animales',
'not_found_in_trash' => 'No hay animales en la papelera',
'all_items' => 'Todos los animales',
'featured_image' => 'Foto principal',
'set_featured_image' => 'Elegir foto principal',
'menu_name' => 'Animales',
),
'public' => true,
'has_archive' => 'adopta',
'rewrite' => array( 'slug' => 'adopta', 'with_front' => false ),
'menu_icon' => 'dashicons-pets',
'menu_position' => 5,
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
'show_in_rest' => true,
) );
register_taxonomy( 'especie', 'animal', array(
'labels' => array(
'name' => 'Especies',
'singular_name' => 'Especie',
'add_new_item' => 'Añadir especie',
),
'hierarchical' => true,
'show_admin_column' => true,
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'especie', 'with_front' => false ),
) );
register_post_type( 'ga_mensaje', array(
'labels' => array(
'name' => 'Mensajes',
'singular_name' => 'Mensaje',
'edit_item' => 'Mensaje',
'all_items' => 'Mensajes recibidos',
'not_found' => 'Aún no hay mensajes',
),
'public' => false,
'show_ui' => true,
'menu_icon' => 'dashicons-email-alt',
'menu_position' => 6,
'supports' => array( 'title', 'editor' ),
'capability_type' => 'post',
'capabilities' => array( 'create_posts' => 'do_not_allow' ),
'map_meta_cap' => true,
) );
foreach ( array_keys( ga_fields() ) as $key ) {
register_post_meta( 'animal', "_ga_$key", array(
'type' => 'string',
'single' => true,
'show_in_rest' => true,
'auth_callback' => function () { return current_user_can( 'edit_posts' ); },
) );
}
} );
/* -------------------------------------------------------------------------
* Campos de la ficha (etiquetas en el idioma actual)
* ---------------------------------------------------------------------- */
function ga_fields() {
return array(
'estado' => array( 'label' => ga__( 'Estado', 'Egoera' ), 'type' => 'select', 'options' => array(
'disponible' => ga__( 'En adopción', 'Adopzioan' ),
'urgente' => ga__( 'Adopción urgente', 'Adopzio premiazkoa' ),
'acogida' => ga__( 'Busca casa de acogida', 'Harrera-etxe bila' ),
'reservado' => ga__( 'Reservado', 'Erreserbatuta' ),
'adoptado' => ga__( 'Adoptado', 'Adoptatuta' ),
) ),
'sexo' => array( 'label' => ga__( 'Sexo', 'Sexua' ), 'type' => 'select', 'options' => array(
'macho' => ga__( 'Macho', 'Arra' ),
'hembra' => ga__( 'Hembra', 'Emea' ),
) ),
'edad' => array( 'label' => ga__( 'Edad', 'Adina' ), 'type' => 'number', 'placeholder' => 'p. ej. 2' ),
'edad_unidad' => array( 'label' => ga__( 'Edad en', 'Adina' ), 'type' => 'select', 'options' => array(
'anos' => ga__( 'Años', 'Urteak' ),
'meses' => ga__( 'Meses', 'Hilabeteak' ),
) ),
'tamano' => array( 'label' => ga__( 'Tamaño', 'Tamaina' ), 'type' => 'select', 'options' => array(
'pequeno' => ga__( 'Pequeño', 'Txikia' ),
'mediano' => ga__( 'Mediano', 'Ertaina' ),
'grande' => ga__( 'Grande', 'Handia' ),
) ),
'raza' => array( 'label' => ga__( 'Raza', 'Arraza' ), 'type' => 'text', 'placeholder' => 'p. ej. Mestizo' ),
'llegada' => array( 'label' => ga__( 'Fecha de llegada', 'Iritsiera-data' ), 'type' => 'date' ),
'salud' => array( 'label' => ga__( 'Salud', 'Osasuna' ), 'type' => 'checks', 'options' => array(
'chip' => ga__( 'Microchip', 'Mikrotxipa' ),
'vacunado' => ga__( 'Vacunado', 'Txertatuta' ),
'esterilizado' => ga__( 'Esterilizado', 'Antzututa' ),
'desparasitado' => ga__( 'Desparasitado', 'Desparasitatuta' ),
) ),
'compatible' => array( 'label' => ga__( 'Se lleva bien con', 'Ondo moldatzen da hauekin' ), 'type' => 'checks', 'options' => array(
'ninos' => ga__( 'Niños', 'Haurrak' ),
'perros' => ga__( 'Perros', 'Txakurrak' ),
'gatos' => ga__( 'Gatos', 'Katuak' ),
) ),
);
}
/** Edad legible en el idioma actual: «3 años», «1 mes», «3 urte», «4 hilabete». */
function ga_age( $post_id ) {
$n = ga_get( $post_id, 'edad' );
if ( '' === $n || ! is_numeric( $n ) ) {
return $n; // Valores antiguos en texto libre.
}
$n = (float) $n + 0;
$months = 'meses' === ga_get( $post_id, 'edad_unidad' );
if ( 'eu' === ga_lang() ) {
return $n . ( $months ? ' hilabete' : ' urte' );
}
if ( $months ) {
return $n . ( 1 == $n ? ' mes' : ' meses' );
}
return $n . ( 1 == $n ? ' año' : ' años' );
}
function ga_get( $post_id, $key ) {
return (string) get_post_meta( $post_id, "_ga_$key", true );
}
/** Etiqueta legible de un campo select, o lista de etiquetas de un campo checks. */
function ga_label( $post_id, $key ) {
$fields = ga_fields();
$value = ga_get( $post_id, $key );
if ( '' === $value || ! isset( $fields[ $key ] ) ) {
return '';
}
$field = $fields[ $key ];
if ( 'select' === $field['type'] ) {
return $field['options'][ $value ] ?? $value;
}
if ( 'checks' === $field['type'] ) {
$labels = array();
foreach ( explode( ',', $value ) as $v ) {
if ( isset( $field['options'][ $v ] ) ) {
$labels[] = $field['options'][ $v ];
}
}
return $labels;
}
if ( 'date' === $field['type'] ) {
return date_i18n( get_option( 'date_format' ), strtotime( $value ) );
}
return $value;
}
add_action( 'add_meta_boxes_animal', function () {
add_meta_box( 'ga_ficha', 'Ficha del animal', 'ga_render_metabox', 'animal', 'normal', 'high' );
} );
function ga_render_metabox( $post ) {
wp_nonce_field( 'ga_ficha', 'ga_ficha_nonce' );
echo '<table class="form-table" role="presentation"><tbody>';
foreach ( ga_fields() as $key => $f ) {
$name = "ga_$key";
$value = ga_get( $post->ID, $key );
if ( 'estado' === $key && '' === $value ) {
$value = 'disponible';
}
echo '<tr><th scope="row"><label for="' . esc_attr( $name ) . '">' . esc_html( $f['label'] ) . '</label></th><td>';
switch ( $f['type'] ) {
case 'select':
echo '<select id="' . esc_attr( $name ) . '" name="' . esc_attr( $name ) . '"><option value="">—</option>';
foreach ( $f['options'] as $v => $l ) {
printf( '<option value="%s"%s>%s</option>', esc_attr( $v ), selected( $value, $v, false ), esc_html( $l ) );
}
echo '</select>';
break;
case 'checks':
$current = array_filter( explode( ',', $value ) );
foreach ( $f['options'] as $v => $l ) {
printf(
'<label style="margin-right:1em"><input type="checkbox" name="%s[]" value="%s"%s> %s</label>',
esc_attr( $name ), esc_attr( $v ), checked( in_array( $v, $current, true ), true, false ), esc_html( $l )
);
}
break;
default:
printf(
'<input type="%s" id="%s" name="%s" value="%s" class="%s" placeholder="%s"%s>',
esc_attr( $f['type'] ), esc_attr( $name ), esc_attr( $name ), esc_attr( $value ),
'number' === $f['type'] ? 'small-text' : 'regular-text',
esc_attr( $f['placeholder'] ?? '' ),
'number' === $f['type'] ? ' min="0" step="1"' : ''
);
}
echo '</td></tr>';
}
echo '</tbody></table>';
echo '<p class="description">La ficha se comparte entre la versión en castellano y en euskera: al guardar una, se copia a la otra. Solo el nombre y la descripción se traducen.</p>';
echo '<p class="description">Consejo: la foto principal aparece en los listados. Añade más fotos en el contenido con el bloque «Galería».</p>';
}
add_action( 'save_post_animal', function ( $post_id ) {
if ( ! isset( $_POST['ga_ficha_nonce'] ) || ! wp_verify_nonce( $_POST['ga_ficha_nonce'], 'ga_ficha' ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
foreach ( ga_fields() as $key => $f ) {
$raw = $_POST[ "ga_$key" ] ?? '';
if ( 'checks' === $f['type'] ) {
$raw = array_intersect( (array) $raw, array_keys( $f['options'] ) );
$value = implode( ',', $raw );
} elseif ( 'select' === $f['type'] ) {
$value = isset( $f['options'][ $raw ] ) ? $raw : '';
} else {
$value = sanitize_text_field( wp_unslash( $raw ) );
}
ga_update_meta_all_languages( $post_id, "_ga_$key", $value );
}
} );
/** Guarda un campo en el animal y en todas sus traducciones. */
function ga_update_meta_all_languages( $post_id, $meta_key, $value ) {
$ids = array( $post_id );
if ( function_exists( 'pll_get_post_translations' ) ) {
$ids = array_unique( array_merge( $ids, array_values( pll_get_post_translations( $post_id ) ) ) );
}
foreach ( $ids as $id ) {
update_post_meta( $id, $meta_key, $value );
}
}
/* Columnas en el listado del admin */
add_filter( 'manage_animal_posts_columns', function ( $cols ) {
$new = array();
foreach ( $cols as $k => $v ) {
if ( 'title' === $k ) {
$new['ga_foto'] = 'Foto';
}
$new[ $k ] = $v;
if ( 'title' === $k ) {
$new['ga_estado'] = 'Estado';
$new['ga_edad'] = 'Edad';
}
}
return $new;
} );
add_action( 'manage_animal_posts_custom_column', function ( $col, $post_id ) {
if ( 'ga_foto' === $col ) {
echo get_the_post_thumbnail( $post_id, array( 60, 60 ) );
} elseif ( 'ga_estado' === $col ) {
echo esc_html( ga_label( $post_id, 'estado' ) );
} elseif ( 'ga_edad' === $col ) {
echo esc_html( ga_age( $post_id ) );
}
}, 10, 2 );
/* Título de la pestaña del listado en el idioma actual */
add_filter( 'document_title_parts', function ( $parts ) {
if ( is_post_type_archive( 'animal' ) ) {
$parts['title'] = ga__( 'Animales en adopción', 'Animaliak adopzioan' );
}
return $parts;
} );
/* -------------------------------------------------------------------------
* Consultas del listado público /adopta/
* ---------------------------------------------------------------------- */
add_filter( 'query_vars', function ( $vars ) {
return array_merge( $vars, array( 'tamano', 'sexo', 'edad', 'con' ) );
} );
/** Grupos de edad para el filtro del listado. */
function ga_age_groups() {
return array(
'joven' => ga__( 'Menos de 1 año', 'Urtebete baino gutxiago' ),
'adulto' => ga__( 'Adulto', 'Heldua' ),
'senior' => ga__( 'Mayor (8+)', 'Adinekoa (8+)' ),
);
}
/** meta_query para un grupo de edad (la edad se guarda como número + unidad). */
function ga_age_meta_query( $group ) {
$anos = array( 'key' => '_ga_edad_unidad', 'value' => 'anos' );
switch ( $group ) {
case 'joven':
return array(
'relation' => 'OR',
array( 'key' => '_ga_edad_unidad', 'value' => 'meses' ),
array( 'relation' => 'AND', $anos, array( 'key' => '_ga_edad', 'value' => 1, 'compare' => '<', 'type' => 'NUMERIC' ) ),
);
case 'adulto':
return array( 'relation' => 'AND', $anos, array( 'key' => '_ga_edad', 'value' => array( 1, 7 ), 'compare' => 'BETWEEN', 'type' => 'NUMERIC' ) );
case 'senior':
return array( 'relation' => 'AND', $anos, array( 'key' => '_ga_edad', 'value' => 8, 'compare' => '>=', 'type' => 'NUMERIC' ) );
}
return array();
}
function ga_not_adopted_meta_query() {
return array(
'relation' => 'OR',
array( 'key' => '_ga_estado', 'value' => 'adoptado', 'compare' => '!=' ),
array( 'key' => '_ga_estado', 'compare' => 'NOT EXISTS' ),
);
}
add_action( 'pre_get_posts', function ( $q ) {
if ( is_admin() || ! $q->is_main_query() || ! ( $q->is_post_type_archive( 'animal' ) || $q->is_tax( 'especie' ) ) ) {
return;
}
$meta = array( ga_not_adopted_meta_query() );
foreach ( array( 'tamano', 'sexo' ) as $key ) {
$v = sanitize_key( (string) $q->get( $key ) );
if ( $v && isset( ga_fields()[ $key ]['options'][ $v ] ) ) {
$meta[] = array( 'key' => "_ga_$key", 'value' => $v );
}
}
$edad = sanitize_key( (string) $q->get( 'edad' ) );
if ( isset( ga_age_groups()[ $edad ] ) ) {
$meta[] = ga_age_meta_query( $edad );
}
$con = sanitize_key( (string) $q->get( 'con' ) );
if ( isset( ga_fields()['compatible']['options'][ $con ] ) ) {
$meta[] = array( 'key' => '_ga_compatible', 'value' => $con, 'compare' => 'LIKE' );
}
$q->set( 'meta_query', $meta );
$q->set( 'posts_per_page', 12 );
} );
/**
* Consulta reutilizable de animales (Polylang filtra por el idioma actual).
*/
function ga_query_animals( $args = array() ) {
$args = wp_parse_args( $args, array(
'numero' => 6,
'especie' => '',
'estado' => '',
) );
$query = array(
'post_type' => 'animal',
'posts_per_page' => (int) $args['numero'],
'no_found_rows' => true,
);
if ( $args['especie'] ) {
$query['tax_query'] = array( array(
'taxonomy' => 'especie',
'field' => 'slug',
'terms' => array_map( 'trim', explode( ',', $args['especie'] ) ),
) );
}
if ( $args['estado'] ) {
$query['meta_query'] = array( array(
'key' => '_ga_estado',
'value' => array_map( 'trim', explode( ',', $args['estado'] ) ),
'compare' => 'IN',
) );
} else {
$query['meta_query'] = ga_not_adopted_meta_query();
}
return new WP_Query( $query );
}
/* [ga_animales numero="6" especie="perro" estado="urgente" vista="carrusel"] */
add_shortcode( 'ga_animales', function ( $atts ) {
$atts = shortcode_atts( array( 'numero' => 6, 'especie' => '', 'estado' => '', 'vista' => 'rejilla' ), $atts, 'ga_animales' );
$q = ga_query_animals( $atts );
ob_start();
if ( $q->have_posts() ) {
$carousel = 'carrusel' === $atts['vista'];
if ( $carousel ) {
ga_carousel_open();
} else {
echo '<div class="ga-grid">';
}
while ( $q->have_posts() ) {
$q->the_post();
ga_animal_card();
}
$carousel ? ga_carousel_close() : print( '</div>' );
} else {
echo '<p class="ga-empty">' . esc_html( ga__( 'Ahora mismo no hay animales en esta sección. ¡Vuelve pronto!', 'Une honetan ez dago animaliarik atal honetan. Itzuli laster!' ) ) . '</p>';
}
wp_reset_postdata();
return ob_get_clean();
} );
/** Apertura y cierre de un carrusel accesible (el tema aporta el CSS y el JS). */
function ga_carousel_open( $label = '' ) {
printf(
'<div class="ga-carousel" data-ga-carousel role="region" aria-roledescription="%s" aria-label="%s"><div class="ga-carousel__track" tabindex="0">',
esc_attr( ga__( 'carrusel', 'karrusela' ) ),
esc_attr( $label ?: ga__( 'Animales', 'Animaliak' ) )
);
}
function ga_carousel_close() {
printf(
'</div><div class="ga-carousel__nav"><button type="button" class="ga-carousel__btn" data-dir="-1" aria-label="%s">←</button><button type="button" class="ga-carousel__btn" data-dir="1" aria-label="%s">→</button></div></div>',
esc_attr( ga__( 'Anteriores', 'Aurrekoak' ) ),
esc_attr( ga__( 'Siguientes', 'Hurrengoak' ) )
);
}
/** Tarjeta de un animal (dentro del loop). El tema puede sobrescribirla con template-parts/animal-card.php. */
function ga_animal_card() {
if ( locate_template( 'template-parts/animal-card.php' ) ) {
get_template_part( 'template-parts/animal-card' );
return;
}
printf( '<article class="ga-card"><a href="%s">%s</a></article>', esc_url( get_permalink() ), esc_html( get_the_title() ) );
}
/* -------------------------------------------------------------------------
* Formulario de contacto / solicitud de adopción [ga_contacto]
* ---------------------------------------------------------------------- */
function ga_contact_reasons() {
return array(
'adopcion' => ga__( 'Adopción', 'Adopzioa' ),
'acogida' => ga__( 'Casa de acogida', 'Harrera-etxea' ),
'voluntario' => ga__( 'Voluntariado', 'Boluntariotza' ),
'donaciones' => ga__( 'Donaciones', 'Dohaintzak' ),
'hotel' => ga__( 'Hotel para perros y gatos', 'Txakur eta katuentzako hotela' ),
'perdido' => ga__( 'He encontrado / perdido un animal', 'Animalia bat aurkitu / galdu dut' ),
'otro' => ga__( 'Otro', 'Beste bat' ),
);
}
add_shortcode( 'ga_contacto', function () {
$status = isset( $_GET['enviado'] ) ? sanitize_key( $_GET['enviado'] ) : '';
$animal_id = isset( $_GET['adoptar'] ) ? absint( $_GET['adoptar'] ) : 0;
$animal = $animal_id && 'animal' === get_post_type( $animal_id ) ? get_the_title( $animal_id ) : '';
$preselect = $animal ? 'adopcion' : ( isset( $_GET['motivo'] ) ? sanitize_key( $_GET['motivo'] ) : '' );
$privacy = ga_page_url( 'politica-de-privacidad' );
ob_start();
if ( 'ok' === $status ) {
echo '<div class="ga-notice ga-notice--ok" role="status"><strong>' . esc_html( ga__( '¡Eskerrik asko!', 'Eskerrik asko!' ) ) . '</strong> '
. esc_html( ga__( 'Hemos recibido tu mensaje y te responderemos lo antes posible.', 'Zure mezua jaso dugu eta ahalik eta lasterren erantzungo dizugu.' ) ) . '</div>';
} elseif ( 'error' === $status ) {
echo '<div class="ga-notice ga-notice--error" role="alert">'
. esc_html( ga__( 'No hemos podido enviar el mensaje. Revisa los campos obligatorios o escríbenos a ', 'Ezin izan dugu mezua bidali. Egiaztatu derrigorrezko eremuak edo idatzi iezaguzu helbide honetara: ' ) . ga_info( 'email' ) ) . '</div>';
}
?>
<form class="ga-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
<input type="hidden" name="action" value="ga_contacto">
<input type="hidden" name="idioma" value="<?php echo esc_attr( ga_lang() ); ?>">
<input type="hidden" name="redirect" value="<?php echo esc_url( get_permalink() ); ?>">
<?php wp_nonce_field( 'ga_contacto', 'ga_nonce' ); ?>
<div class="ga-hp" aria-hidden="true"><label>No rellenar <input type="text" name="web" tabindex="-1" autocomplete="off"></label></div>
<div class="ga-form__row">
<label><?php ga_e( 'Nombre', 'Izena' ); ?> *<input type="text" name="nombre" required autocomplete="name"></label>
<label><?php ga_e( 'Email', 'Posta elektronikoa' ); ?> *<input type="email" name="email" required autocomplete="email"></label>
</div>
<div class="ga-form__row">
<label><?php ga_e( 'Teléfono', 'Telefonoa' ); ?><input type="tel" name="telefono" autocomplete="tel"></label>
<label><?php ga_e( 'Motivo', 'Arrazoia' ); ?>
<select name="motivo">
<?php foreach ( ga_contact_reasons() as $value => $label ) : ?>
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $preselect, $value ); ?>><?php echo esc_html( $label ); ?></option>
<?php endforeach; ?>
</select>
</label>
</div>
<label><?php ga_e( 'Animal por el que preguntas', 'Zein animaliari buruz galdetzen duzu' ); ?>
<input type="text" name="animal" value="<?php echo esc_attr( $animal ); ?>" placeholder="<?php echo esc_attr( ga__( 'Opcional', 'Aukerakoa' ) ); ?>">
</label>
<label><?php ga_e( 'Mensaje', 'Mezua' ); ?> *
<textarea name="mensaje" rows="6" required placeholder="<?php echo $animal ? esc_attr( ga__( 'Cuéntanos un poco sobre ti, tu casa y tu día a día…', 'Kontaiguzu zerbait zuri buruz, zure etxeari eta eguneroko bizitzari buruz…' ) ) : ''; ?>"></textarea>
</label>
<label class="ga-form__check">
<input type="checkbox" name="privacidad" value="1" required>
<span>
<?php if ( 'eu' === ga_lang() ) : ?>
<a href="<?php echo esc_url( $privacy ); ?>" target="_blank">Pribatutasun-politika</a> irakurri eta onartzen dut. *
<?php else : ?>
He leído y acepto la <a href="<?php echo esc_url( $privacy ); ?>" target="_blank">política de privacidad</a>. *
<?php endif; ?>
</span>
</label>
<button type="submit" class="ga-btn"><?php ga_e( 'Enviar mensaje', 'Mezua bidali' ); ?></button>
</form>
<?php
return ob_get_clean();
} );
add_action( 'admin_post_nopriv_ga_contacto', 'ga_handle_contact' );
add_action( 'admin_post_ga_contacto', 'ga_handle_contact' );
function ga_handle_contact() {
$redirect = wp_validate_redirect( esc_url_raw( wp_unslash( $_POST['redirect'] ?? '' ) ), home_url( '/' ) );
$go = function ( $status ) use ( $redirect ) {
wp_safe_redirect( add_query_arg( 'enviado', $status, $redirect ) . '#formulario' );
exit;
};
if ( ! isset( $_POST['ga_nonce'] ) || ! wp_verify_nonce( $_POST['ga_nonce'], 'ga_contacto' ) ) {
$go( 'error' );
}
// Honeypot: los bots rellenan el campo oculto; fingimos éxito.
if ( ! empty( $_POST['web'] ) ) {
$go( 'ok' );
}
$reasons = ga_contact_reasons(); // En castellano: el admin_post se ejecuta en contexto de administración.
$reason = sanitize_key( $_POST['motivo'] ?? '' );
$data = array(
'nombre' => sanitize_text_field( wp_unslash( $_POST['nombre'] ?? '' ) ),
'email' => sanitize_email( wp_unslash( $_POST['email'] ?? '' ) ),
'telefono' => sanitize_text_field( wp_unslash( $_POST['telefono'] ?? '' ) ),
'motivo' => $reasons[ $reason ] ?? $reasons['otro'],
'animal' => sanitize_text_field( wp_unslash( $_POST['animal'] ?? '' ) ),
'mensaje' => sanitize_textarea_field( wp_unslash( $_POST['mensaje'] ?? '' ) ),
'idioma' => 'eu' === ( $_POST['idioma'] ?? '' ) ? 'Euskera' : 'Castellano',
);
if ( ! $data['nombre'] || ! is_email( $data['email'] ) || ! $data['mensaje'] || empty( $_POST['privacidad'] ) ) {
$go( 'error' );
}
$subject = sprintf( '[Web] %s – %s', $data['motivo'], $data['nombre'] );
if ( $data['animal'] ) {
$subject .= ' (' . $data['animal'] . ')';
}
$body = sprintf(
"Nombre: %s\nEmail: %s\nTeléfono: %s\nMotivo: %s\nAnimal: %s\nIdioma: %s\n\n%s",
$data['nombre'], $data['email'], $data['telefono'] ?: '-', $data['motivo'], $data['animal'] ?: '-', $data['idioma'], $data['mensaje']
);
// Se guarda siempre en el panel, aunque falle el correo.
wp_insert_post( array(
'post_type' => 'ga_mensaje',
'post_status' => 'private',
'post_title' => $subject,
'post_content' => $body,
) );
wp_mail( ga_contact_email(), $subject, $body, array( 'Reply-To: ' . $data['nombre'] . ' <' . $data['email'] . '>' ) );
$go( 'ok' );
}