Files
Josep Piguillem 4acc8b62d1 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>
2026-09-24 22:16:24 +02:00

299 lines
14 KiB
PHP

<?php
/**
* Patrones de bloques (secciones prediseñadas) y estilos de bloque propios.
*
* Cada patrón se registra en castellano y en euskera. En el editor aparecen en
* Añadir bloque (+) → Patrones → «Gure Ametsa».
*/
defined( 'ABSPATH' ) || exit;
/* ---------- Estilos de bloque (panel lateral «Estilos» del editor) ---------- */
add_action( 'init', function () {
$styles = array(
'core/group' => array(
'ga-arena' => 'Fondo arena',
'ga-verde' => 'Fondo principal',
'ga-tarjeta' => 'Tarjeta',
'ga-aviso' => 'Aviso destacado',
),
'core/paragraph' => array(
'ga-antetitulo' => 'Antetítulo',
'ga-entradilla' => 'Entradilla',
),
'core/image' => array(
'ga-redondeada' => 'Esquinas redondeadas',
'ga-arco' => 'Arco',
),
'core/list' => array(
'ga-check' => 'Con marcas ✓',
'ga-pasos' => 'Pasos numerados',
'ga-limpia' => 'Sin viñetas',
),
'core/quote' => array(
'ga-testimonio' => 'Testimonio',
),
'core/columns' => array(
'ga-tarjetas' => 'Columnas como tarjetas',
),
);
foreach ( $styles as $block => $list ) {
foreach ( $list as $name => $label ) {
register_block_style( $block, array( 'name' => $name, 'label' => $label ) );
}
}
} );
/* ---------- Patrones ---------- */
add_action( 'init', function () {
register_block_pattern_category( 'gure-ametsa', array( 'label' => 'Gure Ametsa' ) );
foreach ( array( 'es', 'eu' ) as $lang ) {
$t = fn( $es, $eu ) => 'eu' === $lang ? $eu : $es;
$url = fn( $slug_es, $slug_eu ) => 'eu' === $lang ? "/eu/$slug_eu/" : "/$slug_es/";
$sfx = 'eu' === $lang ? ' (euskara)' : '';
foreach ( ga_pattern_definitions( $t, $url ) as $slug => [ $title, $description, $content ] ) {
register_block_pattern( "gure-ametsa/$slug-$lang", array(
'title' => $title . $sfx,
'description' => $description,
'categories' => array( 'gure-ametsa' ),
'content' => $content,
) );
}
}
} );
/** Botón de bloque. */
function ga_p_button( $text, $href, $outline = false ) {
$attrs = $outline ? ' {"className":"is-style-outline"}' : '';
$class = $outline ? ' is-style-outline' : '';
return "<!-- wp:button$attrs -->\n<div class=\"wp-block-button$class\"><a class=\"wp-block-button__link wp-element-button\" href=\"" . esc_url( $href ) . "\">$text</a></div>\n<!-- /wp:button -->";
}
function ga_p_buttons( array $buttons, $center = false ) {
$attrs = $center ? ' {"layout":{"type":"flex","justifyContent":"center"}}' : '';
return "<!-- wp:buttons$attrs -->\n<div class=\"wp-block-buttons\">" . implode( "\n\n", $buttons ) . "</div>\n<!-- /wp:buttons -->";
}
function ga_p_heading( $text, $level = 2, $center = false, $anchor = '' ) {
$attrs = array();
if ( 2 !== $level ) {
$attrs['level'] = $level;
}
if ( $center ) {
$attrs['textAlign'] = 'center';
}
if ( $anchor ) {
$attrs['anchor'] = $anchor;
}
$json = $attrs ? ' ' . wp_json_encode( $attrs ) : '';
$class = 'wp-block-heading' . ( $center ? ' has-text-align-center' : '' );
$id = $anchor ? ' id="' . esc_attr( $anchor ) . '"' : '';
return "<!-- wp:heading$json -->\n<h$level class=\"$class\"$id>$text</h$level>\n<!-- /wp:heading -->";
}
function ga_p_paragraph( $text, $style = '', $center = false ) {
$attrs = array();
if ( $center ) {
$attrs['align'] = 'center';
}
if ( $style ) {
$attrs['className'] = "is-style-$style";
}
$json = $attrs ? ' ' . wp_json_encode( $attrs ) : '';
$classes = trim( ( $center ? 'has-text-align-center ' : '' ) . ( $style ? "is-style-$style" : '' ) );
$class = $classes ? " class=\"$classes\"" : '';
return "<!-- wp:paragraph$json -->\n<p$class>$text</p>\n<!-- /wp:paragraph -->";
}
function ga_p_list( array $items, $style = '', $ordered = false ) {
$attrs = array();
if ( $ordered ) {
$attrs['ordered'] = true;
}
if ( $style ) {
$attrs['className'] = "is-style-$style";
}
$json = $attrs ? ' ' . wp_json_encode( $attrs ) : '';
$tag = $ordered ? 'ol' : 'ul';
$lis = array_map( fn( $i ) => "<!-- wp:list-item -->\n<li>$i</li>\n<!-- /wp:list-item -->", $items );
$cls = 'wp-block-list' . ( $style ? " is-style-$style" : '' );
return "<!-- wp:list$json -->\n<$tag class=\"$cls\">" . implode( "\n\n", $lis ) . "</$tag>\n<!-- /wp:list -->";
}
function ga_p_group( $inner, $style = '', $full = false ) {
$attrs = array();
if ( $full ) {
$attrs['align'] = 'full';
}
$classes = array_filter( array( $style ? "is-style-$style" : '', $full ? 'ga-pad' : '' ) );
if ( $classes ) {
$attrs['className'] = implode( ' ', $classes );
}
$attrs['layout'] = array( 'type' => 'constrained' );
$html_classes = implode( ' ', array_filter( array( 'wp-block-group', $full ? 'alignfull' : '', ...$classes ) ) );
return '<!-- wp:group ' . wp_json_encode( $attrs ) . " -->\n<div class=\"$html_classes\">$inner</div>\n<!-- /wp:group -->";
}
function ga_p_columns( array $columns, $style = '', $wide = true ) {
$attrs = array();
if ( $wide ) {
$attrs['align'] = 'wide';
}
if ( $style ) {
$attrs['className'] = "is-style-$style";
}
$json = $attrs ? ' ' . wp_json_encode( $attrs ) : '';
$class = trim( 'wp-block-columns' . ( $wide ? ' alignwide' : '' ) . ( $style ? " is-style-$style" : '' ) );
$cols = array_map( fn( $c ) => "<!-- wp:column -->\n<div class=\"wp-block-column\">$c</div>\n<!-- /wp:column -->", $columns );
return "<!-- wp:columns$json -->\n<div class=\"$class\">" . implode( "\n\n", $cols ) . "</div>\n<!-- /wp:columns -->";
}
function ga_p_shortcode( $code ) {
return "<!-- wp:shortcode -->\n$code\n<!-- /wp:shortcode -->";
}
/**
* Definición de patrones: slug => [título, descripción, contenido].
*
* @param callable $t Traductor fn( $es, $eu ).
* @param callable $url URL de página fn( $slug_es, $slug_eu ).
*/
function ga_pattern_definitions( $t, $url ) {
$adopta = $url( 'adopta', 'adopta' );
$contacto = $url( 'contacto', 'harremanetarako' ) . '#formulario';
$colabora = $url( 'colabora', 'lagundu' );
return array(
'portada' => array(
$t( 'Portada con imagen', 'Azala irudiarekin' ),
'Bloque de bienvenida a ancho completo con título, texto, botones e imagen.',
ga_p_group(
ga_p_columns( array(
ga_p_paragraph( $t( 'Protectora · Hondarribia', 'Babeslekua · Hondarribia' ), 'ga-antetitulo' )
. "\n\n" . ga_p_heading( $t( 'Adopta y cambia dos mundos', 'Adoptatu eta bi mundu aldatu' ) )
. "\n\n" . ga_p_paragraph( $t( 'Rescatamos, cuidamos y buscamos una segunda oportunidad para perros y gatos abandonados.', 'Abandonatutako txakur eta katuak erreskatatu, zaindu eta bigarren aukera bat bilatzen diegu.' ), 'ga-entradilla' )
. "\n\n" . ga_p_buttons( array(
ga_p_button( $t( 'Conoce a los animales', 'Ezagutu animaliak' ), $adopta ),
ga_p_button( $t( 'Quiero ayudar', 'Lagundu nahi dut' ), $colabora, true ),
) ),
"<!-- wp:image {\"sizeSlug\":\"large\",\"className\":\"is-style-ga-arco\"} -->\n<figure class=\"wp-block-image size-large is-style-ga-arco\"><img alt=\"\"/></figure>\n<!-- /wp:image -->",
) ),
'ga-arena',
true
),
),
'llamada' => array(
$t( 'Llamada a la acción', 'Ekintzarako deia' ),
'Franja de color con título, texto y botón centrados.',
ga_p_group(
ga_p_heading( $t( '¿Tienes sitio en casa… y en tu corazón?', 'Lekua duzu etxean… eta bihotzean?' ), 2, true )
. "\n\n" . ga_p_paragraph( $t( 'Cada adopción deja una plaza libre para rescatar a otro animal.', 'Adopzio bakoitzak beste animalia bat erreskatatzeko lekua uzten du.' ), '', true )
. "\n\n" . ga_p_buttons( array( ga_p_button( $t( 'Quiero adoptar', 'Adoptatu nahi dut' ), $contacto ) ), true ),
'ga-verde',
true
),
),
'tarjetas' => array(
$t( 'Tres tarjetas', 'Hiru txartel' ),
'Tres columnas con icono, título y texto.',
ga_p_columns( array(
ga_p_heading( $t( 'Adopta', 'Adoptatu' ), 3 ) . "\n\n" . ga_p_paragraph( $t( 'Conoce a los perros y gatos que esperan una familia.', 'Ezagutu familia baten zain dauden txakur eta katuak.' ) ),
ga_p_heading( $t( 'Acoge', 'Harrera egin' ), 3 ) . "\n\n" . ga_p_paragraph( $t( 'Ofrece un hogar durante un tiempo a quien lo necesita.', 'Eskaini etxe bat denbora batez behar duenari.' ) ),
ga_p_heading( $t( 'Colabora', 'Lagundu' ), 3 ) . "\n\n" . ga_p_paragraph( $t( 'Voluntariado o ayuda material.', 'Boluntariotza edo laguntza materiala.' ) ),
), 'ga-tarjetas' ),
),
'pasos' => array(
$t( 'Pasos numerados', 'Urrats zenbakidunak' ),
'Lista de pasos con números grandes.',
ga_p_heading( $t( '¿Cómo adoptar?', 'Nola adoptatu?' ) )
. "\n\n" . ga_p_list( array(
$t( '<strong>Elige.</strong> Mira las fichas o ven a conocernos.', '<strong>Aukeratu.</strong> Begiratu fitxak edo etorri gu ezagutzera.' ),
$t( '<strong>Escríbenos.</strong> Hablaremos sobre tu casa y tu rutina.', '<strong>Idatzi iezaguzu.</strong> Zure etxeaz eta ohiturez hitz egingo dugu.' ),
$t( '<strong>Conócelo.</strong> Visitas y paseos sin prisas.', '<strong>Ezagutu.</strong> Bisitak eta ibilaldiak, presarik gabe.' ),
$t( '<strong>¡A casa!</strong> Firmamos la adopción y seguimos a tu lado.', '<strong>Etxera!</strong> Adopzioa sinatu eta zure ondoan jarraituko dugu.' ),
), 'ga-pasos', true ),
),
'animales' => array(
$t( 'Animales en adopción', 'Adopzioko animaliak' ),
'Rejilla automática con los últimos animales en adopción.',
ga_p_heading( $t( 'Te están esperando', 'Zure zain daude' ) )
. "\n\n" . ga_p_shortcode( '[ga_animales numero="4"]' )
. "\n\n" . ga_p_buttons( array( ga_p_button( $t( 'Ver todos', 'Denak ikusi' ), $adopta ) ) ),
),
'carrusel' => array(
$t( 'Carrusel de animales', 'Animalien karrusela' ),
'Animales en adopción en un carrusel que se desliza.',
ga_p_heading( $t( 'Te están esperando', 'Zure zain daude' ) )
. "\n\n" . ga_p_shortcode( '[ga_animales numero="10" vista="carrusel"]' )
. "\n\n" . ga_p_buttons( array( ga_p_button( $t( 'Ver todos', 'Denak ikusi' ), $adopta ) ) ),
),
'urgentes' => array(
$t( 'Adopciones urgentes', 'Adopzio premiazkoak' ),
'Rejilla automática solo con urgentes y animales que buscan acogida.',
ga_p_group(
ga_p_heading( $t( 'Nos necesitan ya', 'Orain behar gaituzte' ) )
. "\n\n" . ga_p_paragraph( $t( 'Mayores, convalecientes o que llevan demasiado tiempo esperando.', 'Adinekoak, gaixorik daudenak edo denbora gehiegi daramatenak zain.' ) )
. "\n\n" . ga_p_shortcode( '[ga_animales numero="3" estado="urgente,acogida"]' ),
'ga-aviso'
),
),
'imagen-texto' => array(
$t( 'Imagen y texto', 'Irudia eta testua' ),
'Imagen a un lado y texto al otro.',
ga_p_columns( array(
"<!-- wp:image {\"sizeSlug\":\"large\",\"className\":\"is-style-ga-redondeada\"} -->\n<figure class=\"wp-block-image size-large is-style-ga-redondeada\"><img alt=\"\"/></figure>\n<!-- /wp:image -->",
ga_p_paragraph( $t( 'Nuestra historia', 'Gure historia' ), 'ga-antetitulo' )
. "\n\n" . ga_p_heading( $t( 'Más de 25 años cuidando', '25 urte baino gehiago zaintzen' ) )
. "\n\n" . ga_p_paragraph( $t( 'Escribe aquí vuestra historia, un rescate especial o cómo es el día a día en el refugio.', 'Idatzi hemen zuen historia, erreskate berezi bat edo babeslekuko eguneroko bizitza.' ) ),
) ),
),
'testimonio' => array(
$t( 'Testimonio de adopción', 'Adopzio-testigantza' ),
'Cita destacada de una familia adoptante.',
"<!-- wp:quote {\"className\":\"is-style-ga-testimonio\"} -->\n<blockquote class=\"wp-block-quote is-style-ga-testimonio\">"
. ga_p_paragraph( $t( 'Llegó asustado y hoy es el rey del sofá. Adoptarle ha sido lo mejor que nos ha pasado.', 'Beldurtuta iritsi zen eta gaur sofako erregea da. Adoptatzea gertatu zaigun onena izan da.' ) )
. '<cite>' . $t( 'Familia de Txuri, Irun', 'Txuriren familia, Irun' ) . "</cite></blockquote>\n<!-- /wp:quote -->",
),
'preguntas' => array(
$t( 'Preguntas frecuentes', 'Ohiko galderak' ),
'Preguntas desplegables.',
ga_p_heading( $t( 'Preguntas frecuentes', 'Ohiko galderak' ) )
. "\n\n" . implode( "\n\n", array_map(
fn( $qa ) => "<!-- wp:details -->\n<details class=\"wp-block-details\"><summary>{$qa[0]}</summary>" . ga_p_paragraph( $qa[1] ) . "</details>\n<!-- /wp:details -->",
array(
array( $t( '¿Cuánto cuesta adoptar?', 'Zenbat balio du adoptatzeak?' ), $t( 'Escribe aquí la respuesta.', 'Idatzi hemen erantzuna.' ) ),
array( $t( '¿Puedo adoptar si vivo en un piso?', 'Adopta dezaket pisu batean bizi banaiz?' ), $t( 'Escribe aquí la respuesta.', 'Idatzi hemen erantzuna.' ) ),
array( $t( '¿Hacéis seguimiento después?', 'Jarraipena egiten duzue gero?' ), $t( 'Escribe aquí la respuesta.', 'Idatzi hemen erantzuna.' ) ),
)
) ),
),
'donaciones' => array(
$t( 'Qué necesitamos', 'Zer behar dugu' ),
'Tarjeta con la lista de ayuda material (se edita en Personalizar → Adopción y colabora → Ayuda material).',
ga_p_group(
ga_p_heading( $t( 'Qué necesitamos ahora', 'Zer behar dugun orain' ), 3 )
. "\n\n" . ga_p_shortcode( '[ga_necesidades]' )
. "\n\n" . ga_p_buttons( array( ga_p_button( $t( 'Escríbenos antes de traerlo', 'Idatzi iezaguzu ekarri aurretik' ), $url( 'contacto', 'harremanetarako' ) . '?motivo=material#formulario' ) ) ),
'ga-tarjeta'
),
),
'contacto' => array(
$t( 'Contacto con formulario', 'Harremana formularioarekin' ),
'Datos de contacto y formulario en dos columnas.',
ga_p_columns( array(
ga_p_heading( $t( 'Ven a vernos', 'Etorri gu ikustera' ), 3 )
. "\n\n" . ga_p_list( array(
'Jaizubia, 44 · 20280 Hondarribia',
'<a href="tel:+34943645279">943 64 52 79</a>',
'<a href="mailto:hola@gureametsabilagun.org">hola@gureametsabilagun.org</a>',
$t( 'Con cita previa', 'Aurretiko hitzorduarekin' ),
), 'ga-limpia' ),
ga_p_heading( $t( 'Escríbenos', 'Idatzi iezaguzu' ), 3, false, 'formulario' )
. "\n\n" . ga_p_shortcode( '[ga_contacto]' ),
) ),
),
);
}