- 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>
193 lines
6.6 KiB
PHP
193 lines
6.6 KiB
PHP
<?php
|
|
/**
|
|
* Personalizador: colores, tipografías, cabecera, contacto, portada y pie.
|
|
*
|
|
* Todas las opciones se definen en ga_customizer_registry(). Los textos marcados
|
|
* como 'i18n' se guardan dos veces: en castellano (clave) y en euskera (clave + '_eu').
|
|
*/
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
require_once __DIR__ . '/registry.php';
|
|
|
|
/** Color efectivo: el de la paleta elegida o, si es «Personalizada», el elegido a mano. */
|
|
function ga_color( $key ) {
|
|
$palette = ga_opt( 'colors', 'palette' );
|
|
$palettes = ga_palettes();
|
|
if ( isset( $palettes[ $palette ][ $key ] ) ) {
|
|
return $palettes[ $palette ][ $key ];
|
|
}
|
|
return ga_opt( 'colors', $key );
|
|
}
|
|
|
|
/** Clave del theme_mod para un campo (y un idioma). */
|
|
function ga_mod_key( $section, $field, $lang = 'es' ) {
|
|
return "ga_{$section}_{$field}" . ( 'eu' === $lang ? '_eu' : '' );
|
|
}
|
|
|
|
/** Valor por defecto de un campo. */
|
|
function ga_field_default( $field, $lang = 'es' ) {
|
|
if ( ! empty( $field['i18n'] ) ) {
|
|
return $field[ $lang ] ?? '';
|
|
}
|
|
return $field['default'] ?? '';
|
|
}
|
|
|
|
/**
|
|
* Valor de una opción. Los textos 'i18n' se devuelven en el idioma actual.
|
|
*/
|
|
function ga_opt( $section, $field ) {
|
|
$registry = ga_customizer_registry();
|
|
$def = $registry[ $section ]['fields'][ $field ] ?? null;
|
|
if ( ! $def ) {
|
|
return '';
|
|
}
|
|
$lang = ! empty( $def['i18n'] ) ? ga_lang() : 'es';
|
|
$key = ga_mod_key( $section, $field, $lang );
|
|
return get_theme_mod( $key, ga_field_default( $def, $lang ) );
|
|
}
|
|
|
|
/** Imprime un texto del personalizador escapado. */
|
|
function ga_opt_e( $section, $field ) {
|
|
echo esc_html( ga_opt( $section, $field ) );
|
|
}
|
|
|
|
/** Secciones de portada visibles, ordenadas. */
|
|
function ga_home_sections() {
|
|
$sections = array();
|
|
foreach ( ga_customizer_registry() as $id => $section ) {
|
|
if ( ! empty( $section['section'] ) && ga_opt( $id, 'show' ) ) {
|
|
$sections[ $id ] = (int) ga_opt( $id, 'order' );
|
|
}
|
|
}
|
|
asort( $sections );
|
|
return array_keys( $sections );
|
|
}
|
|
|
|
/* Los datos de contacto y redes del personalizador sustituyen a los predeterminados. */
|
|
add_filter( 'ga_info', function ( $info ) {
|
|
foreach ( array( 'direccion', 'maps', 'telefono', 'email', 'horario', 'cita' ) as $key ) {
|
|
$info[ $key ] = ga_opt( 'contact', $key );
|
|
}
|
|
foreach ( array( 'instagram', 'facebook', 'tiktok', 'youtube', 'whatsapp' ) as $key ) {
|
|
$info[ $key ] = ga_opt( 'social', $key );
|
|
}
|
|
return $info;
|
|
} );
|
|
|
|
/* ---------- Registro en el personalizador ---------- */
|
|
add_action( 'customize_register', function ( WP_Customize_Manager $c ) {
|
|
$c->add_panel( 'ga_design', array( 'title' => 'Diseño (Gure Ametsa)', 'priority' => 25 ) );
|
|
$c->add_panel( 'ga_info', array( 'title' => 'Contacto y redes', 'priority' => 26 ) );
|
|
$c->add_panel( 'ga_adopt', array( 'title' => 'Adopción y colabora', 'priority' => 26 ) );
|
|
$c->add_panel( 'ga_home', array(
|
|
'title' => 'Portada',
|
|
'priority' => 27,
|
|
'description' => 'Muestra, oculta y reordena las secciones de la portada. Los textos se escriben en castellano y en euskera.',
|
|
) );
|
|
|
|
$sanitizers = array(
|
|
'text' => 'sanitize_text_field',
|
|
'textarea' => 'sanitize_textarea_field',
|
|
'url' => 'esc_url_raw',
|
|
'email' => 'sanitize_email',
|
|
'color' => 'sanitize_hex_color',
|
|
'checkbox' => fn( $v ) => (bool) $v,
|
|
'number' => 'absint',
|
|
'range' => 'absint',
|
|
'image' => 'absint',
|
|
'video' => 'absint',
|
|
);
|
|
|
|
foreach ( ga_customizer_registry() as $sid => $section ) {
|
|
$section_id = "ga_section_$sid";
|
|
$c->add_section( $section_id, array(
|
|
'title' => $section['title'],
|
|
'panel' => $section['panel'],
|
|
'description' => $section['description'] ?? '',
|
|
) );
|
|
|
|
foreach ( $section['fields'] as $fid => $field ) {
|
|
$langs = ! empty( $field['i18n'] ) ? array( 'es', 'eu' ) : array( 'es' );
|
|
foreach ( $langs as $lang ) {
|
|
$key = ga_mod_key( $sid, $fid, $lang );
|
|
$sanitize = $sanitizers[ $field['type'] ] ?? null;
|
|
if ( 'select' === $field['type'] ) {
|
|
$choices = $field['choices'];
|
|
$default = $field['default'];
|
|
$sanitize = fn( $v ) => array_key_exists( $v, $choices ) ? $v : $default;
|
|
}
|
|
$c->add_setting( $key, array(
|
|
'default' => ga_field_default( $field, $lang ),
|
|
'sanitize_callback' => $sanitize,
|
|
) );
|
|
|
|
$label = $field['label'] . ( ! empty( $field['i18n'] ) ? ( 'eu' === $lang ? ' · EU' : ' · ES' ) : '' );
|
|
$args = array(
|
|
'label' => $label,
|
|
'section' => $section_id,
|
|
'description' => $field['description'] ?? '',
|
|
'priority' => empty( $field['i18n'] ) ? 50 : ( 'eu' === $lang ? 200 : 100 ),
|
|
);
|
|
|
|
switch ( $field['type'] ) {
|
|
case 'color':
|
|
$c->add_control( new WP_Customize_Color_Control( $c, $key, $args ) );
|
|
break;
|
|
case 'image':
|
|
case 'video':
|
|
$c->add_control( new WP_Customize_Media_Control( $c, $key, $args + array( 'mime_type' => $field['type'] ) ) );
|
|
break;
|
|
case 'range':
|
|
case 'number':
|
|
$args['type'] = $field['type'];
|
|
$args['input_attrs'] = array_filter( array(
|
|
'min' => $field['min'] ?? null,
|
|
'max' => $field['max'] ?? null,
|
|
'step' => $field['step'] ?? 1,
|
|
), fn( $v ) => null !== $v );
|
|
if ( 'range' === $field['type'] ) {
|
|
$args['description'] = trim( $args['description'] . ' Por defecto: ' . $field['default'] . '.' );
|
|
}
|
|
$c->add_control( $key, $args );
|
|
break;
|
|
case 'select':
|
|
$c->add_control( $key, $args + array( 'type' => 'select', 'choices' => $field['choices'] ) );
|
|
break;
|
|
default:
|
|
$c->add_control( $key, $args + array( 'type' => $field['type'] ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Separador visual entre castellano y euskera.
|
|
$has_i18n = (bool) array_filter( $section['fields'], fn( $f ) => ! empty( $f['i18n'] ) );
|
|
if ( $has_i18n ) {
|
|
foreach ( array( 'es' => array( 99, 'Castellano' ), 'eu' => array( 199, 'Euskara' ) ) as $lang => [ $priority, $title ] ) {
|
|
$c->add_setting( "ga_sep_{$sid}_{$lang}", array( 'sanitize_callback' => '__return_empty_string' ) );
|
|
$c->add_control( new GA_Customize_Heading_Control( $c, "ga_sep_{$sid}_{$lang}", array(
|
|
'label' => $title,
|
|
'section' => $section_id,
|
|
'priority' => $priority,
|
|
) ) );
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
add_action( 'customize_register', function () {
|
|
if ( class_exists( 'GA_Customize_Heading_Control' ) ) {
|
|
return;
|
|
}
|
|
/** Encabezado sin campo, para separar idiomas. */
|
|
class GA_Customize_Heading_Control extends WP_Customize_Control {
|
|
public $type = 'ga-heading';
|
|
public function render_content() {
|
|
printf(
|
|
'<h3 style="margin:18px 0 4px;padding:6px 10px;background:#1e5b3e;color:#fff;border-radius:4px;font-size:13px;letter-spacing:.06em;text-transform:uppercase">%s</h3>',
|
|
esc_html( $this->label )
|
|
);
|
|
}
|
|
}
|
|
}, 1 );
|