Academia Deltamontero · Documentación
Desarrollo

Parches

Los once parches que se aplican al código de Moodle y de plugins de terceros durante la construcción de la imagen, por qué existen y cómo los verifica verify-patches.php.

Algunos comportamientos necesitan cambiar código que no es propio. Para no mantener copias modificadas de Moodle ni de los plugins, se usan parches en tiempo de construcción: scripts PHP puros (sin cargar Moodle) en infrastructure/moodle/patch-*.php que buscan un texto exacto (el ancla) y lo reemplazan con str_replace.

Reglas de los parches

ReglaDetalle
MínimosUna o pocas líneas; si hace falta lógica, el parche llama a una clase de local_deltamodules.
IdempotentesCada parche busca primero su marcador (normalmente un comentario DELTA:) y, si ya está, no hace nada.
No rompen el buildSi el archivo no existe o el ancla no aparece, escriben un aviso en la salida de error y terminan con código 0.
Verificadosverify-patches.php comprueba al final que los importantes quedaron aplicados y, si falta uno, el build falla.
Orden fijoEl Dockerfile los ejecuta en un solo RUN, en el orden de la tabla de abajo.
php /patch-ai-role-injection.php \
  && php /patch-ai-agent.php \
  && php /patch-policy-consentpage.php \
  && php /patch-forgot-password.php \
  && php /patch-welcome-name.php \
  && php /patch-ai-chat-everywhere.php \
  && php /patch-cedula-field.php \
  && php /patch-cert-completion-gate.php \
  && (php /patch-ai-chat-copy.php || true) \
  && (php /patch-ai-chat-ui.php || true) \
  && (php /patch-video-completion.php || true) \
  && php /verify-patches.php

Los tres últimos son cosméticos: van con || true y no detienen el build aunque fallen.

Detalle de cada parche

patch-ai-role-injection.php

ElementoDetalle
Archivolocal/ai_manager/classes/external/submit_query.php
AnclaEl bloque que decodifica $options con json_decode($options, true)
CambioDespués del bloque, si $options es un arreglo y existe la clase, $options = \local_deltamodules\ai_role_injector::inject($options);
Para quéEl chat conoce el perfil del usuario (Asistente de IA). Sin el parche, el chat funciona sin esa información.
Marcador verificadolocal_deltamodules\ai_role_injector

patch-ai-agent.php

ElementoDetalle
Archivolocal/ai_manager/classes/external/submit_query.php
AnclaEl bloque insertado por el parche anterior (por eso debe correr después)
Cambio$deltaagent = \local_deltamodules\ai_agent::maybe_handle($prompt, $options, $contextid); y, si no es null, return ['code' => 200, 'string' => 'ok', 'result' => $deltaagent];
Para quéAgente de acciones con permisos reales
Marcador verificadolocal_deltamodules\ai_agent

patch-policy-consentpage.php

ElementoDetalle
Archivosadmin/tool/policy/classes/output/page_agreedocs.php y admin/tool/policy/templates/page_agreedocs.mustache
Cambios1) Marca como vistas las políticas vigentes en la caché, para ir directo a la página de consentimiento (el texto completo queda en una ventana modal). 2) Quita el mensaje de error "debe aceptar" de la primera carga. 3) Quita de la plantilla la línea "acceda al texto completo". 4) Quita los encabezados "Aceptar" y "Por favor, acepte las siguientes políticas".
Para quéAceptación del aviso de datos en una sola página, más limpia
Marcador verificadoDELTA: ir directo a la página de consentimiento (en el PHP)

patch-forgot-password.php

ElementoDetalle
Archivologin/forgot_password_form.php
CambioQuita la sección "Buscar por dirección email" (encabezado, campo y botón)
Para quéLa recuperación nativa queda solo por nombre de usuario. En la práctica el enlace del login apunta a la página propia local/candidate_enrollment/recover.php (forgottenpasswordurl).
Marcador verificadoDELTA: sin búsqueda por email

patch-welcome-name.php

ElementoDetalle
Archivolib/classes/user.php
Anclareturn new lang_string($messagekey, 'core', $namefields);
CambioAgrega a $namefields las claves firstfirstname y firstlastname (primera palabra del nombre y del apellido)
Para quéEl saludo del Área personal muestra "primer nombre + primer apellido"; se combina con las cadenas welcomeback y welcometosite que redefine customize-strings.php
Marcador verificadofirstfirstname

