Convoca Courses
Guía para administradores: cursos con módulos y lecciones, matrícula, progreso y certificado.
Versión cubierta: 0.3.0 · WP: 6.4+ · PHP: 8.1+ · Requiere: convoca-core.
Manual para la junta directiva (sin conocimientos técnicos)¶
Esta página es la referencia técnica del plugin. Para el día a día hay un manual en tres partes:
1. Introducción¶
Convoca Courses convierte un WordPress en una plataforma de cursos sin atarse a un tema ni a otro plugin del ecosistema. Cubre el ciclo completo: curso → módulos → lecciones → matrícula → progreso → certificado verificable.
La diferencia con Convoca Enroll: Enroll gestiona actividades con plazas y check-in; un curso es otra cosa. La matrícula, el progreso y el certificado son del módulo de cursos, no se delegan.
Dependencias:
| Plugin | Rol | Consecuencia si falta |
|---|---|---|
| convoca-core | Utilidades, locks, logger, circuito de licencias, dompdf | El plugin no arranca (aviso en el panel y return) |
| convoca-gateway | Opcional: cobrar la matrícula con Redsys | El curso es gratuito o se cobra fuera y se marca a mano |
No depende de convoca-enroll ni de convoca-members, a propósito: un cliente puede querer dar un
curso sin comprar medio ecosistema.
2. Modelo de datos¶
2.1. Tipos de contenido¶
| Pieza | Tipo | Público | Meta propia |
|---|---|---|---|
| Curso | convoca_curso |
sí (/cursos/) |
_convoca_precio, _convoca_moneda, _convoca_plazas, _convoca_certificado, _convoca_desbloqueo_secuencial |
| Módulo | convoca_modulo |
no | _convoca_curso_id, _convoca_orden |
| Lección | convoca_leccion |
no | _convoca_modulo_id, _convoca_tipo, _convoca_orden, _convoca_duracion, _convoca_adjunto_id, _convoca_video_url, _convoca_video_key |
| Matrícula | convoca_matricula |
no | _convoca_curso_id, _convoca_user_id, _convoca_estado, _convoca_importe, _convoca_pago, _convoca_cert_codigo, _convoca_cert_fecha |
2.2. Jerarquía¶
curso → módulos → lecciones. Se guarda en meta (_convoca_curso_id, _convoca_modulo_id), no con
post_parent, porque son tipos de contenido distintos. Al guardar se valida: un módulo sin curso
o una lección sin módulo no se aceptan y el editor avisa.
El orden se guarda en _convoca_orden (no se depende del campo Orden de WordPress) y se aplica el
mismo criterio en el panel y en el front.
2.3. Progreso: tabla propia¶
{prefijo}convoca_course_progress
id, course_id, user_id, lesson_id, completed_at
UNIQUE (user_id, lesson_id)
KEY (course_id, user_id)
No se usa postmeta: el progreso se consulta por persona y por curso constantemente y ahí sería un
escaneo. La tabla se crea con dbDelta y se versiona con CONVOCA_COURSES_DB_VERSION.
2.4. Estados de la matrícula¶
| Valor | Significado |
|---|---|
pendiente |
Creada, pendiente de pago o de aprobación manual |
activa |
Da acceso al contenido |
completada |
Al 100 % de progreso; dispara el certificado si el curso lo tiene activado |
cancelada |
Baja; libera la plaza |
pendiente, activa y completada ocupan plaza. cancelada no.
3. Shortcodes¶
| Shortcode | Qué pinta |
|---|---|
[convoca_curso id="123"] |
Portada: datos, precio, plazas, progreso y matrícula |
[convoca_curso_lecciones id="123"] |
Índice de módulos y lecciones con progreso y bloqueos |
[convoca_curso_leccion id="456"] |
Render de una lección concreta |
Si se omite id se usa el curso de la entrada actual (útil en la plantilla del CPT).
4. Formularios sin JavaScript¶
Convención del ecosistema: todo funciona sin JS.
| Acción | admin-post.php?action= |
Nonce |
|---|---|---|
| Matricularse | convoca_courses_enroll |
convoca_courses_enroll |
| Baja | convoca_courses_cancel |
convoca_courses_cancel_{id} |
| Marcar lección completada | convoca_courses_complete |
convoca_courses_complete_{lesson_id} |
La respuesta es siempre una redirección a la página de origen con convoca_msg (enrolled,
cancelled, completed, nonce, error). El JavaScript (assets/js/courses.js) solo renueva la URL
firmada del vídeo cuando caduca; sin él, se entrega una URL de vida más larga.
5. Plazas y concurrencia¶
Con plazas limitadas (_convoca_plazas > 0) la matrícula toma un lock del núcleo
(Utils::acquire_lock) y vuelve a contar dentro del lock: dos peticiones simultáneas no pueden
quedarse con la última plaza. Sin límite (0), no se toma lock.
5 bis. Cobro de la matrícula (opcional)¶
Si Convoca Gateway está activo y el curso tiene precio, la matrícula se cobra:
- La persona pulsa Comprar plaza — 25,00 EUR.
- La matrícula se crea en estado
pendiente(no da acceso) y se crea el pago en el gateway con origencourses. - Se redirige a la pasarela (tarjeta, Bizum o transferencia, según lo configurado).
- Cuando el gateway confirma el cobro dispara
convoca_payment_completed: la matrícula pasa aactivay se guarda la referencia del pago. Si el pago falla, la matrícula se quedapendiente.
En la portada del curso, una matrícula pendiente muestra el aviso y un botón para completar el pago (el enlace queda guardado, así que se puede retomar).
Sin gateway activo no cambia nada: matrícula gratuita, o cobrada fuera y marcada a mano desde el panel.
Requiere Convoca Gateway 2.13.19 o superior (antes la lista de orígenes de pago estaba cerrada a
enroll y members).
6. Certificado¶
- Se emite cuando el curso tiene
_convoca_certificadoy el progreso llega al 100 %. - Numeración propia y canónica: mayúsculas y solo letras y números (
CC+ curso + matrícula + 8 caracteres). La búsqueda normaliza lo que escribe la persona (guiones, espacios, minúsculas). - PDF con dompdf (el que ya trae
convoca-core) enuploads/convoca-courses/. - Verificación pública:
/verificar-curso/?codigo=CC…(y&formato=pdfpara el PDF). Un código inventado se rechaza. - La página de verificación se registra por reescritura: si el sitio no vuelve a guardar los enlaces permanentes tras activar, hay que hacerlo a mano (Ajustes → Enlaces permanentes → Guardar).
7. Vídeo (PRO)¶
El plugin no aloja ni transcodifica vídeo.
- Ajustes → Cursos → Ajustes: endpoint compatible con S3 (R2, B2, Wasabi, MinIO), bucket, región,
clave, secreto (guardado cifrado, prefijo
enc:), prefijo de objetos y estilo de ruta. - Se sirve con URL firmada AWS V4 de 900 s y
<video>nativo. La firma está probada contra el vector publicado por AWS. - Alternativa: URL externa pegada en la lección.
- Sin licencia, la lección de vídeo no ofrece el vídeo (texto, adjuntos y PDF siguen).
Licencia y gracia¶
| Estado | Texto, adjuntos y PDF | Vídeo |
|---|---|---|
| Sin licencia | sí | no |
| PRO activa | sí | sí |
| PRO caducada, ≤ 30 días | sí | sí (gracia) |
| PRO caducada, > 30 días | sí | no |
Filtro para entornos gestionados o pruebas: convoca_courses_has_pro.
8. Ganchos¶
| Gancho | Tipo | Cuándo |
|---|---|---|
convoca_courses_enrolled |
acción | Matrícula creada ($enrollment_id, $course_id, $user_id) |
convoca_courses_enrollment_cancelled |
acción | Matrícula cancelada ($enrollment_id) |
convoca_courses_certificate_issued |
acción | Certificado emitido ($enrollment_id, $code) |
convoca_courses_enrollment_paid |
acción | Matrícula activada por pago confirmado ($enrollment_id, $pago_id) |
convoca_courses_has_pro |
filtro | Resultado de la licencia PRO (bool) |
Referencia generada desde el código: Hooks — Courses.
9. Capabilities¶
| Capability | Para qué |
|---|---|
convoca_manage_courses |
Crear y editar cursos, módulos, lecciones y ajustes |
convoca_enroll_courses |
Reservada para integraciones que matriculan a otras personas |
convoca_view_certificates |
Consulta de certificados |
Se conceden a administrator y editor al activar.
10. Opciones¶
| Opción | Contenido |
|---|---|
convoca_courses_db_version |
Versión de esquema aplicada |
convoca_courses_video |
Configuración del almacenamiento de vídeo |
convoca_courses_keep_data |
Si al desinstalar se conservan cursos, matrículas y progreso |
uninstall.php borra todo salvo que convoca_courses_keep_data esté activo. El progreso nunca se
borra al desinstalar el plugin si esa opción está marcada: es el dato que no se puede reconstruir.
11. Estándares y pruebas¶
| Medida | Resultado |
|---|---|
PHPCS (WordPress, dominio convoca-courses) |
0 errores, 0 avisos |
| PHPStan nivel 5 | [OK] |
| PHPUnit 9.6 (8.2 y 8.3 en CI) | 40 pruebas: progreso, jerarquía, firma de vídeo, licencia y gracia, manifiesto |
| Plugin Check (PCP) | job propio del CI, versiones fijadas |
| Regla 0 | prueba automática: falla si aparece el nombre de una entidad concreta en el repo |
Las pruebas unitarias no necesitan WordPress. La comprobación de punta a punta se hace aparte, contra
un WordPress real, con dev-tools/verificar.php (modelo) y dev-tools/verificar-web.py (recorrido
sin JavaScript: entrar, matricularse, abrir lección, completarla, nonce falso rechazado).
12. Pendiente y limitaciones conocidas¶
- La feature
coursesdel circuito de licencias (License_Manager::pro_features()) y el mapeo del generador de licencias están en el camino, no publicados todavía. - Traducción
en_USdel.pot: pendiente. El.potestá generado y validado. - El CI cubre pruebas unitarias; las de integración con WordPress no están en el runner todavía.
- El cobro está probado contra el gateway real en un WordPress de desarrollo (matrícula pendiente, pago creado con su importe en céntimos, activación al confirmar y no-efecto de un pago de otro origen). No se ha hecho un cobro real contra el entorno de pruebas de Redsys.