Saltar a contenido

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:

  1. La persona pulsa Comprar plaza — 25,00 EUR.
  2. La matrícula se crea en estado pendiente (no da acceso) y se crea el pago en el gateway con origen courses.
  3. Se redirige a la pasarela (tarjeta, Bizum o transferencia, según lo configurado).
  4. Cuando el gateway confirma el cobro dispara convoca_payment_completed: la matrícula pasa a activa y se guarda la referencia del pago. Si el pago falla, la matrícula se queda pendiente.

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_certificado y 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) en uploads/convoca-courses/.
  • Verificación pública: /verificar-curso/?codigo=CC… (y &formato=pdf para 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 courses del 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_US del .pot: pendiente. El .pot está 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.