diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..55e0e07 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.env +.git +*.md +docker-compose*.yml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..227805d --- /dev/null +++ b/.env.example @@ -0,0 +1,31 @@ +# URL pública del sitio (con https y sin barra final) +WP_URL=https://gureametsabilagun.eus +WP_TITLE=Gure Ametsa Bi Lagun + +# Administrador inicial de WordPress (solo se usa en la primera instalación) +WP_ADMIN_USER=gureametsa +WP_ADMIN_PASSWORD=cambia-esta-contraseña-larga +WP_ADMIN_EMAIL=hola@gureametsabilagun.org + +# Correo que recibe los mensajes del formulario de contacto / adopción +GA_CONTACT_EMAIL=hola@gureametsabilagun.org + +# Correo saliente (formularios, avisos) vía SMTP. Vacío = configurar desde el panel (WP Mail SMTP). +# Ejemplos: Gmail/Google Workspace → smtp.gmail.com, 587, tls (con contraseña de aplicación) +# Brevo → smtp-relay.brevo.com, 587, tls +SMTP_HOST= +SMTP_PORT=587 +SMTP_ENCRYPTION=tls +SMTP_USER= +SMTP_PASSWORD= +SMTP_FROM=hola@gureametsabilagun.org + +# Base de datos +DB_NAME=wordpress +DB_USER=wordpress +DB_PASSWORD=cambia-esto +DB_ROOT_PASSWORD=cambia-esto-tambien +DB_TABLE_PREFIX=ga_ + +# true = crea 4 animales de ejemplo en la primera instalación (útil para probar) +SEED_DEMO_ANIMALS=false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3323b34 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fa294df --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM wordpress:php8.3-apache + +# Cliente MariaDB (para `wp db export/import`) y utilidades +RUN apt-get update \ + && apt-get install -y --no-install-recommends mariadb-client less unzip \ + && rm -rf /var/lib/apt/lists/* + +# WP-CLI +RUN curl -fsSL -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \ + && chmod +x /usr/local/bin/wp + +# Polylang (castellano / euskera) incluido en la imagen +ARG POLYLANG_VERSION=3.8.9 +RUN mkdir -p /usr/src/gure-ametsa/plugins \ + && curl -fsSL -o /tmp/polylang.zip "https://downloads.wordpress.org/plugin/polylang.${POLYLANG_VERSION}.zip" \ + && unzip -q /tmp/polylang.zip -d /usr/src/gure-ametsa/plugins \ + && rm /tmp/polylang.zip + +COPY docker/php.ini /usr/local/etc/php/conf.d/zz-gure-ametsa.ini + +# Código propio: se sincroniza dentro del volumen en cada arranque +COPY wp-content/themes/gure-ametsa /usr/src/gure-ametsa/themes/gure-ametsa +COPY wp-content/mu-plugins /usr/src/gure-ametsa/mu-plugins +COPY docker/content /usr/src/gure-ametsa/content +COPY docker/setup-content.php /usr/src/gure-ametsa/setup-content.php + +COPY docker/entrypoint.sh /usr/local/bin/ga-entrypoint.sh +COPY docker/setup.sh /usr/local/bin/ga-setup.sh +RUN chmod +x /usr/local/bin/ga-entrypoint.sh /usr/local/bin/ga-setup.sh + +ENTRYPOINT ["ga-entrypoint.sh"] +CMD ["apache2-foreground"] diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..7ec9901 --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,7 @@ +# Solo para desarrollo local: +# docker compose -f docker-compose.yml -f docker-compose.local.yml up --build +# y abre http://localhost:8080 +services: + wordpress: + ports: + - "8080:80" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..05f23a1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,90 @@ +# Gure Ametsa Bi Lagun — WordPress para Dokploy (Docker Compose) +# +# En Dokploy: crea un servicio "Compose", apunta a este repositorio, +# define las variables de .env.example en la pestaña "Environment" y +# añade el dominio en "Domains" (servicio: wordpress, puerto: 80). + +services: + wordpress: + build: . + image: gure-ametsa-wordpress:latest + restart: unless-stopped + init: true + depends_on: + db: + condition: service_healthy + expose: + - "80" + environment: + WORDPRESS_DB_HOST: db + WORDPRESS_DB_NAME: ${DB_NAME:-wordpress} + WORDPRESS_DB_USER: ${DB_USER:-wordpress} + WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:?Define DB_PASSWORD} + WORDPRESS_TABLE_PREFIX: ${DB_TABLE_PREFIX:-ga_} + WP_URL: ${WP_URL:?Define WP_URL (p. ej. https://gureametsabilagun.eus)} + WP_TITLE: ${WP_TITLE:-Gure Ametsa Bi Lagun} + WP_ADMIN_USER: ${WP_ADMIN_USER:-admin} + WP_ADMIN_PASSWORD: ${WP_ADMIN_PASSWORD:?Define WP_ADMIN_PASSWORD} + WP_ADMIN_EMAIL: ${WP_ADMIN_EMAIL:?Define WP_ADMIN_EMAIL} + GA_CONTACT_EMAIL: ${GA_CONTACT_EMAIL:-hola@gureametsabilagun.org} + SEED_DEMO_ANIMALS: ${SEED_DEMO_ANIMALS:-false} + SMTP_HOST: ${SMTP_HOST:-} + SMTP_PORT: ${SMTP_PORT:-587} + SMTP_ENCRYPTION: ${SMTP_ENCRYPTION:-tls} + SMTP_USER: ${SMTP_USER:-} + SMTP_PASSWORD: ${SMTP_PASSWORD:-} + SMTP_FROM: ${SMTP_FROM:-} + WORDPRESS_CONFIG_EXTRA: | + if ( getenv('WP_URL') ) { + define( 'WP_HOME', rtrim( getenv('WP_URL'), '/' ) ); + define( 'WP_SITEURL', rtrim( getenv('WP_URL'), '/' ) ); + } + define( 'FS_METHOD', 'direct' ); + define( 'DISALLOW_FILE_EDIT', true ); + define( 'WP_POST_REVISIONS', 10 ); + define( 'WP_AUTO_UPDATE_CORE', 'minor' ); + // Correo por SMTP (plugin WP Mail SMTP) si se definen las variables SMTP_* + if ( getenv('SMTP_HOST') ) { + define( 'WPMS_ON', true ); + define( 'WPMS_MAILER', 'smtp' ); + define( 'WPMS_SMTP_HOST', getenv('SMTP_HOST') ); + define( 'WPMS_SMTP_PORT', (int) ( getenv('SMTP_PORT') ?: 587 ) ); + define( 'WPMS_SSL', getenv('SMTP_ENCRYPTION') === 'none' ? '' : ( getenv('SMTP_ENCRYPTION') ?: 'tls' ) ); + define( 'WPMS_SMTP_AUTH', true ); + define( 'WPMS_SMTP_AUTOTLS', true ); + define( 'WPMS_SMTP_USER', getenv('SMTP_USER') ); + define( 'WPMS_SMTP_PASS', getenv('SMTP_PASSWORD') ); + define( 'WPMS_MAIL_FROM', getenv('SMTP_FROM') ?: getenv('SMTP_USER') ); + define( 'WPMS_MAIL_FROM_FORCE', true ); + define( 'WPMS_MAIL_FROM_NAME', 'Gure Ametsa Bi Lagun' ); + define( 'WPMS_MAIL_FROM_NAME_FORCE', true ); + } + volumes: + - wp_data:/var/www/html + healthcheck: + test: ["CMD-SHELL", "curl -fsS -o /dev/null -H 'X-Forwarded-Proto: https' http://localhost/wp-includes/images/blank.gif || exit 1"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 60s + + db: + image: mariadb:11.4 + restart: unless-stopped + environment: + MARIADB_DATABASE: ${DB_NAME:-wordpress} + MARIADB_USER: ${DB_USER:-wordpress} + MARIADB_PASSWORD: ${DB_PASSWORD:?Define DB_PASSWORD} + MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:?Define DB_ROOT_PASSWORD} + volumes: + - db_data:/var/lib/mysql + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + +volumes: + wp_data: + db_data: diff --git a/docker/content/es/aviso-legal.html b/docker/content/es/aviso-legal.html new file mode 100644 index 0000000..00c7a8d --- /dev/null +++ b/docker/content/es/aviso-legal.html @@ -0,0 +1,11 @@ + +
Texto base: complétalo con la razón social y el CIF de la entidad y revísalo con vuestra asesoría.
+ + + +En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información (LSSI-CE), se informa de que este sitio web pertenece a Gure Ametsa Bi Lagun, con domicilio en Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa). Contacto: hola@gureametsabilagun.org · 943 64 52 79.
+ + + +Los textos e imágenes de esta web pertenecen a Gure Ametsa Bi Lagun y no pueden reproducirse sin autorización, salvo para difundir a los animales en adopción citando la fuente.
+ diff --git a/docker/content/es/colabora.html b/docker/content/es/colabora.html new file mode 100644 index 0000000..5cdf1ca --- /dev/null +++ b/docker/content/es/colabora.html @@ -0,0 +1,63 @@ + +Cada ayuda cuenta. Estas son las formas en las que puedes cambiar la vida de nuestros animales:
+ + + +Adoptar es la forma más directa de salvar una vida. Consulta los animales en adopción, ven a conocerlos y te acompañaremos en todo el proceso. Todos se entregan con microchip, vacunados y esterilizados.
+ + + +Algunos animales necesitan salir del centro cuanto antes: cachorros, mayores o convalecientes. Como casa de acogida les ofreces un hogar temporal mientras encuentran su familia definitiva. Nosotros te orientamos en todo momento.
+ + + +Pasear perros, socializar gatos, ayudar en jornadas de adopción, hacer fotos para las fichas o difundir en redes sociales. Si tienes tiempo y ganas, ¡te necesitamos!
+ + + +Siempre nos vienen bien:
+ + + +Si prefieres hacer una aportación económica, escríbenos y te indicamos cómo.
+ + + + + diff --git a/docker/content/es/contacto.html b/docker/content/es/contacto.html new file mode 100644 index 0000000..1372b74 --- /dev/null +++ b/docker/content/es/contacto.html @@ -0,0 +1,15 @@ + +📍 Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa)
📞 943 64 52 79
✉️ hola@gureametsabilagun.org
🕙 Lunes a viernes: 10:00–13:00 y 14:00–19:00
Para adopciones, acogidas, voluntariado o reservas del hotel, déjanos tu mensaje y te responderemos lo antes posible.
+ + + +[ga_contacto] + diff --git a/docker/content/es/hotel.html b/docker/content/es/hotel.html new file mode 100644 index 0000000..7f934c9 --- /dev/null +++ b/docker/content/es/hotel.html @@ -0,0 +1,35 @@ + +¿Planeas unas vacaciones y no puedes llevar a tu compañero? En Gure Ametsa Bi Lagun cuidamos de tu perro o gato mientras estás fuera, en nuestras instalaciones de Jaizubia (Hondarribia), rodeadas de naturaleza.
+ + + +Para reservar es necesario que el animal tenga el microchip y las vacunas al día. Las plazas se llenan en verano y fechas señaladas: reserva con antelación.
+ + + + + diff --git a/docker/content/es/inicio.html b/docker/content/es/inicio.html new file mode 100644 index 0000000..b12ead6 --- /dev/null +++ b/docker/content/es/inicio.html @@ -0,0 +1,7 @@ + +Gure Ametsa Bi Lagun es la protectora y residencia de animales de Hondarribia. Desde hace más de 25 años colaboramos con los ayuntamientos de Irun y Hondarribia recogiendo a los animales perdidos o abandonados, dándoles atención veterinaria y cuidándolos hasta que encuentran una familia.
+ diff --git a/docker/content/es/privacidad.html b/docker/content/es/privacidad.html new file mode 100644 index 0000000..2256803 --- /dev/null +++ b/docker/content/es/privacidad.html @@ -0,0 +1,43 @@ + +Texto base: revísalo con vuestra asesoría antes de publicar la web y completa los datos del responsable (razón social y CIF).
+ + + +Gure Ametsa Bi Lagun · Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa) · hola@gureametsabilagun.org · 943 64 52 79.
+ + + +Los datos que nos envías a través del formulario de contacto (nombre, email, teléfono y mensaje) se usan únicamente para responder a tu consulta y, en su caso, gestionar la adopción, acogida, voluntariado o reserva que solicites. La base legal es tu consentimiento.
+ + + +Conservamos los datos el tiempo necesario para atender tu solicitud y cumplir las obligaciones legales. No se ceden a terceros salvo obligación legal.
+ + + +Puedes ejercer tus derechos de acceso, rectificación, supresión, oposición, limitación y portabilidad escribiendo a hola@gureametsabilagun.org. También puedes reclamar ante la Agencia Española de Protección de Datos (www.aepd.es).
+ + + +Esta web solo utiliza cookies técnicas necesarias para su funcionamiento. No utilizamos cookies de analítica ni de publicidad.
+ diff --git a/docker/content/es/quienes-somos.html b/docker/content/es/quienes-somos.html new file mode 100644 index 0000000..1a9f132 --- /dev/null +++ b/docker/content/es/quienes-somos.html @@ -0,0 +1,43 @@ + +Gure Ametsa Bi Lagun (en euskera, «nuestro sueño, dos amigos») es un centro de protección y residencia de animales situado en Jaizubia, Hondarribia.
+ + + +Trabajamos desde hace más de 25 años con los ayuntamientos de Irun y Hondarribia. Cuando la Policía Municipal encuentra un animal perdido o abandonado en la vía pública, lo trae a nuestras instalaciones. Aquí pasa un control veterinario y permanece alojado y cuidado hasta que vuelve con su familia o encuentra una nueva.
+ + + +Cumpliendo la Ley de Bienestar Animal, todos los animales reciben los tratamientos necesarios antes de ser adoptados:
+ + + +++ + + +Adopta y cambia dos mundos: el suyo y el tuyo.
+
Si has perdido a tu perro o gato en Irun u Hondarribia, llámanos cuanto antes al 943 64 52 79 y avisa también a la Policía Municipal. Tener el microchip actualizado es la mejor forma de que vuelva a casa.
+ diff --git a/docker/content/eu/harremanetarako.html b/docker/content/eu/harremanetarako.html new file mode 100644 index 0000000..031503d --- /dev/null +++ b/docker/content/eu/harremanetarako.html @@ -0,0 +1,15 @@ + +📍 Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa)
📞 943 64 52 79
✉️ hola@gureametsabilagun.org
🕙 Astelehenetik ostiralera: 10:00–13:00 eta 14:00–19:00
Adopzioak, harrerak, boluntariotza edo hoteleko erreserbak direla eta, utzi zure mezua eta ahalik eta lasterren erantzungo dizugu.
+ + + +[ga_contacto] + diff --git a/docker/content/eu/hasiera.html b/docker/content/eu/hasiera.html new file mode 100644 index 0000000..39d1b96 --- /dev/null +++ b/docker/content/eu/hasiera.html @@ -0,0 +1,7 @@ + +Gure Ametsa Bi Lagun Hondarribiko animalien babesleku eta egoitza da. 25 urte baino gehiago daramatzagu Irun eta Hondarribiko udalekin lanean: galdutako edo abandonatutako animaliak jasotzen ditugu, albaitari-arreta ematen diegu eta familia bat aurkitu arte zaintzen ditugu.
+ diff --git a/docker/content/eu/hotela.html b/docker/content/eu/hotela.html new file mode 100644 index 0000000..8d3d0b6 --- /dev/null +++ b/docker/content/eu/hotela.html @@ -0,0 +1,35 @@ + +Oporretara joateko asmoa duzu eta ezin duzu zure laguna eraman? Gure Ametsa Bi Lagunen zure txakurra edo katua zaintzen dugu kanpoan zauden bitartean, Hondarribiko Jaizubian ditugun instalazioetan, naturaz inguratuta.
+ + + +Erreserba egiteko, animaliak mikrotxipa eta txertoak egunean izan behar ditu. Udan eta data berezietan plazak azkar betetzen dira: egin erreserba aldez aurretik.
+ + + + + diff --git a/docker/content/eu/lagundu.html b/docker/content/eu/lagundu.html new file mode 100644 index 0000000..bf67763 --- /dev/null +++ b/docker/content/eu/lagundu.html @@ -0,0 +1,63 @@ + +Laguntza oro da garrantzitsua. Hauek dira gure animalien bizitza aldatzeko moduak:
+ + + +Adoptatzea da bizitza bat salbatzeko modurik zuzenena. Begiratu adopzioko animaliak, etorri haiek ezagutzera eta prozesu osoan lagunduko dizugu. Guztiak mikrotxiparekin, txertatuta eta antzututa ematen dira.
+ + + +Animalia batzuek lehenbailehen irten behar dute zentrotik: kumeek, zaharrek edo gaixorik daudenek. Harrera-etxe gisa, aldi baterako etxe bat eskaintzen diezu behin betiko familia aurkitu bitartean. Guk uneoro bideratuko zaitugu.
+ + + +Txakurrak paseatu, katuak sozializatu, adopzio-jardunaldietan lagundu, fitxetarako argazkiak atera edo sare sozialetan zabaldu. Denbora eta gogoa badituzu, behar zaitugu!
+ + + +Beti ondo etortzen zaizkigu:
+ + + +Diru-ekarpen bat egin nahi baduzu, idatzi iezaguzu eta nola egin azalduko dizugu.
+ + + + + diff --git a/docker/content/eu/lege-oharra.html b/docker/content/eu/lege-oharra.html new file mode 100644 index 0000000..fc0aef5 --- /dev/null +++ b/docker/content/eu/lege-oharra.html @@ -0,0 +1,11 @@ + +Oinarrizko testua: osatu erakundearen izen sozialarekin eta IFKarekin, eta berrikusi zuen aholkularitzarekin.
+ + + +Informazio Gizartearen Zerbitzuei buruzko 34/2002 Legea (LSSI-CE) betez, jakinarazten da webgune hau Gure Ametsa Bi Lagun erakundearena dela, helbidea Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa) duena. Harremanetarako: hola@gureametsabilagun.org · 943 64 52 79.
+ + + +Webgune honetako testuak eta irudiak Gure Ametsa Bi Lagunenak dira eta ezin dira baimenik gabe erreproduzitu, adopzioko animaliak zabaltzeko izan ezik, iturria aipatuz gero.
+ diff --git a/docker/content/eu/nor-gara.html b/docker/content/eu/nor-gara.html new file mode 100644 index 0000000..2a0f567 --- /dev/null +++ b/docker/content/eu/nor-gara.html @@ -0,0 +1,43 @@ + +Gure Ametsa Bi Lagun animaliak babesteko zentro eta egoitza bat da, Hondarribiko Jaizubia auzoan.
+ + + +25 urte baino gehiago daramatzagu Irun eta Hondarribiko udalekin lanean. Udaltzaingoak kalean galdutako edo abandonatutako animalia bat aurkitzen duenean, gure instalazioetara ekartzen du. Hemen albaitari-kontrola egiten zaio eta zainduta egoten da bere familiarengana itzuli arte edo familia berri bat aurkitu arte.
+ + + +Animalien Ongizaterako Legea betez, animalia guztiek beharrezko tratamenduak jasotzen dituzte adoptatu aurretik:
+ + + +++ + + +Adoptatu eta bi mundu aldatu: berea eta zurea.
+
Zure txakurra edo katua Irunen edo Hondarribian galdu baduzu, deitu iezaguzu lehenbailehen 943 64 52 79 zenbakira eta jakinarazi Udaltzaingoari ere. Mikrotxipa eguneratuta izatea da etxera itzultzeko modurik onena.
+ diff --git a/docker/content/eu/pribatutasun-politika.html b/docker/content/eu/pribatutasun-politika.html new file mode 100644 index 0000000..31a1631 --- /dev/null +++ b/docker/content/eu/pribatutasun-politika.html @@ -0,0 +1,43 @@ + +Oinarrizko testua: berrikusi zuen aholkularitzarekin webgunea argitaratu aurretik eta osatu arduradunaren datuak (izen soziala eta IFK).
+ + + +Gure Ametsa Bi Lagun · Jaizubia, 44 · 20280 Hondarribia (Gipuzkoa) · hola@gureametsabilagun.org · 943 64 52 79.
+ + + +Harremanetarako formularioaren bidez bidaltzen dizkiguzun datuak (izena, posta elektronikoa, telefonoa eta mezua) zure kontsultari erantzuteko eta, hala badagokio, eskatzen duzun adopzioa, harrera, boluntariotza edo erreserba kudeatzeko baino ez dira erabiltzen. Oinarri juridikoa zure baimena da.
+ + + +Datuak zure eskaera artatzeko eta lege-betebeharrak betetzeko behar den denboran gordetzen ditugu. Ez zaizkie hirugarrenei lagatzen, legezko betebeharra dagoenean izan ezik.
+ + + +Datuetara sartzeko, zuzentzeko, ezabatzeko, aurka egiteko, mugatzeko eta eramateko eskubideak erabil ditzakezu hola@gureametsabilagun.org helbidera idatzita. Datuak Babesteko Espainiako Agentzian (www.aepd.es) ere erreklamazioa aurkez dezakezu.
+ + + +Webgune honek funtzionatzeko beharrezkoak diren cookie teknikoak baino ez ditu erabiltzen. Ez dugu analitikarako edo publizitaterako cookierik erabiltzen.
+ diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..c6cfa2a --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Envoltorio del entrypoint oficial de WordPress: +# lanza en segundo plano la configuración inicial (ga-setup.sh) y después +# arranca Apache con el entrypoint original. +set -euo pipefail + +if [[ "${1:-}" == apache2* ]]; then + ga-setup.sh & +fi + +exec docker-entrypoint.sh "$@" diff --git a/docker/php.ini b/docker/php.ini new file mode 100644 index 0000000..c642a9d --- /dev/null +++ b/docker/php.ini @@ -0,0 +1,5 @@ +upload_max_filesize = 64M +post_max_size = 64M +memory_limit = 256M +max_execution_time = 120 +expose_php = Off diff --git a/docker/setup-content.php b/docker/setup-content.php new file mode 100644 index 0000000..25f6b1f --- /dev/null +++ b/docker/setup-content.php @@ -0,0 +1,276 @@ +model; + $existing = wp_list_pluck( $model->get_languages_list(), 'slug' ); + $langs = array( + array( 'locale' => 'es_ES', 'slug' => 'es', 'name' => 'Español', 'flag' => 'es', 'term_group' => 0 ), + array( 'locale' => 'eu', 'slug' => 'eu', 'name' => 'Euskara', 'flag' => 'basque', 'term_group' => 1 ), + ); + foreach ( $langs as $lang ) { + if ( in_array( $lang['slug'], $existing, true ) ) { + continue; + } + $result = $model->add_language( $lang ); + if ( is_wp_error( $result ) ) { + WP_CLI::warning( 'No se pudo crear el idioma ' . $lang['slug'] . ': ' . $result->get_error_message() ); + } + } + $model->clean_languages_cache(); + + $settings = array( + 'default_lang' => 'es', + 'force_lang' => 1, // Idioma en el directorio: /eu/... + 'hide_default' => true, // Castellano sin prefijo. + 'rewrite' => true, // /eu/ en lugar de /language/eu/. + 'redirect_lang' => true, // Portada en euskera en /eu/ (no /eu/hasiera/). + 'browser' => false, + 'post_types' => array( 'animal' ), + 'taxonomies' => array( 'especie' ), + 'sync' => array( 'taxonomies', 'post_meta', '_thumbnail_id', 'menu_order', 'post_parent' ), + ); + $options = PLL()->options; + if ( is_object( $options ) && method_exists( $options, 'set' ) ) { + foreach ( $settings as $key => $value ) { + $options->set( $key, $value ); + } + if ( method_exists( $options, 'save_all' ) ) { + $options->save_all(); + } + } else { + update_option( 'polylang', array_merge( (array) get_option( 'polylang', array() ), $settings ) ); + } + // Traducción al euskera del lema del sitio. + if ( class_exists( 'PLL_MO' ) && ( $eu = $model->get_language( 'eu' ) ) ) { + $mo = new PLL_MO(); + $mo->import_from_db( $eu ); + $mo->add_entry( $mo->make_entry( get_option( 'blogdescription' ), 'Adoptatu eta bi mundu aldatu · Hondarribia' ) ); + $mo->export_to_db( $eu ); + } + if ( class_exists( 'PLL_Admin_Notices' ) ) { + PLL_Admin_Notices::dismiss( 'wizard' ); + } + WP_CLI::log( '[ga-setup] Idiomas: castellano (por defecto) y euskera' ); +} + +/* ---------- 2. Páginas ---------- */ +function ga_setup_page( $slug, $title, $file, $lang ) { + $existing = get_page_by_path( $slug, OBJECT, 'page' ); + if ( $existing ) { + return $existing->ID; + } + $content = file_get_contents( $file ); + $id = wp_insert_post( array( + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => $title, + 'post_name' => $slug, + 'post_content' => $content, + ), true ); + if ( is_wp_error( $id ) ) { + WP_CLI::error( "No se pudo crear la página $slug: " . $id->get_error_message() ); + } + if ( function_exists( 'pll_set_post_language' ) ) { + pll_set_post_language( $id, $lang ); + } + return $id; +} + +// slug es => [título es, archivo es, slug eu, título eu, archivo eu] +$pages = array( + 'inicio' => array( 'Inicio', 'inicio', 'hasiera', 'Hasiera', 'hasiera' ), + 'quienes-somos' => array( 'Quiénes somos', 'quienes-somos', 'nor-gara', 'Nor gara', 'nor-gara' ), + 'colabora' => array( 'Colabora', 'colabora', 'lagundu', 'Lagundu', 'lagundu' ), + 'hotel' => array( 'Hotel para perros y gatos', 'hotel', 'hotela', 'Txakur eta katuentzako hotela', 'hotela' ), + 'contacto' => array( 'Contacto', 'contacto', 'harremanetarako', 'Harremanetarako', 'harremanetarako' ), + 'politica-de-privacidad' => array( 'Política de privacidad', 'privacidad', 'pribatutasun-politika', 'Pribatutasun-politika', 'pribatutasun-politika' ), + 'aviso-legal' => array( 'Aviso legal', 'aviso-legal', 'lege-oharra', 'Lege-oharra', 'lege-oharra' ), +); + +$ids = array(); +foreach ( $pages as $slug => [ $title_es, $file_es, $slug_eu, $title_eu, $file_eu ] ) { + $ids[ $slug ]['es'] = ga_setup_page( $slug, $title_es, "$src/es/$file_es.html", 'es' ); + if ( $pll ) { + $ids[ $slug ]['eu'] = ga_setup_page( $slug_eu, $title_eu, "$src/eu/$file_eu.html", 'eu' ); + pll_save_post_translations( $ids[ $slug ] ); + } +} + +update_option( 'show_on_front', 'page' ); +update_option( 'page_on_front', $ids['inicio']['es'] ); +update_option( 'wp_page_for_privacy_policy', $ids['politica-de-privacidad']['es'] ); +WP_CLI::log( '[ga-setup] Páginas creadas' ); + +/* ---------- 3. Especies ---------- */ +$species = array( + 'perro' => array( 'Perro', 'txakurra', 'Txakurra' ), + 'gato' => array( 'Gato', 'katua', 'Katua' ), + 'otros' => array( 'Otros', 'besteak', 'Besteak' ), +); +$term_ids = array(); +foreach ( $species as $slug => [ $name_es, $slug_eu, $name_eu ] ) { + $pairs = array( 'es' => array( $slug, $name_es ) ); + if ( $pll ) { + $pairs['eu'] = array( $slug_eu, $name_eu ); + } + foreach ( $pairs as $lang => [ $term_slug, $term_name ] ) { + $term = get_term_by( 'slug', $term_slug, 'especie' ); + if ( ! $term ) { + $res = wp_insert_term( $term_name, 'especie', array( 'slug' => $term_slug ) ); + $term = is_wp_error( $res ) ? null : get_term( $res['term_id'], 'especie' ); + } + if ( $term ) { + $term_ids[ $slug ][ $lang ] = $term->term_id; + if ( $pll ) { + pll_set_term_language( $term->term_id, $lang ); + } + } + } + if ( $pll && count( $term_ids[ $slug ] ?? array() ) === 2 ) { + pll_save_term_translations( $term_ids[ $slug ] ); + } +} + +/* ---------- 4. Menús ---------- */ +function ga_setup_menu( $name, $items ) { + $menu = wp_get_nav_menu_object( $name ); + if ( $menu ) { + return $menu->term_id; + } + $menu_id = wp_create_nav_menu( $name ); + foreach ( $items as $pos => $item ) { + $args = array( 'menu-item-status' => 'publish', 'menu-item-position' => $pos + 1, 'menu-item-title' => $item['title'] ); + if ( isset( $item['page'] ) ) { + $args += array( 'menu-item-type' => 'post_type', 'menu-item-object' => 'page', 'menu-item-object-id' => $item['page'] ); + } else { + $args += array( 'menu-item-type' => 'custom', 'menu-item-url' => $item['url'] ); + } + wp_update_nav_menu_item( $menu_id, 0, $args ); + } + return $menu_id; +} + +$menus = array( + 'primary' => array( + 'es' => ga_setup_menu( 'Principal', array( + array( 'title' => 'Adopta', 'url' => '/adopta/' ), + array( 'title' => 'Acoge', 'url' => '/colabora/#acogida' ), + array( 'title' => 'Voluntariado', 'url' => '/colabora/#voluntariado' ), + array( 'title' => 'Dona', 'url' => '/colabora/#donaciones' ), + array( 'title' => 'Hotel', 'page' => $ids['hotel']['es'] ), + array( 'title' => 'Contacto', 'page' => $ids['contacto']['es'] ), + ) ), + ), + 'footer' => array( + 'es' => ga_setup_menu( 'Legal', array( + array( 'title' => 'Aviso legal', 'page' => $ids['aviso-legal']['es'] ), + array( 'title' => 'Política de privacidad', 'page' => $ids['politica-de-privacidad']['es'] ), + ) ), + ), +); +if ( $pll ) { + $menus['primary']['eu'] = ga_setup_menu( 'Nagusia (euskara)', array( + array( 'title' => 'Adoptatu', 'url' => '/eu/adopta/' ), + array( 'title' => 'Harrera', 'url' => '/eu/lagundu/#acogida' ), + array( 'title' => 'Boluntariotza', 'url' => '/eu/lagundu/#voluntariado' ), + array( 'title' => 'Dohaintza', 'url' => '/eu/lagundu/#donaciones' ), + array( 'title' => 'Hotela', 'page' => $ids['hotel']['eu'] ), + array( 'title' => 'Harremanetarako', 'page' => $ids['contacto']['eu'] ), + ) ); + $menus['footer']['eu'] = ga_setup_menu( 'Legala (euskara)', array( + array( 'title' => 'Lege-oharra', 'page' => $ids['aviso-legal']['eu'] ), + array( 'title' => 'Pribatutasun-politika', 'page' => $ids['politica-de-privacidad']['eu'] ), + ) ); + + $theme = get_stylesheet(); + $nav_menus = array( $theme => $menus ); + if ( is_object( PLL()->options ) && method_exists( PLL()->options, 'set' ) ) { + PLL()->options->set( 'nav_menus', $nav_menus ); + if ( method_exists( PLL()->options, 'save_all' ) ) { + PLL()->options->save_all(); + } + } else { + $opts = (array) get_option( 'polylang', array() ); + $opts['nav_menus'] = $nav_menus; + update_option( 'polylang', $opts ); + } +} +set_theme_mod( 'nav_menu_locations', array( + 'primary' => $menus['primary']['es'], + 'footer' => $menus['footer']['es'], +) ); +WP_CLI::log( '[ga-setup] Menús creados' ); + +/* ---------- 5. Animales de ejemplo (opcional) ---------- */ +if ( 'true' === getenv( 'SEED_DEMO_ANIMALS' ) ) { + $demo = array( + array( + 'es' => array( 'Txuri (ejemplo)', 'Txuri es cariñosa, tranquila en casa y le encantan los paseos por Jaizkibel.' ), + 'eu' => array( 'Txuri (adibidea)', 'Txuri maitekorra da, lasaia etxean, eta Jaizkibelen barrena paseatzea asko gustatzen zaio.' ), + 'sp' => 'perro', + 'meta' => array( 'sexo' => 'hembra', 'edad' => '3', 'edad_unidad' => 'anos', 'tamano' => 'mediano', 'estado' => 'disponible', 'raza' => 'Mestiza' ), + ), + array( + 'es' => array( 'Beltza (ejemplo)', 'Beltza es un gato curioso y juguetón que busca un hogar sin prisas.' ), + 'eu' => array( 'Beltza (adibidea)', 'Beltza katu jakin-nahia eta jostalaria da, eta presarik gabe etxe baten bila dabil.' ), + 'sp' => 'gato', + 'meta' => array( 'sexo' => 'macho', 'edad' => '1', 'edad_unidad' => 'anos', 'tamano' => 'pequeno', 'estado' => 'disponible', 'raza' => 'Común europeo' ), + ), + array( + 'es' => array( 'Hartz (ejemplo)', 'Hartz es un abuelito noble que merece pasar sus mejores años en familia.' ), + 'eu' => array( 'Hartz (adibidea)', 'Hartz aitona noblea da, eta bere urterik onenak familian igarotzea merezi du.' ), + 'sp' => 'perro', + 'meta' => array( 'sexo' => 'macho', 'edad' => '7', 'edad_unidad' => 'anos', 'tamano' => 'grande', 'estado' => 'urgente', 'raza' => 'Mastín' ), + ), + array( + 'es' => array( 'Ilargi (ejemplo)', 'Ilargi es una gatita sociable que se lleva bien con otros gatos.' ), + 'eu' => array( 'Ilargi (adibidea)', 'Ilargi katakume soziala da eta beste katuekin ondo moldatzen da.' ), + 'sp' => 'gato', + 'meta' => array( 'sexo' => 'hembra', 'edad' => '4', 'edad_unidad' => 'meses', 'tamano' => 'pequeno', 'estado' => 'reservado', 'raza' => 'Común europeo' ), + ), + ); + foreach ( $demo as $animal ) { + $translations = array(); + foreach ( $pll ? array( 'es', 'eu' ) : array( 'es' ) as $lang ) { + [ $title, $text ] = $animal[ $lang ]; + $id = wp_insert_post( array( + 'post_type' => 'animal', + 'post_status' => 'publish', + 'post_title' => $title, + 'post_content' => "\n$text
\n", + ) ); + if ( ! empty( $term_ids[ $animal['sp'] ][ $lang ] ) ) { + wp_set_object_terms( $id, array( $term_ids[ $animal['sp'] ][ $lang ] ), 'especie' ); + } + foreach ( $animal['meta'] + array( 'salud' => 'chip,vacunado,esterilizado', 'compatible' => 'perros,ninos' ) as $key => $value ) { + update_post_meta( $id, "_ga_$key", $value ); + } + if ( $pll ) { + pll_set_post_language( $id, $lang ); + } + $translations[ $lang ] = $id; + } + if ( $pll ) { + pll_save_post_translations( $translations ); + } + } + WP_CLI::log( '[ga-setup] Animales de ejemplo creados' ); +} + +// Polylang guarda en caché la portada de cada idioma: se regenera con las traducciones ya creadas. +if ( $pll ) { + PLL()->model->clean_languages_cache(); +} +flush_rewrite_rules( false ); diff --git a/docker/setup.sh b/docker/setup.sh new file mode 100644 index 0000000..815d2a4 --- /dev/null +++ b/docker/setup.sh @@ -0,0 +1,160 @@ +#!/bin/bash +# Configuración inicial idempotente de WordPress para Gure Ametsa Bi Lagun. +# Se ejecuta en segundo plano en cada arranque del contenedor. +set -uo pipefail + +log() { echo "[ga-setup] $*"; } + +WP_PATH=/var/www/html +SRC=/usr/src/gure-ametsa +export WP_CLI_CACHE_DIR=/tmp/wp-cli-cache + +wp_() { runuser -u www-data -- wp --path="$WP_PATH" "$@"; } + +# 1. Esperar a que el entrypoint oficial copie WordPress y genere wp-config.php +for _ in $(seq 1 120); do + [[ -f "$WP_PATH/wp-config.php" && -f "$WP_PATH/wp-includes/version.php" ]] && break + sleep 1 +done + +# 2. Sincronizar tema y mu-plugins propios (siempre, para que las actualizaciones de imagen se apliquen) +mkdir -p "$WP_PATH/wp-content/themes" "$WP_PATH/wp-content/mu-plugins" "$WP_PATH/wp-content/uploads" +rm -rf "$WP_PATH/wp-content/themes/gure-ametsa" +cp -r "$SRC/themes/gure-ametsa" "$WP_PATH/wp-content/themes/" +cp -r "$SRC/mu-plugins/." "$WP_PATH/wp-content/mu-plugins/" +# Polylang: se copia solo si no existe (después se actualiza desde el panel) +if [[ ! -d "$WP_PATH/wp-content/plugins/polylang" ]]; then + mkdir -p "$WP_PATH/wp-content/plugins" + cp -r "$SRC/plugins/polylang" "$WP_PATH/wp-content/plugins/" +fi +chown -R www-data:www-data "$WP_PATH/wp-content" +log "Tema y mu-plugins sincronizados" + +# .htaccess para enlaces permanentes bonitos +if [[ ! -f "$WP_PATH/.htaccess" ]]; then + cat > "$WP_PATH/.htaccess" <<'EOF' +# BEGIN WordPress +| '; + switch ( $f['type'] ) { + case 'select': + echo ''; + break; + case 'checks': + $current = array_filter( explode( ',', $value ) ); + foreach ( $f['options'] as $v => $l ) { + printf( + '', + esc_attr( $name ), esc_attr( $v ), checked( in_array( $v, $current, true ), true, false ), esc_html( $l ) + ); + } + break; + default: + printf( + '', + 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 ' |
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.
'; + echo 'Consejo: la foto principal aparece en los listados. Añade más fotos en el contenido con el bloque «Galería».
'; +} + +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 '' . esc_html( ga__( 'Ahora mismo no hay animales en esta sección. ¡Vuelve pronto!', 'Une honetan ez dago animaliarik atal honetan. Itzuli laster!' ) ) . '
'; + } + 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( + '