Academia Deltamontero · Documentación
Desarrollo

Guía de cambios

Procedimientos para modificar y ampliar la plataforma - páginas, reglas, correos, tours, scripts, parches, plugins de terceros, versiones, pruebas locales y commits.

Procedimientos que se desprenden de cómo está construido el código. Antes de cambiar algo, revise la página del subsistema correspondiente en esta sección.

Ciclo general

Cambiar el código

En plugins/ (plugins propios) o infrastructure/moodle/ (arranque, configuración, parches). Mantenga las convenciones: comentarios en español, encabezado DELTA-APP LMS — …, idempotencia, try/catch en hooks y observadores, acciones por POST con sesskey.

Si es un archivo nuevo, agregarlo a .dockerignore

.dockerignore es una lista blanca. Un script nuevo de infrastructure/moodle/ necesita su línea !infrastructure/moodle/<archivo>; un plugin propio nuevo necesita !plugins/<carpeta>/ y !plugins/<carpeta>/**. Sin eso, no llega a la imagen.

Probar en local

Con la imagen reconstruida (docker compose up -d --build) o copiando los archivos a los contenedores (ver Probar en local).

Revisar el registro del arranque

docker compose logs -f moodle: los pasos de moodle-config.sh que fallan aparecen con !!! ERROR (críticos) o ! Aviso (cosméticos), y el super administrador los ve en Moodle.

Commit y despliegue

Ver Commits. En producción, Coolify reconstruye la imagen al desplegar (Operación).

Probar en local

El código está horneado en la imagen: los contenedores delta-lms_app y delta-lms_cron tienen cada uno su propia copia de /var/www/html (solo moodledata es un volumen compartido). La forma canónica de probar es reconstruir:

docker compose up -d --build
docker compose logs -f moodle

Para iterar más rápido se pueden copiar archivos a los contenedores en marcha. Hay que copiarlos a los dos (el sitio y el cron), porque el cron ejecuta tareas y observadores con su propia copia del código y, si su versión no coincide con la de la base de datos, informa "upgrade pending":

# Plugin propio (ejemplo: local_deltamodules)
docker cp plugins/local_deltamodules/. delta-lms_app:/var/www/html/local/deltamodules/
docker cp plugins/local_deltamodules/. delta-lms_cron:/var/www/html/local/deltamodules/
docker exec delta-lms_app chown -R www-data:www-data /var/www/html/local/deltamodules
docker exec delta-lms_cron chown -R www-data:www-data /var/www/html/local/deltamodules

# Si se subió version.php
docker exec delta-lms_app php /var/www/html/admin/cli/upgrade.php --non-interactive

# Siempre
docker exec delta-lms_app php /var/www/html/admin/cli/purge_caches.php

Para un script de configuración:

docker cp infrastructure/moodle/configure-tours.php delta-lms_app:/configure-tours.php
docker exec delta-lms_app php /configure-tours.php

Lo copiado a mano se pierde al recrear los contenedores (la imagen manda). Antes de dar un cambio por terminado, pruébelo con docker compose up -d --build, que además ejecuta verify-patches.php y todo moodle-config.sh. En los contenedores locales, $CFG->noemailever no está fijado: si .env define MOODLE_SMTP_HOST, los correos salen de verdad (use MOODLE_MAIL_DIVERT_TO para desviarlos a una dirección de prueba).

Los nombres de contenedor dependen de COMPOSE_PROJECT_NAME (por defecto delta-lms).

Subir la versión de un plugin

Moodle solo ejecuta db/upgrade.php y vuelve a leer db/access.php, db/events.php, db/tasks.php, db/services.php, db/hooks.php y db/messages.php cuando la versión del plugin aumenta.

  1. En version.php, aumente $plugin->version con el formato AAAAMMDDXX (por ejemplo 2026100700 → 2026100800).
  2. Si cambia la base de datos: edite db/install.xml (instalaciones nuevas) y agregue un bloque en db/upgrade.php con la nueva versión, que compruebe table_exists / field_exists antes de crear y termine con upgrade_plugin_savepoint(true, <versión>, 'local', 'deltamodules'). La versión del último paso no puede ser mayor que la de version.php.
  3. Si otro plugin depende de la nueva versión, actualice su $plugin->dependencies (por ejemplo, los dataformat_delta* dependen de local_deltamodules >= 2026092404).
  4. Al arrancar, entrypoint.sh ejecuta upgrade.php; si falla, el despliegue se detiene.

Agregar una página

  1. Cree plugins/local_deltamodules/<pagina>.php con require(__DIR__ . '/../../config.php');, require_login() (o admin_externalpage_setup() si va en Administración) y require_capability() con la capacidad adecuada.
  2. Use ui::css(), las clases dp-* y, si va dentro de Administración del sitio, ui::crumbs([...]) antes de $OUTPUT->header().
  3. Acciones que cambian datos: POST con sesskey (ui::post_button()), confirm_sesskey() al procesar, confirmación con data-delta-confirm y redirección con mensaje.
  4. Si debe aparecer en Administración del sitio, regístrela en settings.php con admin_externalpage y agregue su nombre a admin_access::ALLOWED si deben verla perfiles que no son super administradores.
  5. Si debe ir en la barra superior, agréguela en hook_callbacks::primary_extend, su clave en PRIMARY_ORDER y su ruta en el mapa de pestaña activa de primary_order.
  6. Si debe tener tour, ver Agregar un recorrido guiado.

Agregar una regla de la Academia

  1. Agregue la clave a rules::definitions() con group, label, help, default (su tipo define el tipo del valor) y options. Si al cambiarla debe imponerse a lo configurado a mano, agregue 'force' => true y trate la clave en standard::apply_quiz() o donde corresponda.
  2. Lea el valor con rules::get('<clave>', $courseid) en el lugar que la aplica (standard, academy, servicios web…).
  3. Si su cambio debe recalcular algo en los módulos, trátela en standard::apply_course() (reciba la clave en $force).
  4. Si debe verse en el formulario de las actividades, agréguela a la lista de local_deltamodules_coursemodule_definition_after_data en lib.php.
  5. Si el manual la menciona, actualice el texto en classes/manual.php.

No hace falta tocar la base de datos: la regla general se guarda en la configuración (rule_<clave>) y las propias de cada módulo en local_deltamodules_rule.

Agregar un tipo de correo

  1. Agregue el tipo a mailer::KINDS (clave => [nombre, cuándo se envía]): así aparece en la página de correo con su interruptor.
  2. Cree un método que arme el contenido con los ayudantes (greet, p, badge, button, note, closing) y llame a self::queue($usuario_o_correo, '<clave>', $asunto, $contenido, $opciones). Use dedupe si no debe repetirse y immediate (true o 'after') si debe salir sin esperar a la tarea.
  3. Si lleva enlace para crear contraseña, use self::PWLINK en el botón y purpose (welcome o reset; otra vigencia exige agregarla a mailer::TTL).
  4. Agregue el caso en mailer::sample() para poder enviar un ejemplo.
  5. Si se dispara por un evento, agregue el observador en db/events.php (y suba la versión), con try/catch y comprobando self::enabled() y self::kind_on().
  6. Si se dispara periódicamente, cree una tarea en classes/task/ y regístrela en db/tasks.php.

Agregar un recorrido guiado

  1. Agregue una entrada a $TOURS en infrastructure/moodle/configure-tours.php con name (único, se usa para encontrarlo), description, pathmatch, steps y, si corresponde, roles, category o css.
  2. Los pasos se arman con $u(título, contenido) (sin elemento) o $s(selector, título, contenido, ubicación). Si el selector no está en la página, el paso se salta.
  3. Despliegue: el script crea o actualiza el tour. Para que lo vuelvan a ver quienes ya vieron una versión anterior, agregue 'major' => true.

El observador tours::started hace que cada tour se muestre una sola vez por persona sin configuración adicional.

Agregar un script de configuración

  1. Cree infrastructure/moodle/<script>.php con define('CLI_SCRIPT', true); require('/var/www/html/config.php');, idempotente y con mensajes cortos en la salida.
  2. Agréguelo a .dockerignore.
  3. Si debe correr en cada arranque, agréguelo a moodle-config.sh con step critico "<descripción>" php /<script>.php o step cosmetico …, en el lugar correcto del orden (por ejemplo, después de lo que crea los datos que necesita).
  4. Si debe correr una sola vez, use una marca: const FLAG = '<nombre>_AAAAMMDD';, salga si get_config('local_deltamodules', FLAG) existe y al final set_config(FLAG, time(), 'local_deltamodules'). Si conviene permitir repetirlo, acepte --force.
  5. Nunca escriba claves en el script: léalas con getenv() y documente la variable en Variables de entorno.

Agregar una capacidad

  1. Defínala en db/access.php del plugin (captype, contextlevel, riskbitmask, archetypes). Sin arquetipo, nadie la recibe hasta que se le conceda.
  2. Agregue su nombre en lang/es y lang/en (<plugin>:<capacidad>).
  3. Concédala por perfil en align-access-profiles-to-manual.php ($ALLOW) o retírela ($PREVENT).
  4. Suba la versión del plugin.

Guardar datos personales

  1. No escriba en el código datos de personas reales (cédulas, correos, contraseñas, nombres de usuario ni listas de cuentas): las reglas deben aplicarse por cargo, cohorte o perfil, y los datos se cargan desde la plataforma o desde la importación de Excel. En comentarios y ejemplos, nombre roles ("el Jefe de Talento Humano") o datos ficticios.
  2. Si agrega una tabla, un campo o una preferencia con datos de personas, declárelo en el proveedor de privacidad del plugin (classes/privacy/provider.php): metadatos en get_metadata(), exportación y eliminación. En local_deltamodules, agregue la tabla a OWNED (la fila es de la persona: se borra) o a AUTHORED (la persona solo figura como autora de un registro de la empresa: se desvincula con 0), con sus cadenas privacy:metadata:* en lang/es y lang/en. Ver local_deltamodules → Privacidad.
  3. Si un dato nuevo se envía al proveedor de IA, declárelo en la ubicación externa groq del proveedor de privacidad y, en el agente de acciones, pase el texto por pii_hide() antes de enviarlo (ver Asistente de IA).

Agregar un parche a código de terceros

  1. Cree infrastructure/moodle/patch-<nombre>.php siguiendo el patrón de los existentes: PHP puro, comprobar que el archivo existe, salir si ya está el marcador DELTA: …, buscar el ancla exacta, str_replace, y terminar siempre con código 0.
  2. Mantenga el cambio mínimo; ponga la lógica en una clase de local_deltamodules.
  3. Agréguelo a .dockerignore y al RUN de parches del Dockerfile (con || true si es cosmético).
  4. Si es importante, agregue su archivo y marcador a $checks en verify-patches.php para que el build falle si deja de aplicarse.

Actualizar un plugin de terceros

  1. En el Dockerfile, cambie el commit de su línea git-at (o la etiqueta de git clone --branch en los plugins de IA). Verifique que la versión nueva siga siendo compatible con Moodle 4.5.
  2. Revise si el plugin tiene parches (ver Parches) y si cada ancla sigue existiendo en el archivo nuevo.
  3. Revise si las traducciones de infrastructure/moodle/lang/es/ siguen correspondiendo a sus cadenas.
  4. Reconstruya: si un parche importante ya no se aplica, verify-patches.php detiene el build. Si un parche cosmético deja de aplicarse, el build sigue, pero el registro muestra el aviso.
  5. Pruebe el flujo que depende del plugin (chat de IA, certificados, videos).

Al actualizar Moodle, revise además los parches al núcleo (tool_policy, login, lib/classes/user.php, user/editlib.php) y el JavaScript de additionalhtmlhead, que depende de selectores de la interfaz de Moodle 4.5.

Commits

ReglaDetalle
IdiomaLos mensajes de commit van en inglés (comentarios del código, textos de la interfaz y documentación siguen en español).
EstiloUna línea descriptiva que dice qué cambia para el usuario, por ejemplo "Backups page in Moodle; keep Moodle's per-course automated backups off" o "Quiz editor with settings and custom notice; blank modules open in edit mode".
Qué no se sube.env (está en .gitignore), respaldos (backups/), credenciales, tokens, datos personales ni archivos locales de trabajo. Lo que se sube queda en el historial de Git aunque luego se borre del código: sacarlo exige reescribir el historial.
RamaLos commits recientes del repositorio están en main.

En esta página