Files
Josep Piguillem f6150bd71b Carrusel de animales más fácil de entender
- Botones grandes con texto («Anteriores» / «Siguientes»; en móvil solo flechas, con nombre accesible).
- Contador «1–3 / 10» y la siguiente tarjeta asomando por el borde para que se vea que hay más.
- Última tarjeta «Ver todos los animales» que lleva a la página Adopta.
- Arreglado: al empezar, «Anteriores» no salía desactivado (el scroll-snap desplazaba 4 px).
- Versión del tema 2.3.1.

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

544 lines
22 KiB
PHP
Raw Permalink 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
/**
* Animales en adopción: tipo de contenido, ficha, galería, consultas y listados.
*/
defined( 'ABSPATH' ) || exit;
/* -------------------------------------------------------------------------
* 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',
'remove_featured_image' => 'Quitar foto principal',
'use_featured_image' => 'Usar como foto principal',
'excerpt' => 'Frase corta',
'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,
'rest_base' => 'animals',
'show_in_graphql' => true,
'graphql_single_name' => 'animal',
'graphql_plural_name' => 'animals',
) );
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,
'rest_base' => 'species',
'show_in_graphql' => true,
'graphql_single_name' => 'species',
'graphql_plural_name' => 'speciesList',
'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 ) {
// Los metadatos internos no se exponen tal cual: la API usa el campo «profile» (en inglés, ver api.php).
register_post_meta( 'animal', "_ga_$key", array(
'type' => 'string',
'single' => true,
'show_in_rest' => false,
'auth_callback' => fn() => current_user_can( 'edit_posts' ),
) );
}
} );
/* -------------------------------------------------------------------------
* Campos de la ficha
*
* 'shared' => true: el dato es común a la versión en castellano y en euskera.
* Los textos (carácter, necesidades…) se escriben en cada idioma.
* ---------------------------------------------------------------------- */
function ga_fields() {
return array(
'estado' => array( 'shared' => true, 'label' => ga__( 'Estado', 'Egoera' ), 'type' => 'select', 'options' => array(
'disponible' => ga__( 'Disponible', 'Eskuragarri' ),
'proceso' => ga__( 'En proceso', 'Prozesuan' ),
'adoptado' => ga__( 'Adoptado', 'Adoptatuta' ),
), 'help' => 'Los adoptados salen solos del listado.' ),
'destacado' => array( 'shared' => true, 'label' => ga__( 'Destacado', 'Nabarmendua' ), 'type' => 'checkbox', 'help' => 'Aparece en la portada. Útil para quien lleva más tiempo esperando o necesita un hogar especial.' ),
'apadrinable' => array( 'shared' => true, 'label' => ga__( 'Busca padrino o madrina', 'Aitabitxi edo amabitxi bila' ), 'type' => 'checkbox', 'help' => 'Aparece en la sección «Apadrina» (si está activada en Personalizar).' ),
'sexo' => array( 'shared' => true, 'label' => ga__( 'Sexo', 'Sexua' ), 'type' => 'select', 'options' => array(
'macho' => ga__( 'Macho', 'Arra' ),
'hembra' => ga__( 'Hembra', 'Emea' ),
) ),
'nacimiento' => array( 'shared' => true, 'label' => ga__( 'Fecha de nacimiento', 'Jaiotze-data' ), 'type' => 'date', 'help' => 'Si no se conoce, deja la fecha vacía y rellena la edad aproximada.' ),
'edad' => array( 'shared' => true, 'label' => ga__( 'Edad aproximada', 'Gutxi gorabeherako adina' ), 'type' => 'number' ),
'edad_unidad' => array( 'shared' => true, 'label' => ga__( 'Edad en', 'Adina' ), 'type' => 'select', 'options' => array(
'anos' => ga__( 'Años', 'Urteak' ),
'meses' => ga__( 'Meses', 'Hilabeteak' ),
) ),
'tamano' => array( 'shared' => true, 'label' => ga__( 'Tamaño', 'Tamaina' ), 'type' => 'select', 'options' => array(
'pequeno' => ga__( 'Pequeño', 'Txikia' ),
'mediano' => ga__( 'Mediano', 'Ertaina' ),
'grande' => ga__( 'Grande', 'Handia' ),
), 'help' => 'Solo en perros.' ),
'llegada' => array( 'shared' => true, 'label' => ga__( 'En Bilagun desde', 'Bilagunen noiztik' ), 'type' => 'date', 'help' => 'Fecha de entrada, solo si está confirmada.' ),
'galeria' => array( 'shared' => true, 'label' => ga__( 'Más fotos', 'Argazki gehiago' ), 'type' => 'gallery' ),
'video' => array( 'shared' => true, 'label' => ga__( 'Vídeo', 'Bideoa' ), 'type' => 'url', 'help' => 'Enlace de YouTube, Vimeo o Instagram, o un vídeo subido a la biblioteca.' ),
'caracter' => array( 'label' => ga__( 'Cómo es', 'Nolakoa den' ), 'type' => 'textarea', 'help' => 'Su carácter, contado como en redes.' ),
'necesidades' => array( 'label' => ga__( 'Qué necesita', 'Zer behar duen' ), 'type' => 'textarea' ),
'convivencia' => array( 'label' => ga__( 'Convivencia con niños y otros animales', 'Haurrekin eta beste animaliekin bizikidetza' ), 'type' => 'textarea', 'help' => 'Solo lo observado, con contexto. Déjalo vacío si no lo sabemos.' ),
'hogar' => array( 'label' => ga__( 'El hogar que buscamos', 'Bilatzen dugun etxea' ), 'type' => 'textarea' ),
);
}
function ga_get( $post_id, $key ) {
return (string) get_post_meta( $post_id, "_ga_$key", true );
}
/** Estado normalizado (acepta valores antiguos). */
function ga_status( $post_id ) {
$estado = ga_get( $post_id, 'estado' );
return match ( $estado ) {
'adoptado' => 'adoptado',
'proceso', 'reservado' => 'proceso',
default => 'disponible',
};
}
/** Etiqueta legible de un campo de opciones. */
function ga_label( $post_id, $key ) {
$fields = ga_fields();
$value = 'estado' === $key ? ga_status( $post_id ) : ga_get( $post_id, $key );
if ( '' === $value || ! isset( $fields[ $key ] ) ) {
return '';
}
$field = $fields[ $key ];
if ( 'select' === $field['type'] ) {
return $field['options'][ $value ] ?? '';
}
if ( 'date' === $field['type'] ) {
return date_i18n( get_option( 'date_format' ), strtotime( $value ) );
}
return $value;
}
/** Edad legible: calculada desde la fecha de nacimiento o la aproximada. */
function ga_age( $post_id ) {
$birth = ga_get( $post_id, 'nacimiento' );
if ( $birth && strtotime( $birth ) ) {
$diff = date_diff( date_create( $birth ), date_create( 'today' ) );
$n = $diff->y ?: $diff->m;
$months = ! $diff->y;
if ( ! $n ) {
return ga__( 'Menos de un mes', 'Hilabete bat baino gutxiago' );
}
} else {
$n = ga_get( $post_id, 'edad' );
if ( '' === $n || ! is_numeric( $n ) ) {
return '';
}
$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' );
}
/** ¿Es un perro? (el tamaño solo se muestra en perros) */
function ga_is_dog( $post_id ) {
$terms = get_the_terms( $post_id, 'especie' ) ?: array();
foreach ( $terms as $term ) {
if ( in_array( $term->slug, array( 'perro', 'txakurra' ), true ) ) {
return true;
}
}
return false;
}
/** IDs de las fotos: la principal primero y después la galería. */
function ga_gallery_ids( $post_id ) {
$ids = array_filter( array_map( 'absint', explode( ',', ga_get( $post_id, 'galeria' ) ) ) );
if ( has_post_thumbnail( $post_id ) ) {
array_unshift( $ids, (int) get_post_thumbnail_id( $post_id ) );
}
return array_values( array_unique( $ids ) );
}
/* -------------------------------------------------------------------------
* Ficha en el panel
* ---------------------------------------------------------------------- */
/* Editor clásico para los animales: la historia arriba y la ficha justo debajo, siempre a la vista. */
add_filter( 'use_block_editor_for_post_type', fn( $use, $type ) => 'animal' === $type ? false : $use, 10, 2 );
/* El cuadro de Yoast SEO va al final, debajo de la ficha. */
add_filter( 'wpseo_metabox_prio', fn() => 'low' );
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' );
$fields = ga_fields();
$groups = array(
'Datos (comunes a castellano y euskera)' => array_filter( $fields, fn( $f ) => ! empty( $f['shared'] ) ),
'Textos de la ficha (en el idioma de esta página)' => array_filter( $fields, fn( $f ) => empty( $f['shared'] ) ),
);
echo '<p class="description">La historia se escribe en el editor principal. La «frase corta» (extracto) es opcional.</p>';
foreach ( $groups as $title => $group ) {
echo '<h3 style="margin:24px 0 4px">' . esc_html( $title ) . '</h3><table class="form-table" role="presentation"><tbody>';
foreach ( $group as $key => $f ) {
$name = "ga_$key";
$value = 'estado' === $key ? ga_status( $post->ID ) : ga_get( $post->ID, $key );
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 ) . '">';
if ( 'estado' !== $key ) {
echo '<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 'checkbox':
printf( '<label><input type="checkbox" id="%1$s" name="%1$s" value="1"%2$s> Sí</label>', esc_attr( $name ), checked( $value, '1', false ) );
break;
case 'textarea':
printf( '<textarea id="%1$s" name="%1$s" rows="4" class="large-text">%2$s</textarea>', esc_attr( $name ), esc_textarea( $value ) );
break;
case 'gallery':
printf( '<input type="hidden" id="%1$s" name="%1$s" value="%2$s">', esc_attr( $name ), esc_attr( $value ) );
echo '<div class="ga-gallery-admin" data-input="' . esc_attr( $name ) . '">';
foreach ( array_filter( explode( ',', $value ) ) as $id ) {
$thumb = wp_get_attachment_image( (int) $id, array( 80, 80 ) );
if ( $thumb ) {
printf( '<span class="ga-gallery-admin__item" data-id="%d">%s<button type="button" aria-label="Quitar">×</button></span>', (int) $id, $thumb );
}
}
echo '</div><button type="button" class="button ga-gallery-add">Añadir fotos</button>';
break;
case 'number':
printf( '<input type="number" min="0" step="1" id="%1$s" name="%1$s" value="%2$s" class="small-text">', esc_attr( $name ), esc_attr( $value ) );
break;
default:
printf( '<input type="%1$s" id="%2$s" name="%2$s" value="%3$s" class="regular-text">', esc_attr( $f['type'] ), esc_attr( $name ), esc_attr( $value ) );
}
if ( ! empty( $f['help'] ) ) {
echo '<p class="description">' . esc_html( $f['help'] ) . '</p>';
}
echo '</td></tr>';
}
echo '</tbody></table>';
}
}
/* Selector de fotos de la galería */
add_action( 'admin_enqueue_scripts', function ( $hook ) {
if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) || 'animal' !== get_current_screen()->post_type ) {
return;
}
wp_enqueue_media();
wp_add_inline_style( 'wp-admin', '.ga-gallery-admin{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.ga-gallery-admin__item{position:relative;cursor:move}.ga-gallery-admin__item img{display:block;width:80px;height:80px;object-fit:cover;border-radius:6px}.ga-gallery-admin__item button{position:absolute;top:-6px;right:-6px;width:22px;height:22px;border-radius:50%;border:0;background:#b32d2e;color:#fff;cursor:pointer;line-height:1}' );
wp_add_inline_script( 'media-editor', <<<'JS'
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('.ga-gallery-admin').forEach(function (box) {
var input = document.getElementById(box.dataset.input);
var sync = function () {
input.value = Array.from(box.querySelectorAll('[data-id]')).map(function (el) { return el.dataset.id; }).join(',');
};
box.addEventListener('click', function (e) {
if (e.target.tagName === 'BUTTON') { e.target.parentNode.remove(); sync(); }
});
box.nextElementSibling.addEventListener('click', function () {
var frame = wp.media({ title: 'Fotos del animal', multiple: 'add', library: { type: 'image' }, button: { text: 'Añadir a la ficha' } });
frame.on('select', function () {
frame.state().get('selection').each(function (att) {
if (box.querySelector('[data-id="' + att.id + '"]')) return;
var src = (att.get('sizes') && att.get('sizes').thumbnail ? att.get('sizes').thumbnail.url : att.get('url'));
var item = document.createElement('span');
item.className = 'ga-gallery-admin__item';
item.dataset.id = att.id;
item.innerHTML = '<img src="' + src + '" alt=""><button type="button" aria-label="Quitar">×</button>';
box.appendChild(item);
});
sync();
});
frame.open();
});
});
});
JS
);
} );
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 = wp_unslash( $_POST[ "ga_$key" ] ?? '' );
$value = match ( $f['type'] ) {
'select' => isset( $f['options'][ $raw ] ) ? $raw : '',
'checkbox' => $raw ? '1' : '',
'textarea' => sanitize_textarea_field( $raw ),
'gallery' => implode( ',', array_filter( array_map( 'absint', explode( ',', $raw ) ) ) ),
'url' => esc_url_raw( $raw ),
'number' => '' === $raw ? '' : (string) absint( $raw ),
'date' => preg_match( '/^\d{4}-\d{2}-\d{2}$/', $raw ) ? $raw : '',
default => sanitize_text_field( $raw ),
};
if ( ! empty( $f['shared'] ) ) {
ga_update_meta_all_languages( $post_id, "_ga_$key", $value );
} else {
update_post_meta( $post_id, "_ga_$key", $value );
}
}
} );
/** Guarda un campo común 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 );
}
}
/* Polylang: al crear o sincronizar traducciones, no copiar los textos (se escriben en cada idioma). */
add_filter( 'pll_copy_post_metas', function ( $metas, $sync ) {
$texts = array_map( fn( $k ) => "_ga_$k", array_keys( array_filter( ga_fields(), fn( $f ) => empty( $f['shared'] ) ) ) );
return $sync ? array_values( array_diff( $metas, $texts ) ) : $metas;
}, 10, 2 );
/* Columnas del listado del panel */
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_destacado'] = '★';
}
}
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' ) );
}
}, 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__( 'Adopta', 'Adoptatu' );
}
return $parts;
} );
/* -------------------------------------------------------------------------
* Consultas
* ---------------------------------------------------------------------- */
/** meta_query de los estados visibles en los listados. */
function ga_visible_meta_query() {
$hidden = array( 'adoptado' );
if ( ! ga_setting( 'adopcion', 'show_in_process', true ) ) {
$hidden = array_merge( $hidden, array( 'proceso', 'reservado' ) );
}
return array(
'relation' => 'OR',
array( 'key' => '_ga_estado', 'value' => $hidden, 'compare' => 'NOT IN' ),
array( 'key' => '_ga_estado', 'compare' => 'NOT EXISTS' ),
);
}
/** Orden de los listados según el ajuste «Orden». */
function ga_order_args() {
return 'antiguos' === ga_setting( 'adopcion', 'order', 'recientes' )
? array( 'orderby' => 'date', 'order' => 'ASC' )
: array( 'orderby' => 'date', 'order' => 'DESC' );
}
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;
}
$q->set( 'meta_query', array( ga_visible_meta_query() ) );
$q->set( 'posts_per_page', 24 );
foreach ( ga_order_args() as $k => $v ) {
$q->set( $k, $v );
}
} );
/**
* Consulta reutilizable de animales (Polylang filtra por el idioma actual).
*
* @param array $args numero, especie (slugs), estado (lista o 'adoptado'), destacados (bool).
*/
function ga_query_animals( $args = array() ) {
$args = wp_parse_args( $args, array( 'numero' => 6, 'especie' => '', 'estado' => '', 'destacados' => false, 'apadrinables' => false ) );
$query = array(
'post_type' => 'animal',
'posts_per_page' => (int) $args['numero'],
'no_found_rows' => true,
) + ga_order_args();
if ( $args['especie'] ) {
$query['tax_query'] = array( array(
'taxonomy' => 'especie',
'field' => 'slug',
'terms' => array_map( 'trim', explode( ',', $args['especie'] ) ),
) );
}
$meta = array();
if ( $args['estado'] ) {
$meta[] = array( 'key' => '_ga_estado', 'value' => array_map( 'trim', explode( ',', $args['estado'] ) ), 'compare' => 'IN' );
} else {
$meta[] = ga_visible_meta_query();
}
if ( $args['destacados'] ) {
$meta[] = array( 'key' => '_ga_destacado', 'value' => '1' );
}
if ( $args['apadrinables'] ) {
$meta[] = array( 'key' => '_ga_apadrinable', 'value' => '1' );
}
$query['meta_query'] = $meta;
$q = new WP_Query( $query );
// Si no hay destacados marcados, se muestran los que llevan más tiempo esperando.
if ( $args['destacados'] && ! $q->have_posts() ) {
unset( $query['meta_query'][1] );
$query['orderby'] = 'date';
$query['order'] = 'ASC';
$q = new WP_Query( $query );
}
return $q;
}
/* [ga_animales numero="6" especie="perro" destacados="1" vista="carrusel"] */
add_shortcode( 'ga_animales', function ( $atts ) {
$atts = shortcode_atts( array( 'numero' => 6, 'especie' => '', 'estado' => '', 'destacados' => '', 'apadrinables' => '', 'vista' => 'rejilla' ), $atts, 'ga_animales' );
foreach ( array( 'destacados', 'apadrinables' ) as $flag ) {
$atts[ $flag ] = in_array( $atts[ $flag ], array( '1', 'si', 'true' ), true );
}
$q = ga_query_animals( $atts );
ob_start();
if ( $q->have_posts() ) {
$carousel = 'carrusel' === $atts['vista'];
$carousel ? ga_carousel_open() : print( '<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' ) )
);
}
/**
* Cierre del carrusel: última tarjeta «Ver todos», botones con texto y contador («1–3 / 10»).
*
* @param string|false $more_url Enlace de la última tarjeta (por defecto, la página Adopta); false = sin ella.
*/
function ga_carousel_close( $more_url = null ) {
$more_url = null === $more_url ? get_post_type_archive_link( 'animal' ) : $more_url;
$arrow = function_exists( 'ga_icon' ) ? ga_icon( 'arrow' ) : '→';
if ( $more_url ) {
printf(
'<a class="ga-carousel__more" href="%s">%s<span>%s</span>%s</a>',
esc_url( $more_url ),
function_exists( 'ga_icon' ) ? ga_icon( 'paw' ) : '',
esc_html( ga__( 'Ver todos los animales', 'Animalia guztiak ikusi' ) ),
$arrow // SVG estático del tema.
);
}
printf(
'</div><div class="ga-carousel__nav"><button type="button" class="ga-carousel__btn" data-dir="-1">%1$s<span>%2$s</span></button>'
. '<span class="ga-carousel__count" aria-live="polite"></span>'
. '<button type="button" class="ga-carousel__btn" data-dir="1"><span>%3$s</span>%1$s</button></div></div>',
$arrow, // SVG estático del tema.
esc_html( ga__( 'Anteriores', 'Aurrekoak' ) ),
esc_html( ga__( 'Siguientes', 'Hurrengoak' ) )
);
}
/** Tarjeta de un animal (dentro del loop). El tema la define en 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() ) );
}