patch-ai-chat-everywhere.php

ElementoDetalle
Archivolocal/ai_manager/classes/local/userinfo.php
Cambioget_default_scope() devuelve siempre SCOPE_EVERYWHERE (antes, el nivel básico recibía "solo cursos")
Para quéUn colaborador nuevo ve el chat flotante en todas las páginas, respetando su cuota
Marcador verificadoDELTA: chat disponible en todas las páginas

patch-cedula-field.php

ElementoDetalle
Archivouser/editlib.php
CambioAgrega un campo idnumber con la etiqueta "Cédula", maxlength 10 y obligatorio, en la sección General (después del correo), y quita la definición original de "Número de ID" de la sección Opcional
Para quéLa cédula es el identificador estable de cada persona y base de la recuperación de contraseña. Solo afecta al formulario de usuario.
Marcador verificadoDELTA: Cédula

patch-cert-completion-gate.php

ElementoDetalle
Archivomod/customcert/view.php
Cambios1) Calcula $deltacomplete con info_module::is_available(…, false, …) (sin el atajo de gestores; el super administrador siempre true; ante un error, true). 2) Muestra el botón de descarga solo si $canreceive && $deltacomplete. 3) Con downloadown y sin completar, redirige a la vista.
Para quéCandado real del certificado propio, también para gestores (Certificados)
Marcador verificado$deltacomplete

patch-ai-chat-copy.php (cosmético)

ElementoDetalle
Archivosblocks/ai_chat/amd/src/helper.js y blocks/ai_chat/amd/build/helper.min.js
CambioReemplaza navigator.clipboard.writeText(textToCopy) por una versión que, fuera de un contexto seguro, copia con un textarea y document.execCommand('copy')
Para quéEl botón copiar fallaba al entrar por http://IP

patch-ai-chat-ui.php (cosmético)

ElementoDetalle
Archivosblocks/ai_chat/classes/output/renderer.php, blocks/ai_chat/templates/floatingbutton.mustache, blocks/ai_chat/classes/external/get_conversationcontext_limit.php
Cambios1) El renderizador agrega deltafirstname (primer nombre) y deltaailimit (límite diario según el nivel del usuario). 2) La plantilla agrega un span oculto data-delta-aichat con contextid, userid, nombre y límite. 3) El contexto por defecto pasa de 5 a 50 mensajes.
Para quéEl JavaScript propio del chat (saludo, contador, borrar una conversación) y más memoria de la conversación

patch-video-completion.php (cosmético)

ElementoDetalle
Archivosmod/interactivevideo/amd/build/viewannotation.min.js (y, si coincide, amd/src/viewannotation.js)
CambioQuita la llamada a fireConfetti() y al aviso "congratulationsyoucompletethisactivity"
Para quéEl video solo se marca como hecho, sin confeti ni anuncio

verify-patches.php

Revisa ocho parches importantes buscando su marcador en el archivo parcheado:

ComprobaciónArchivoMarcador
Perfil del usuario en el chat de IAlocal/ai_manager/classes/external/submit_query.phplocal_deltamodules\ai_role_injector
Asistente de gestión del chat de IAlocal/ai_manager/classes/external/submit_query.phplocal_deltamodules\ai_agent
Política del sitio en una sola páginaadmin/tool/policy/classes/output/page_agreedocs.phpDELTA: ir directo a la página de consentimiento
"¿Olvidó su contraseña?" sin correologin/forgot_password_form.phpDELTA: sin búsqueda por email
Saludo con nombre y apellidolib/classes/user.phpfirstfirstname
Chat de IA en todas las páginaslocal/ai_manager/classes/local/userinfo.phpDELTA: chat disponible en todas las páginas
Campo Cédula en el perfiluser/editlib.phpDELTA: Cédula
Certificado solo con el módulo completomod/customcert/view.php$deltacomplete

Si falta alguno, escribe la lista en la salida de error y termina con código 1: el build se detiene y el error se ve en Coolify. Los parches cosméticos no se verifican.

Como Moodle y casi todos los plugins están fijados a un commit, un parche solo deja de aplicarse cuando alguien cambia esa versión. Al actualizar Moodle o un plugin parcheado, revise que cada ancla siga existiendo en el archivo nuevo (ver Guía de cambios).

En esta página