parent
59decff895
commit
5f79f57ca2
@ -0,0 +1,10 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
/** |
||||
* Strings to dutch L10n. |
||||
* |
||||
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com> |
||||
* |
||||
* @package chamilo.plugin.azure_active_directory |
||||
*/ |
||||
$strings['InvalidId'] = 'Deze identificatie is niet geldig (verkeerde log-in of wachtwoord). Errocode: AZMNF'; |
||||
@ -1,10 +1,11 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* Config the plugin. |
||||
* |
||||
* @package chamilo.plugin.customcertificate |
||||
* |
||||
* @author Jose Angel Ruiz <desarrollo@nosolored.com> |
||||
*/ |
||||
require_once __DIR__.'/../../main/inc/global.inc.php'; |
||||
|
||||
@ -1,4 +1,3 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
require_once 'config.php'; |
||||
|
||||
@ -1,77 +1,77 @@ |
||||
<?php |
||||
|
||||
$strings['plugin_title'] = 'Custom certificate'; |
||||
$strings['plugin_comment'] = 'This plugin allows you to create custom certificates for each course.'; |
||||
$strings['enable_plugin_customcertificate'] = 'Enable plugin'; |
||||
$strings['customcertificate_course_enable'] = 'Custom certificate enable in course'; |
||||
$strings['use_certificate_default'] = 'Use default custom certificate'; |
||||
$strings['ToolDisabled'] = 'The tool is disabled from the administration'; |
||||
$strings['OnlyAdminPlatform'] = 'Tool only for administrators'; |
||||
$strings['OnlyAdminPlatformOrTeacher'] = 'Tool only for administrators and teachers'; |
||||
$strings['TrainingEntity'] = 'Training entity'; |
||||
$strings['DescriptionFront'] = 'Description front'; |
||||
$strings['DescriptionRear'] = 'Description rear'; |
||||
$strings['Certify'] = 'Certify'; |
||||
$strings['CertificateType'] = 'Certificate type'; |
||||
$strings['CertifyThat'] = 'CERTIFY THAT'; |
||||
$strings['plugin_title'] = "Custom certificate"; |
||||
$strings['plugin_comment'] = "This plugin allows you to create custom certificates for each course."; |
||||
$strings['enable_plugin_customcertificate'] = "Enable plugin"; |
||||
$strings['customcertificate_course_enable'] = "Custom certificate enable in course"; |
||||
$strings['use_certificate_default'] = "Use default custom certificate"; |
||||
$strings['ToolDisabled'] = "The tool is disabled from the administration"; |
||||
$strings['OnlyAdminPlatform'] = "Tool only for administrators"; |
||||
$strings['OnlyAdminPlatformOrTeacher'] = "Tool only for administrators and teachers"; |
||||
$strings['TrainingEntity'] = "Training entity"; |
||||
$strings['DescriptionFront'] = "Description front"; |
||||
$strings['DescriptionRear'] = "Description rear"; |
||||
$strings['Certify'] = "Certify"; |
||||
$strings['CertificateType'] = "Certificate type"; |
||||
$strings['CertifyThat'] = "CERTIFY THAT"; |
||||
$strings['StudentCourseInfo'] = 'Student and Course data'; |
||||
$strings['StudentData'] = 'Student data'; |
||||
$strings['CourseData'] = 'Course data'; |
||||
$strings['Modality'] = 'Modality'; |
||||
$strings['Contents'] = 'Contents'; |
||||
$strings['ContentsToShow'] = 'Contents to show'; |
||||
$strings['StudentData'] = "Student data"; |
||||
$strings['CourseData'] = "Course data"; |
||||
$strings['Modality'] = "Modality"; |
||||
$strings['Contents'] = "Contents"; |
||||
$strings['ContentsToShow'] = "Contents to show"; |
||||
$strings['ContentsCourseDescription'] = 'Use section "Course description"> "Contents"'; |
||||
$strings['ContentsIndexLearnpath'] = 'Use learnpath index'; |
||||
$strings['ContentsCustom'] = 'Use custom content'; |
||||
$strings['ContentsHide'] = 'No show contents'; |
||||
$strings['Dates'] = 'Dates'; |
||||
$strings['CourseDeliveryDates'] = 'Course delivery dates'; |
||||
$strings['Custom'] = 'Custom'; |
||||
$strings['UseDateSessionAccess'] = 'Use access dates to the session'; |
||||
$strings['ExpectionPlace'] = 'Expection place'; |
||||
$strings['DateExpediction'] = 'Expediction date'; |
||||
$strings['UseDateEndAccessSession'] = 'Use end date of session access'; |
||||
$strings['UseDateDownloadCertificate'] = 'Use certificate download date'; |
||||
$strings['UseDateGenerationCertificate'] = 'Use certificate generation date'; |
||||
$strings['UseCustomDate'] = 'Use custom date'; |
||||
$strings['LogosSeal'] = 'Logos / Seals'; |
||||
$strings['LogoLeft'] = 'Logo left'; |
||||
$strings['LogoCenter'] = 'Logo center'; |
||||
$strings['LogoRight'] = 'Logo right'; |
||||
$strings['Seal'] = 'Seal'; |
||||
$strings['Signature1'] = 'Signature 1'; |
||||
$strings['Signature2'] = 'Signature 2'; |
||||
$strings['Signature3'] = 'Signature 3'; |
||||
$strings['Signature4'] = 'Signature 4'; |
||||
$strings['SignatureText1'] = 'Signature text 1'; |
||||
$strings['SignatureText2'] = 'Signature text 2'; |
||||
$strings['SignatureText3'] = 'Signature text 3'; |
||||
$strings['SignatureText4'] = 'Signature text 4'; |
||||
$strings['OtherOptions'] = 'Others options'; |
||||
$strings['MarginRight'] = 'Margin right'; |
||||
$strings['MarginLeft'] = 'Margin left'; |
||||
$strings['SetDefaultTemplate'] = 'Set template by default'; |
||||
$strings['MessageDefaultTemplate'] = 'Save this default customization for courses and sessions without |
||||
defined certificates'; |
||||
$strings['None'] = 'None'; |
||||
$strings['ErrorTemplateCertificate'] = 'There is no template defined for the certificate. |
||||
There is no template by default.'; |
||||
$strings['DateStartEnd'] = 'With Start date and End date: '; |
||||
$strings['ExpedictionIn'] = 'Expediction in'; |
||||
$strings['Signatures'] = 'Signatures'; |
||||
$strings['BackgroundCertificate'] = 'Background image of the certificate'; |
||||
$strings['Background'] = 'Background'; |
||||
$strings['CertificateSetting'] = 'Certificate setting'; |
||||
$strings['ToolDisabledCourse'] = 'Tool disabled in course setting'; |
||||
$strings['ToolUseDefaultSettingCourse'] = 'Tool configured to use the default certificate. <br> |
||||
$strings['ContentsIndexLearnpath'] = "Use learnpath index"; |
||||
$strings['ContentsCustom'] = "Use custom content"; |
||||
$strings['ContentsHide'] = "No show contents"; |
||||
$strings['Dates'] = "Dates"; |
||||
$strings['CourseDeliveryDates'] = "Course delivery dates"; |
||||
$strings['Custom'] = "Custom"; |
||||
$strings['UseDateSessionAccess'] = "Use access dates to the session"; |
||||
$strings['ExpectionPlace'] = "Expection place"; |
||||
$strings['DateExpediction'] = "Expediction date"; |
||||
$strings['UseDateEndAccessSession'] = "Use end date of session access"; |
||||
$strings['UseDateDownloadCertificate'] = "Use certificate download date"; |
||||
$strings['UseDateGenerationCertificate'] = "Use certificate generation date"; |
||||
$strings['UseCustomDate'] = "Use custom date"; |
||||
$strings['LogosSeal'] = "Logos / Seals"; |
||||
$strings['LogoLeft'] = "Logo left"; |
||||
$strings['LogoCenter'] = "Logo center"; |
||||
$strings['LogoRight'] = "Logo right"; |
||||
$strings['Seal'] = "Seal"; |
||||
$strings['Signature1'] = "Signature 1"; |
||||
$strings['Signature2'] = "Signature 2"; |
||||
$strings['Signature3'] = "Signature 3"; |
||||
$strings['Signature4'] = "Signature 4"; |
||||
$strings['SignatureText1'] = "Signature text 1"; |
||||
$strings['SignatureText2'] = "Signature text 2"; |
||||
$strings['SignatureText3'] = "Signature text 3"; |
||||
$strings['SignatureText4'] = "Signature text 4"; |
||||
$strings['OtherOptions'] = "Others options"; |
||||
$strings['MarginRight'] = "Margin right"; |
||||
$strings['MarginLeft'] = "Margin left"; |
||||
$strings['SetDefaultTemplate'] = "Set template by default"; |
||||
$strings['MessageDefaultTemplate'] = "Save this default customization for courses and sessions without |
||||
defined certificates"; |
||||
$strings['None'] = "None"; |
||||
$strings['ErrorTemplateCertificate'] = "There is no template defined for the certificate. |
||||
There is no template by default."; |
||||
$strings['DateStartEnd'] = "With Start date and End date: "; |
||||
$strings['ExpedictionIn'] = "Expediction in"; |
||||
$strings['Signatures'] = "Signatures"; |
||||
$strings['BackgroundCertificate'] = "Background image of the certificate"; |
||||
$strings['Background'] = "Background"; |
||||
$strings['CertificateSetting'] = "Certificate setting"; |
||||
$strings['ToolDisabledCourse'] = "Tool disabled in course setting"; |
||||
$strings['ToolUseDefaultSettingCourse'] = "Tool configured to use the default certificate. <br> |
||||
You can edit it from the Administration screen -> Plugins -> Custom Certificate. <br> |
||||
Or if you want you can disable the option to use certificate by default in the plugin configuration in the course'; |
||||
$strings['CertificateSettingDefault'] = 'Default certificate settings'; |
||||
$strings['InfoFromDefaultCertificate'] = 'The content of the certificate is based on the default certificate. |
||||
The modifications you make will not affect the default certificate.'; |
||||
$strings['to'] = ' to '; |
||||
$strings['formatDownloadDate'] = ' to %sth %s, %s'; |
||||
$strings['PrintCertificate'] = 'Print certificate'; |
||||
$strings['QuestionDelete'] = 'Do you want to delete the specific diploma and use the default certificate?'; |
||||
$strings['SuccessDelete'] = 'Successfully deleted'; |
||||
$strings['ProblemDelete'] = 'Problem deleting the certificate'; |
||||
Or if you want you can disable the option to use certificate by default in the plugin configuration in the course"; |
||||
$strings['CertificateSettingDefault'] = "Default certificate settings"; |
||||
$strings['InfoFromDefaultCertificate'] = "The content of the certificate is based on the default certificate. |
||||
The modifications you make will not affect the default certificate."; |
||||
$strings['to'] = " to "; |
||||
$strings['formatDownloadDate'] = " to %sth %s, %s"; |
||||
$strings['PrintCertificate'] = "Print certificate"; |
||||
$strings['QuestionDelete'] = "Do you want to delete the specific diploma and use the default certificate?"; |
||||
$strings['SuccessDelete'] = "Successfully deleted"; |
||||
$strings['ProblemDelete'] = "Problem deleting the certificate"; |
||||
$strings['OnlyCustomCertificates'] = "Only courses with a personalized certificate are exported"; |
||||
|
||||
@ -1,79 +1,79 @@ |
||||
<?php |
||||
|
||||
$strings['plugin_title'] = 'Certificado personalizado'; |
||||
$strings['plugin_comment'] = 'Este plugin permite crear certificados personalizados por curso.'; |
||||
$strings['enable_plugin_customcertificate'] = 'Activar plugin'; |
||||
$strings['customcertificate_course_enable'] = 'Habilitar en el curso el certificado alternativo'; |
||||
$strings['use_certificate_default'] = 'Usar el certificado personalizado por defecto'; |
||||
$strings['ToolDisabled'] = 'La herramienta está deshabilitada desde la administración'; |
||||
$strings['OnlyAdminPlatform'] = 'Herramienta exclusiva para administradores'; |
||||
$strings['OnlyAdminPlatformOrTeacher'] = 'Herramienta para administradores y profesores'; |
||||
$strings['TrainingEntity'] = 'Entidad formadora'; |
||||
$strings['DescriptionFront'] = 'Descripción principal'; |
||||
$strings['DescriptionRear'] = 'Descripción trasera'; |
||||
$strings['Certify'] = 'Certifica'; |
||||
$strings['CertificateType'] = 'Tipo certificado'; |
||||
$strings['CertifyThat'] = 'CERTIFICA QUE'; |
||||
$strings['plugin_title'] = "Certificado personalizado"; |
||||
$strings['plugin_comment'] = "Este plugin permite crear certificados personalizados por curso."; |
||||
$strings['enable_plugin_customcertificate'] = "Activar plugin"; |
||||
$strings['customcertificate_course_enable'] = "Habilitar en el curso el certificado alternativo"; |
||||
$strings['use_certificate_default'] = "Usar el certificado personalizado por defecto"; |
||||
$strings['ToolDisabled'] = "La herramienta está deshabilitada desde la administración"; |
||||
$strings['OnlyAdminPlatform'] = "Herramienta exclusiva para administradores"; |
||||
$strings['OnlyAdminPlatformOrTeacher'] = "Herramienta para administradores y profesores"; |
||||
$strings['TrainingEntity'] = "Entidad formadora"; |
||||
$strings['DescriptionFront'] = "Descripción principal"; |
||||
$strings['DescriptionRear'] = "Descripción trasera"; |
||||
$strings['Certify'] = "Certifica"; |
||||
$strings['CertificateType'] = "Tipo certificado"; |
||||
$strings['CertifyThat'] = "CERTIFICA QUE"; |
||||
$strings['StudentCourseInfo'] = 'Datos del alumno y curso'; |
||||
$strings['StudentData'] = 'Datos estudiante'; |
||||
$strings['CourseData'] = 'Datos curso'; |
||||
$strings['Modality'] = 'Modalidad'; |
||||
$strings['Contents'] = 'Contenidos'; |
||||
$strings['ContentsToShow'] = 'Contenidos a mostrar'; |
||||
$strings['StudentData'] = "Datos estudiante"; |
||||
$strings['CourseData'] = "Datos curso"; |
||||
$strings['Modality'] = "Modalidad"; |
||||
$strings['Contents'] = "Contenidos"; |
||||
$strings['ContentsToShow'] = "Contenidos a mostrar"; |
||||
$strings['ContentsCourseDescription'] = 'Usar apartado "Descripcion del curso" > "Contenidos"'; |
||||
$strings['ContentsIndexLearnpath'] = 'Usar indice de lecciones'; |
||||
$strings['ContentsCustom'] = 'Usar contenido personalizado'; |
||||
$strings['ContentsHide'] = 'No mostrar contenidos'; |
||||
$strings['Dates'] = 'Fechas'; |
||||
$strings['CourseDeliveryDates'] = 'Fechas de impartición del curso'; |
||||
$strings['Custom'] = 'Personalizado'; |
||||
$strings['UseDateSessionAccess'] = 'Usar fechas de acceso a la sesión'; |
||||
$strings['ExpectionPlace'] = 'Lugar expedición'; |
||||
$strings['DateExpediction'] = 'Fecha expedición'; |
||||
$strings['UseDateEndAccessSession'] = 'Usar fecha fin de acceso de la sesión'; |
||||
$strings['UseDateDownloadCertificate'] = 'Usar fecha de descarga del certificado'; |
||||
$strings['UseDateGenerationCertificate'] = 'Usar fecha de generación del certificado'; |
||||
$strings['UseCustomDate'] = 'Usar fechas personalizadas'; |
||||
$strings['LogosSeal'] = 'Logos / Sellos'; |
||||
$strings['LogoLeft'] = 'Logo izquierda'; |
||||
$strings['LogoCenter'] = 'Logo central'; |
||||
$strings['LogoRight'] = 'Logo derecha'; |
||||
$strings['Seal'] = 'Sello'; |
||||
$strings['Signature1'] = 'Firma 1'; |
||||
$strings['Signature2'] = 'Firma 2'; |
||||
$strings['Signature3'] = 'Firma 3'; |
||||
$strings['Signature4'] = 'Firma 4'; |
||||
$strings['SignatureText1'] = 'Texto firma 1'; |
||||
$strings['SignatureText2'] = 'Texto firma 2'; |
||||
$strings['SignatureText3'] = 'Texto firma 3'; |
||||
$strings['SignatureText4'] = 'Texto firma 4'; |
||||
$strings['OtherOptions'] = 'Otras opciones'; |
||||
$strings['MarginRight'] = 'Margen derecho'; |
||||
$strings['MarginLeft'] = 'Margen izquierdo'; |
||||
$strings['SetDefaultTemplate'] = 'Establecer plantilla por defecto'; |
||||
$strings['MessageDefaultTemplate'] = 'Guardar esta personalización por defecto para cursos y |
||||
sesiones sin certificados definidos'; |
||||
$strings['None'] = 'Ninguno'; |
||||
$strings['ErrorTemplateCertificate'] = 'No hay una plantilla definida para el certificado. |
||||
No existe plantilla por defecto.'; |
||||
$strings['DateStartEnd'] = 'Con Fecha de inicio y Fecha fin: '; |
||||
$strings['ExpedictionIn'] = 'Expedido en'; |
||||
$strings['Signatures'] = 'Firmas'; |
||||
$strings['BackgroundCertificate'] = 'Imagen de fondo del certificado'; |
||||
$strings['Background'] = 'Fondo'; |
||||
$strings['CertificateSetting'] = 'Configuración Certificado'; |
||||
$strings['ToolDisabledCourse'] = 'Herramienta desabilitada en el curso'; |
||||
$strings['ToolUseDefaultSettingCourse'] = 'Herramienta configurada para usar el certificado por defecto.<br> |
||||
$strings['ContentsIndexLearnpath'] = "Usar indice de lecciones"; |
||||
$strings['ContentsCustom'] = "Usar contenido personalizado"; |
||||
$strings['ContentsHide'] = "No mostrar contenidos"; |
||||
$strings['Dates'] = "Fechas"; |
||||
$strings['CourseDeliveryDates'] = "Fechas de impartición del curso"; |
||||
$strings['Custom'] = "Personalizado"; |
||||
$strings['UseDateSessionAccess'] = "Usar fechas de acceso a la sesión"; |
||||
$strings['ExpectionPlace'] = "Lugar expedición"; |
||||
$strings['DateExpediction'] = "Fecha expedición"; |
||||
$strings['UseDateEndAccessSession'] = "Usar fecha fin de acceso de la sesión"; |
||||
$strings['UseDateDownloadCertificate'] = "Usar fecha de descarga del certificado"; |
||||
$strings['UseDateGenerationCertificate'] = "Usar fecha de generación del certificado"; |
||||
$strings['UseCustomDate'] = "Usar fechas personalizadas"; |
||||
$strings['LogosSeal'] = "Logos / Sellos"; |
||||
$strings['LogoLeft'] = "Logo izquierda"; |
||||
$strings['LogoCenter'] = "Logo central"; |
||||
$strings['LogoRight'] = "Logo derecha"; |
||||
$strings['Seal'] = "Sello"; |
||||
$strings['Signature1'] = "Firma 1"; |
||||
$strings['Signature2'] = "Firma 2"; |
||||
$strings['Signature3'] = "Firma 3"; |
||||
$strings['Signature4'] = "Firma 4"; |
||||
$strings['SignatureText1'] = "Texto firma 1"; |
||||
$strings['SignatureText2'] = "Texto firma 2"; |
||||
$strings['SignatureText3'] = "Texto firma 3"; |
||||
$strings['SignatureText4'] = "Texto firma 4"; |
||||
$strings['OtherOptions'] = "Otras opciones"; |
||||
$strings['MarginRight'] = "Margen derecho"; |
||||
$strings['MarginLeft'] = "Margen izquierdo"; |
||||
$strings['SetDefaultTemplate'] = "Establecer plantilla por defecto"; |
||||
$strings['MessageDefaultTemplate'] = "Guardar esta personalización por defecto para cursos y |
||||
sesiones sin certificados definidos"; |
||||
$strings['None'] = "Ninguno"; |
||||
$strings['ErrorTemplateCertificate'] = "No hay una plantilla definida para el certificado. |
||||
No existe plantilla por defecto."; |
||||
$strings['DateStartEnd'] = "Con Fecha de inicio y Fecha fin: "; |
||||
$strings['ExpedictionIn'] = "Expedido en"; |
||||
$strings['Signatures'] = "Firmas"; |
||||
$strings['BackgroundCertificate'] = "Imagen de fondo del certificado"; |
||||
$strings['Background'] = "Fondo"; |
||||
$strings['CertificateSetting'] = "Configuración Certificado"; |
||||
$strings['ToolDisabledCourse'] = "Herramienta desabilitada en el curso"; |
||||
$strings['ToolUseDefaultSettingCourse'] = "Herramienta configurada para usar el certificado por defecto.<br> |
||||
Podrá editarlo desde la pantalla de Administración -> Plugins -> Certificado personalizado.<br> |
||||
O si lo desea puede desactivar la opción de usar certificado por defecto en la configuración del |
||||
plugin en el curso'; |
||||
$strings['CertificateSettingDefault'] = 'Configuración del certificado por defecto'; |
||||
$strings['InfoFromDefaultCertificate'] = 'El contenido del certificado está basado en el certificado por defecto. |
||||
Las modificaciones que realice no afectará al certificado por defecto.'; |
||||
$strings['to'] = ' a '; |
||||
$strings['formatDownloadDate'] = ' a %s de %s de %s'; |
||||
$strings['MessageUpdate'] = 'El proceso de actualización ha terminado'; |
||||
$strings['PrintCertificate'] = 'Imprimir certificado'; |
||||
$strings['QuestionDelete'] = '¿Desea eliminar el diploma específico y volver a usar el certificado por defecto?'; |
||||
$strings['SuccessDelete'] = 'Borrado con éxito'; |
||||
$strings['ProblemDelete'] = 'Hubo un problema al borrar el certificado'; |
||||
plugin en el curso"; |
||||
$strings['CertificateSettingDefault'] = "Configuración del certificado por defecto"; |
||||
$strings['InfoFromDefaultCertificate'] = "El contenido del certificado está basado en el certificado por defecto. |
||||
Las modificaciones que realice no afectará al certificado por defecto."; |
||||
$strings['to'] = " a "; |
||||
$strings['formatDownloadDate'] = " a %s de %s de %s"; |
||||
$strings['MessageUpdate'] = "El proceso de actualización ha terminado"; |
||||
$strings['PrintCertificate'] = "Imprimir certificado"; |
||||
$strings['QuestionDelete'] = "¿Desea eliminar el diploma específico y volver a usar el certificado por defecto?"; |
||||
$strings['SuccessDelete'] = "Borrado con éxito"; |
||||
$strings['ProblemDelete'] = "Hubo un problema al borrar el certificado"; |
||||
$strings['OnlyCustomCertificates'] = "Solo se exportan los diplomas de cursos con certificado personalizado"; |
||||
|
||||
@ -0,0 +1,708 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
use Chamilo\CourseBundle\Entity\CLpCategory; |
||||
|
||||
$course_plugin = 'customcertificate'; |
||||
require_once __DIR__.'/../config.php'; |
||||
|
||||
api_block_anonymous_users(); |
||||
$plugin = CustomCertificatePlugin::create(); |
||||
$enable = $plugin->get('enable_plugin_customcertificate') === 'true'; |
||||
$tblProperty = Database::get_course_table(TABLE_ITEM_PROPERTY); |
||||
$tblCourse = Database::get_main_table(TABLE_MAIN_COURSE); |
||||
$tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE); |
||||
$tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION); |
||||
|
||||
define('NO_DATE_FILTER', 0); |
||||
define('DATE_BEGIN_FILTER', 1); |
||||
define('DATE_END_FILTER', 2); |
||||
define('ALL_DATE_FILTER', 3); |
||||
|
||||
if (!$enable) { |
||||
api_not_allowed(true, $plugin->get_lang('ToolDisabled')); |
||||
} |
||||
|
||||
$currentLocalTime = api_get_local_time(); |
||||
$accessUrlId = api_get_current_access_url_id(); |
||||
|
||||
$sessionId = isset($_GET['session_id']) ? (int) $_GET['session_id'] : null; |
||||
$dateBegin = isset($_GET['date_begin']) ? strtotime($_GET['date_begin']) : null; |
||||
$dateEnd = isset($_GET['date_end']) ? strtotime($_GET['date_end'].' 23:59:59') : null; |
||||
|
||||
if (api_is_multiple_url_enabled()) { |
||||
if ($accessUrlId != -1) { |
||||
$result = Database::select( |
||||
'*', |
||||
"$tblSessionRelAccessUrl", |
||||
[ |
||||
'where' => [ |
||||
"access_url_id = ? AND session_id = ?" => [$accessUrlId, $sessionId], |
||||
], |
||||
] |
||||
); |
||||
|
||||
if (empty($result)) { |
||||
api_not_allowed(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
$exportAllInOne = isset($_GET['export_pdf']) ? (int) $_GET['export_pdf'] : false; |
||||
$exportZip = isset($_GET['export_zip']) ? (int) $_GET['export_zip'] : false; |
||||
|
||||
$filterDate = 0; |
||||
if (!empty($dateBegin)) { |
||||
$filterDate += DATE_BEGIN_FILTER; |
||||
} |
||||
if (!empty($dateEnd)) { |
||||
$filterDate += DATE_END_FILTER; |
||||
} |
||||
|
||||
$filterCheckList = []; |
||||
$extraField = new ExtraField('user'); |
||||
$extraFieldsAll = $extraField->get_all(['filter = ?' => 1], 'option_order'); |
||||
foreach ($extraFieldsAll as $field) { |
||||
if (!empty($_GET['extra_'.$field['variable']])) { |
||||
$filterCheckList[$field['id']] = $field; |
||||
} |
||||
} |
||||
|
||||
$result = Database::select( |
||||
'c.id, c.code', |
||||
"$tblCourse c INNER JOIN $tblSessionRelCourse r ON c.id = r.c_id", |
||||
[ |
||||
'where' => [ |
||||
"r.session_id = ? " => [$sessionId], |
||||
], |
||||
] |
||||
); |
||||
|
||||
foreach ($result as $value) { |
||||
$courseId = $value['id']; |
||||
$courseCode = $value['code']; |
||||
|
||||
$cats = Category::load( |
||||
null, |
||||
null, |
||||
$courseCode, |
||||
null, |
||||
null, |
||||
$sessionId, |
||||
'ORDER BY id' |
||||
); |
||||
|
||||
if (empty($cats)) { |
||||
// first time |
||||
$cats = Category::load( |
||||
0, |
||||
null, |
||||
$courseCode, |
||||
null, |
||||
null, |
||||
$sessionId, |
||||
'ORDER BY id' |
||||
); |
||||
} |
||||
|
||||
$selectCat = (int) $cats[0]->get_id(); |
||||
$certificateList = []; |
||||
$certificateListAux = GradebookUtils::get_list_users_certificates($selectCat); |
||||
|
||||
foreach ($certificateListAux as $value) { |
||||
$created_at = strtotime(api_get_local_time($value['created_at'])); |
||||
$value['category_id'] = $selectCat; |
||||
$value['c_id'] = $courseId; |
||||
$value['course_code'] = $courseCode; |
||||
switch ($filterDate) { |
||||
case NO_DATE_FILTER: |
||||
$certificateList[] = $value; |
||||
break; |
||||
case DATE_BEGIN_FILTER: |
||||
if ($created_at >= $dateBegin) { |
||||
$certificateList[] = $value; |
||||
} |
||||
break; |
||||
case DATE_END_FILTER: |
||||
if ($created_at <= $dateEnd) { |
||||
$certificateList[] = $value; |
||||
} |
||||
break; |
||||
case ALL_DATE_FILTER: |
||||
if ($created_at >= $dateBegin && $created_at <= $dateEnd) { |
||||
$certificateList[] = $value; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
// Filter extra field |
||||
foreach ($certificateList as $key => $value) { |
||||
foreach ($filterCheckList as $fieldId => $field) { |
||||
$extraFieldValue = new ExtraFieldValue('user'); |
||||
$extraFieldValueData = $extraFieldValue->get_values_by_handler_and_field_id( |
||||
$value['user_id'], |
||||
$fieldId |
||||
); |
||||
|
||||
if (empty($extraFieldValueData)) { |
||||
unset($certificateList[$key]); |
||||
break; |
||||
} |
||||
|
||||
switch ($field['field_type']) { |
||||
case ExtraField::FIELD_TYPE_TEXT: |
||||
case ExtraField::FIELD_TYPE_ALPHANUMERIC: |
||||
$pos = stripos($extraFieldValueData['value'], $_GET['extra_'.$field['variable']]); |
||||
if ($pos === false) { |
||||
unset($certificateList[$key]); |
||||
} |
||||
break; |
||||
case ExtraField::FIELD_TYPE_RADIO: |
||||
$valueRadio = $_GET['extra_'.$field['variable']]['extra_'.$field['variable']]; |
||||
if ($extraFieldValueData['value'] != $valueRadio) { |
||||
unset($certificateList[$key]); |
||||
} |
||||
break; |
||||
case ExtraField::FIELD_TYPE_SELECT: |
||||
if ($extraFieldValueData['value'] != $_GET['extra_'.$field['variable']]) { |
||||
unset($certificateList[$key]); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
$userList = []; |
||||
foreach ($certificateList as $index => $value) { |
||||
$infoUser = api_get_user_info($value['user_id']); |
||||
$infoUser['category_id'] = $value['category_id']; |
||||
$infoUser['c_id'] = $value['c_id']; |
||||
$infoUser['course_code'] = $value['course_code']; |
||||
$userList[] = $infoUser; |
||||
} |
||||
|
||||
$sessionInfo = []; |
||||
if ($sessionId > 0) { |
||||
$sessionInfo = SessionManager::fetch($sessionId); |
||||
} |
||||
|
||||
$path = api_get_path(WEB_UPLOAD_PATH).'certificates/'; |
||||
$htmlList = []; |
||||
|
||||
foreach ($userList as $userInfo) { |
||||
$courseId = $userInfo['c_id']; |
||||
$courseCode = $userInfo['course_code']; |
||||
$studentId = $userInfo['user_id']; |
||||
|
||||
$courseInfo = api_get_course_info($courseCode); |
||||
$allowCustomCertificate = api_get_course_setting('customcertificate_course_enable', $courseInfo); |
||||
if (!$allowCustomCertificate) { |
||||
continue; |
||||
} |
||||
|
||||
// Get info certificate |
||||
$infoCertificate = CustomCertificatePlugin::getInfoCertificate($courseId, $sessionId, $accessUrlId); |
||||
|
||||
if (!is_array($infoCertificate)) { |
||||
$infoCertificate = []; |
||||
} |
||||
|
||||
if (empty($infoCertificate)) { |
||||
$infoCertificate = CustomCertificatePlugin::getInfoCertificateDefault($accessUrlId); |
||||
|
||||
if (empty($infoCertificate)) { |
||||
Display::display_header($plugin->get_lang('PrintCertificate')); |
||||
echo Display::return_message($plugin->get_lang('ErrorTemplateCertificate'), 'error'); |
||||
Display::display_footer(); |
||||
exit; |
||||
} |
||||
} |
||||
|
||||
$workSpace = intval(297 - $infoCertificate['margin_left'] - $infoCertificate['margin_right']); |
||||
$widthCell = intval($workSpace / 6); |
||||
|
||||
$htmlText = ''; |
||||
if (!$exportAllInOne) { |
||||
$htmlText = '<html>'; |
||||
$htmlText .= ' |
||||
<link rel="stylesheet" |
||||
type="text/css" |
||||
href="'.api_get_path(WEB_PLUGIN_PATH).'customcertificate/resources/css/certificate.css">'; |
||||
$htmlText .= ' |
||||
<link rel="stylesheet" |
||||
type="text/css" |
||||
href="'.api_get_path(WEB_CSS_PATH).'document.css">'; |
||||
$htmlText .= '<body>'; |
||||
} |
||||
$studentId = $userInfo['user_id']; |
||||
|
||||
if (empty($infoCertificate['background'])) { |
||||
$htmlText .= '<div class="caraA" style="page-break-before:always; margin:0px; padding:0px;">'; |
||||
} else { |
||||
$urlBackground = $path.$infoCertificate['background']; |
||||
$htmlText .= ' <div |
||||
class="caraA" |
||||
style="background-image:url('.$urlBackground.') no-repeat; |
||||
background-image-resize:6; margin:0px; padding:0px;">'; |
||||
} |
||||
|
||||
if (!empty($infoCertificate['logo_left'])) { |
||||
$logoLeft = ' |
||||
<img |
||||
style="max-height: 150px; max-width: '.(2 * $widthCell).'mm;" |
||||
src="'.$path.$infoCertificate['logo_left'].'" />'; |
||||
} else { |
||||
$logoLeft = ''; |
||||
} |
||||
|
||||
$logoCenter = ''; |
||||
if (!empty($infoCertificate['logo_center'])) { |
||||
$logoCenter = ' |
||||
<img |
||||
style="max-height: 150px; max-width: '.intval($workSpace - (2 * $widthCell)).'mm;" |
||||
src="'.$path.$infoCertificate['logo_center'].'" />'; |
||||
} |
||||
|
||||
$logoRight = ''; |
||||
if (!empty($infoCertificate['logo_right'])) { |
||||
$logoRight = ' |
||||
<img |
||||
style="max-height: 150px; max-width: '.(2 * $widthCell).'mm;" |
||||
src="'.$path.$infoCertificate['logo_right'].'" />'; |
||||
} |
||||
|
||||
$htmlText .= '<table |
||||
width="'.$workSpace.'mm" |
||||
style=" |
||||
margin-left:'.$infoCertificate['margin_left'].'mm; |
||||
margin-right:'.$infoCertificate['margin_right'].'mm; |
||||
" |
||||
border="0">'; |
||||
$htmlText .= '<tr>'; |
||||
$htmlText .= '<td style="width:'.intval($workSpace / 3).'mm" class="logo">'.$logoLeft.'</td>'; |
||||
$htmlText .= '<td style="width:'.intval($workSpace / 3).'mm; text-align:center;" class="logo">'; |
||||
$htmlText .= $logoCenter; |
||||
$htmlText .= '</td>'; |
||||
$htmlText .= '<td style="width:'.intval($workSpace / 3).'mm; text-align:right;" class="logo">'.$logoRight.'</td>'; |
||||
$htmlText .= '</tr>'; |
||||
$htmlText .= '</table>'; |
||||
|
||||
$allUserInfo = DocumentManager::get_all_info_to_certificate( |
||||
$studentId, |
||||
$courseCode, |
||||
$sessionId, |
||||
false |
||||
); |
||||
|
||||
$myContentHtml = $infoCertificate['content_course']; |
||||
$myContentHtml = str_replace(chr(13).chr(10).chr(13).chr(10), chr(13).chr(10), $myContentHtml); |
||||
$infoToBeReplacedInContentHtml = $allUserInfo[0]; |
||||
$infoToReplaceInContentHtml = $allUserInfo[1]; |
||||
$myContentHtml = str_replace( |
||||
$infoToBeReplacedInContentHtml, |
||||
$infoToReplaceInContentHtml, |
||||
$myContentHtml |
||||
); |
||||
|
||||
$startDate = ''; |
||||
$endDate = ''; |
||||
switch ($infoCertificate['date_change']) { |
||||
case 0: |
||||
if (!empty($sessionInfo['access_start_date'])) { |
||||
$startDate = date("d/m/Y", strtotime(api_get_local_time($sessionInfo['access_start_date']))); |
||||
} |
||||
if (!empty($sessionInfo['access_end_date'])) { |
||||
$endDate = date("d/m/Y", strtotime(api_get_local_time($sessionInfo['access_end_date']))); |
||||
} |
||||
break; |
||||
case 1: |
||||
$startDate = date("d/m/Y", strtotime($infoCertificate['date_start'])); |
||||
$endDate = date("d/m/Y", strtotime($infoCertificate['date_end'])); |
||||
break; |
||||
} |
||||
|
||||
$myContentHtml = str_replace( |
||||
'((start_date))', |
||||
$startDate, |
||||
$myContentHtml |
||||
); |
||||
|
||||
$myContentHtml = str_replace( |
||||
'((end_date))', |
||||
$endDate, |
||||
$myContentHtml |
||||
); |
||||
|
||||
$dateExpediction = ''; |
||||
if ($infoCertificate['type_date_expediction'] != 3) { |
||||
$dateExpediction .= $plugin->get_lang('ExpedictionIn').' '.$infoCertificate['place']; |
||||
if ($infoCertificate['type_date_expediction'] == 1) { |
||||
$dateExpediction .= $plugin->get_lang('to').api_format_date(time(), DATE_FORMAT_LONG); |
||||
} elseif ($infoCertificate['type_date_expediction'] == 2) { |
||||
$dateFormat = $plugin->get_lang('formatDownloadDate'); |
||||
if (!empty($infoCertificate['day']) && |
||||
!empty($infoCertificate['month']) && |
||||
!empty($infoCertificate['year']) |
||||
) { |
||||
$dateExpediction .= sprintf( |
||||
$dateFormat, |
||||
$infoCertificate['day'], |
||||
$infoCertificate['month'], |
||||
$infoCertificate['year'] |
||||
); |
||||
} else { |
||||
$dateExpediction .= sprintf( |
||||
$dateFormat, |
||||
'......', |
||||
'....................', |
||||
'............' |
||||
); |
||||
} |
||||
} elseif ($infoCertificate['type_date_expediction'] == 4) { |
||||
$dateExpediction .= $plugin->get_lang('to').$infoToReplaceInContentHtml[9]; //date_certificate_no_time |
||||
} else { |
||||
if (!empty($sessionInfo)) { |
||||
$dateInfo = api_get_local_time($sessionInfo['access_end_date']); |
||||
$dateExpediction .= $plugin->get_lang('to').api_format_date($dateInfo, DATE_FORMAT_LONG); |
||||
} |
||||
} |
||||
} |
||||
|
||||
$myContentHtml = str_replace( |
||||
'((date_expediction))', |
||||
$dateExpediction, |
||||
$myContentHtml |
||||
); |
||||
|
||||
$myContentHtml = strip_tags( |
||||
$myContentHtml, |
||||
'<p><b><strong><table><tr><td><th><tbody><span><i><li><ol><ul> |
||||
<dd><dt><dl><br><hr><img><a><div><h1><h2><h3><h4><h5><h6>' |
||||
); |
||||
|
||||
$htmlText .= '<div style=" |
||||
height: 480px; |
||||
width:'.$workSpace.'mm; |
||||
margin-left:'.$infoCertificate['margin_left'].'mm; |
||||
margin-right:'.$infoCertificate['margin_right'].'mm; |
||||
">'; |
||||
$htmlText .= $myContentHtml; |
||||
$htmlText .= '</div>'; |
||||
|
||||
$htmlText .= '<table |
||||
width="'.$workSpace.'mm" |
||||
style=" |
||||
margin-left:'.$infoCertificate['margin_left'].'mm; |
||||
margin-right:'.$infoCertificate['margin_right'].'mm; |
||||
" |
||||
border="0">'; |
||||
|
||||
$htmlText .= '<tr>'; |
||||
$htmlText .= '<td colspan="2" class="seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature_text1'])) ? $infoCertificate['signature_text1'] : ''). |
||||
'</td> |
||||
<td colspan="2" class="seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature_text2'])) ? $infoCertificate['signature_text2'] : ''). |
||||
'</td> |
||||
<td colspan="2" class="seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature_text3'])) ? $infoCertificate['signature_text3'] : ''). |
||||
'</td> |
||||
<td colspan="2" class="seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature_text4'])) ? $infoCertificate['signature_text4'] : ''). |
||||
'</td> |
||||
<td colspan="4" class="seals" style="width:'.(2 * $widthCell).'mm"> |
||||
'.((!empty($infoCertificate['seal'])) ? $plugin->get_lang('Seal') : ''). |
||||
'</td>'; |
||||
$htmlText .= '</tr>'; |
||||
$htmlText .= '<tr>'; |
||||
$htmlText .= '<td colspan="2" class="logo-seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature1'])) |
||||
? '<img style="max-height: 100px; max-width: '.$widthCell.'mm;" |
||||
src="'.$path.$infoCertificate['signature1'].'" />' |
||||
: ''). |
||||
'</td> |
||||
<td colspan="2" class="logo-seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature2'])) |
||||
? '<img style="max-height: 100px; '.$widthCell.'mm;" |
||||
src="'.$path.$infoCertificate['signature2'].'" />' |
||||
: ''). |
||||
'</td> |
||||
<td colspan="2" class="logo-seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature3'])) |
||||
? '<img style="max-height: 100px; '.$widthCell.'mm;" |
||||
src="'.$path.$infoCertificate['signature3'].'" />' |
||||
: ''). |
||||
'</td> |
||||
<td colspan="2" class="logo-seals" style="width:'.$widthCell.'mm">'. |
||||
((!empty($infoCertificate['signature4'])) |
||||
? '<img style="max-height: 100px; '.$widthCell.'mm;" |
||||
src="'.$path.$infoCertificate['signature4'].'" />' |
||||
: ''). |
||||
'</td> |
||||
<td colspan="4" class="logo-seals" style="width:'.(2 * $widthCell).'mm">'. |
||||
((!empty($infoCertificate['seal'])) |
||||
? '<img style="max-height: 100px; '.(2 * $widthCell).'mm;" |
||||
src="'.$path.$infoCertificate['seal'].'" />' |
||||
: ''). |
||||
'</td>'; |
||||
$htmlText .= '</tr>'; |
||||
$htmlText .= '</table>'; |
||||
$htmlText .= '</div>'; |
||||
|
||||
// Rear certificate |
||||
if ($infoCertificate['contents_type'] != 3) { |
||||
$htmlText .= '<div class="caraB" style="page-break-before:always; margin:0px; padding:0px;">'; |
||||
if ($infoCertificate['contents_type'] == 0) { |
||||
$courseDescription = new CourseDescription(); |
||||
$contentDescription = $courseDescription->get_data_by_description_type(3, $courseId, 0); |
||||
$domd = new DOMDocument(); |
||||
libxml_use_internal_errors(true); |
||||
if (isset($contentDescription['description_content'])) { |
||||
$domd->loadHTML($contentDescription['description_content']); |
||||
} |
||||
libxml_use_internal_errors(false); |
||||
$domx = new DOMXPath($domd); |
||||
$items = $domx->query("//li[@style]"); |
||||
foreach ($items as $item) { |
||||
$item->removeAttribute("style"); |
||||
} |
||||
|
||||
$items = $domx->query("//span[@style]"); |
||||
foreach ($items as $item) { |
||||
$item->removeAttribute("style"); |
||||
} |
||||
|
||||
$output = $domd->saveHTML(); |
||||
$htmlText .= getIndexFiltered($output); |
||||
} |
||||
|
||||
if ($infoCertificate['contents_type'] == 1) { |
||||
$items = []; |
||||
$categoriesTempList = learnpath::getCategories($courseId); |
||||
$categoryTest = new CLpCategory(); |
||||
$categoryTest->setId(0); |
||||
$categoryTest->setName($plugin->get_lang('WithOutCategory')); |
||||
$categoryTest->setPosition(0); |
||||
$categories = [$categoryTest]; |
||||
|
||||
if (!empty($categoriesTempList)) { |
||||
$categories = array_merge($categories, $categoriesTempList); |
||||
} |
||||
|
||||
foreach ($categories as $item) { |
||||
$categoryId = $item->getId(); |
||||
|
||||
if (!learnpath::categoryIsVisibleForStudent($item, api_get_user_entity($studentId))) { |
||||
continue; |
||||
} |
||||
|
||||
$sql = "SELECT 1 |
||||
FROM $tblProperty |
||||
WHERE tool = 'learnpath_category' |
||||
AND ref = $categoryId |
||||
AND visibility = 0 |
||||
AND (session_id = $sessionId OR session_id IS NULL)"; |
||||
$res = Database::query($sql); |
||||
if (Database::num_rows($res) > 0) { |
||||
continue; |
||||
} |
||||
|
||||
$list = new LearnpathList( |
||||
$studentId, |
||||
$courseCode, |
||||
$sessionId, |
||||
null, |
||||
false, |
||||
$categoryId |
||||
); |
||||
|
||||
$flat_list = $list->get_flat_list(); |
||||
|
||||
if (empty($flat_list)) { |
||||
continue; |
||||
} |
||||
|
||||
if (count($categories) > 1 && count($flat_list) > 0) { |
||||
if ($item->getName() != $plugin->get_lang('WithOutCategory')) { |
||||
$items[] = '<h4 style="margin:0">'.$item->getName().'</h4>'; |
||||
} |
||||
} |
||||
|
||||
foreach ($flat_list as $learnpath) { |
||||
$lpId = $learnpath['lp_old_id']; |
||||
$sql = "SELECT 1 |
||||
FROM $tblProperty |
||||
WHERE tool = 'learnpath' |
||||
AND ref = $lpId AND visibility = 0 |
||||
AND (session_id = $sessionId OR session_id IS NULL)"; |
||||
$res = Database::query($sql); |
||||
if (Database::num_rows($res) > 0) { |
||||
continue; |
||||
} |
||||
$lpName = $learnpath['lp_name']; |
||||
$items[] = $lpName.'<br>'; |
||||
} |
||||
$items[] = '<br />'; |
||||
} |
||||
|
||||
if (count($items) > 0) { |
||||
$htmlText .= '<table width="100%" class="contents-learnpath">'; |
||||
$htmlText .= '<tr>'; |
||||
$htmlText .= '<td>'; |
||||
$i = 0; |
||||
foreach ($items as $value) { |
||||
if ($i == 50) { |
||||
$htmlText .= '</td><td>'; |
||||
} |
||||
$htmlText .= $value; |
||||
$i++; |
||||
} |
||||
$htmlText .= '</td>'; |
||||
$htmlText .= '</tr>'; |
||||
$htmlText .= '</table>'; |
||||
} |
||||
$htmlText .= '</td></table>'; |
||||
} |
||||
|
||||
if ($infoCertificate['contents_type'] == 2) { |
||||
$htmlText .= '<table width="100%" class="contents-learnpath">'; |
||||
$htmlText .= '<tr>'; |
||||
$htmlText .= '<td>'; |
||||
$myContentHtml = strip_tags( |
||||
$infoCertificate['contents'], |
||||
'<p><b><strong><table><tr><td><th><span><i><li><ol><ul>'. |
||||
'<dd><dt><dl><br><hr><img><a><div><h1><h2><h3><h4><h5><h6>' |
||||
); |
||||
$htmlText .= $myContentHtml; |
||||
$htmlText .= '</td>'; |
||||
$htmlText .= '</tr>'; |
||||
$htmlText .= '</table>'; |
||||
} |
||||
$htmlText .= '</div>'; |
||||
} |
||||
|
||||
if (!$exportAllInOne) { |
||||
$htmlText .= '</body></html>'; |
||||
} |
||||
$fileName = 'certificate_'.$userInfo['course_code'].'_'.$userInfo['complete_name'].'_'.$currentLocalTime; |
||||
$htmlList[$fileName] = $htmlText; |
||||
} |
||||
|
||||
$fileList = []; |
||||
$archivePath = api_get_path(SYS_ARCHIVE_PATH).'certificates/'; |
||||
if (!is_dir($archivePath)) { |
||||
mkdir($archivePath, api_get_permissions_for_new_directories()); |
||||
} |
||||
|
||||
if ($exportAllInOne) { |
||||
$params = [ |
||||
'pdf_title' => 'Certificate', |
||||
'pdf_description' => '', |
||||
'format' => 'A4-L', |
||||
'orientation' => 'L', |
||||
'left' => 15, |
||||
'top' => 15, |
||||
'bottom' => 0, |
||||
]; |
||||
$pdf = new PDF($params['format'], $params['orientation'], $params); |
||||
|
||||
$contentAllCertificate = ''; |
||||
foreach ($htmlList as $fileName => $content) { |
||||
$contentAllCertificate .= $content; |
||||
} |
||||
|
||||
if (!empty($contentAllCertificate)) { |
||||
$certificateContent = '<html>'; |
||||
$certificateContent .= ' |
||||
<link rel="stylesheet" |
||||
type="text/css" |
||||
href="'.api_get_path(WEB_PLUGIN_PATH).'customcertificate/resources/css/certificate.css">'; |
||||
$certificateContent .= ' |
||||
<link rel="stylesheet" |
||||
type="text/css" |
||||
href="'.api_get_path(WEB_CSS_PATH).'document.css">'; |
||||
$certificateContent .= '<body>'; |
||||
$certificateContent .= $contentAllCertificate; |
||||
$certificateContent .= '</body></html>'; |
||||
|
||||
$pdf->content_to_pdf( |
||||
$certificateContent, |
||||
'', |
||||
'certificate'.date('Y_m_d_His'), |
||||
null, |
||||
'D', |
||||
false, |
||||
null, |
||||
false, |
||||
false, |
||||
false |
||||
); |
||||
} |
||||
} else { |
||||
foreach ($htmlList as $fileName => $content) { |
||||
$fileName = api_replace_dangerous_char($fileName); |
||||
$params = [ |
||||
'filename' => $fileName, |
||||
'pdf_title' => 'Certificate', |
||||
'pdf_description' => '', |
||||
'format' => 'A4-L', |
||||
'orientation' => 'L', |
||||
'left' => 15, |
||||
'top' => 15, |
||||
'bottom' => 0, |
||||
]; |
||||
$pdf = new PDF($params['format'], $params['orientation'], $params); |
||||
if ($exportZip) { |
||||
$filePath = $archivePath.$fileName.'.pdf'; |
||||
$pdf->content_to_pdf($content, '', $fileName, null, 'F', true, $filePath, false, false, false); |
||||
$fileList[] = $filePath; |
||||
} else { |
||||
$pdf->content_to_pdf($content, '', $fileName, null, 'D', false, null, false, false, false); |
||||
} |
||||
} |
||||
|
||||
if (!empty($fileList)) { |
||||
$zipFile = $archivePath.'certificates_'.api_get_unique_id().'.zip'; |
||||
$zipFolder = new PclZip($zipFile); |
||||
foreach ($fileList as $file) { |
||||
$zipFolder->add($file, PCLZIP_OPT_REMOVE_ALL_PATH); |
||||
} |
||||
$name = 'certificates_'.$currentLocalTime.'.zip'; |
||||
DocumentManager::file_send_for_download($zipFile, true, $name); |
||||
exit; |
||||
} |
||||
} |
||||
|
||||
function getIndexFiltered($index) |
||||
{ |
||||
$txt = strip_tags($index, "<b><strong><i>"); |
||||
$txt = str_replace(chr(13).chr(10).chr(13).chr(10), chr(13).chr(10), $txt); |
||||
$lines = explode(chr(13).chr(10), $txt); |
||||
$text1 = ''; |
||||
for ($x = 0; $x < 47; $x++) { |
||||
if (isset($lines[$x])) { |
||||
$text1 .= $lines[$x].chr(13).chr(10); |
||||
} |
||||
} |
||||
|
||||
$text2 = ''; |
||||
for ($x = 47; $x < 94; $x++) { |
||||
if (isset($lines[$x])) { |
||||
$text2 .= $lines[$x].chr(13).chr(10); |
||||
} |
||||
} |
||||
|
||||
$showLeft = str_replace(chr(13).chr(10), "<br/>", $text1); |
||||
$showRight = str_replace(chr(13).chr(10), "<br/>", $text2); |
||||
$result = '<table width="100%">'; |
||||
$result .= '<tr>'; |
||||
$result .= '<td style="width:50%;vertical-align:top;padding-left:15px; font-size:12px;">'.$showLeft.'</td>'; |
||||
$result .= '<td style="vertical-align:top; font-size:12px;">'.$showRight.'</td>'; |
||||
$result .= '<tr>'; |
||||
$result .= '</table>'; |
||||
|
||||
return $result; |
||||
} |
||||
@ -1,11 +1,12 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
/** |
||||
* This script is included by main/admin/settings.lib.php when unselecting a plugin |
||||
* and is meant to remove things installed by the install.php script in both |
||||
* the global database and the courses tables. |
||||
* |
||||
* @package chamilo.plugin.customcertificate |
||||
*/ |
||||
require_once __DIR__.'/config.php'; |
||||
CustomCertificatePlugin::create()->uninstall(); |
||||
|
||||
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php'; |
||||
|
||||
PauseTraining::create()->runCronTest(); |
||||
@ -0,0 +1,608 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\CourseRelUser; |
||||
use Chamilo\CoreBundle\Entity\Session; |
||||
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser; |
||||
use Chamilo\CourseBundle\Entity\CGroupInfo; |
||||
use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet; |
||||
use Chamilo\PluginBundle\Zoom\API\MeetingListItem; |
||||
use Chamilo\PluginBundle\Zoom\API\MeetingSettings; |
||||
use Chamilo\UserBundle\Entity\User; |
||||
use Database; |
||||
use DateInterval; |
||||
use DateTime; |
||||
use DateTimeZone; |
||||
use Doctrine\Common\Collections\ArrayCollection; |
||||
use Doctrine\ORM\Mapping as ORM; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class Meeting. |
||||
* |
||||
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\MeetingRepository") |
||||
* @ORM\Table( |
||||
* name="plugin_zoom_meeting", |
||||
* indexes={ |
||||
* @ORM\Index(name="user_id_index", columns={"user_id"}), |
||||
* @ORM\Index(name="course_id_index", columns={"course_id"}), |
||||
* @ORM\Index(name="session_id_index", columns={"session_id"}) |
||||
* } |
||||
* ) |
||||
* @ORM\HasLifecycleCallbacks |
||||
*/ |
||||
class Meeting |
||||
{ |
||||
/** @var string meeting type name */ |
||||
public $typeName; |
||||
|
||||
/** @var DateTime meeting start time as a DateTime instance */ |
||||
public $startDateTime; |
||||
|
||||
/** @var string meeting formatted start time */ |
||||
public $formattedStartTime; |
||||
|
||||
/** @var DateInterval meeting duration as a DateInterval instance */ |
||||
public $durationInterval; |
||||
|
||||
/** @var string meeting formatted duration */ |
||||
public $formattedDuration; |
||||
|
||||
/** @var string */ |
||||
public $statusName; |
||||
|
||||
/** |
||||
* @var int |
||||
* @ORM\Column(type="integer") |
||||
* @ORM\Id |
||||
* @ORM\GeneratedValue() |
||||
*/ |
||||
protected $id; |
||||
|
||||
/** |
||||
* @var int the remote zoom meeting identifier |
||||
* @ORM\Column(name="meeting_id", type="string") |
||||
*/ |
||||
protected $meetingId; |
||||
|
||||
/** |
||||
* @var User |
||||
* @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User") |
||||
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true) |
||||
*/ |
||||
protected $user; |
||||
|
||||
/** |
||||
* @var Course |
||||
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course") |
||||
* @ORM\JoinColumn(name="course_id", referencedColumnName="id", nullable=true) |
||||
*/ |
||||
protected $course; |
||||
|
||||
/** |
||||
* @var CGroupInfo |
||||
* @ORM\ManyToOne(targetEntity="Chamilo\CourseBundle\Entity\CGroupInfo") |
||||
* @ORM\JoinColumn(name="group_id", referencedColumnName="iid", nullable=true) |
||||
*/ |
||||
protected $group; |
||||
|
||||
/** |
||||
* @var Session |
||||
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Session") |
||||
* @ORM\JoinColumn(name="session_id", referencedColumnName="id", nullable=true) |
||||
*/ |
||||
protected $session; |
||||
|
||||
/** |
||||
* @var string |
||||
* @ORM\Column(type="text", name="meeting_list_item_json", nullable=true) |
||||
*/ |
||||
protected $meetingListItemJson; |
||||
|
||||
/** |
||||
* @var string |
||||
* @ORM\Column(type="text", name="meeting_info_get_json", nullable=true) |
||||
*/ |
||||
protected $meetingInfoGetJson; |
||||
|
||||
/** @var MeetingListItem */ |
||||
protected $meetingListItem; |
||||
|
||||
/** @var MeetingInfoGet */ |
||||
protected $meetingInfoGet; |
||||
|
||||
/** |
||||
* @var MeetingActivity[]|ArrayCollection |
||||
* @ORM\OrderBy({"createdAt" = "DESC"}) |
||||
* @ORM\OneToMany(targetEntity="MeetingActivity", mappedBy="meeting", cascade={"persist", "remove"}) |
||||
*/ |
||||
protected $activities; |
||||
|
||||
/** |
||||
* @var Registrant[]|ArrayCollection |
||||
* |
||||
* @ORM\OneToMany(targetEntity="Registrant", mappedBy="meeting", cascade={"persist", "remove"}) |
||||
*/ |
||||
protected $registrants; |
||||
|
||||
/** |
||||
* @var Recording[]|ArrayCollection |
||||
* |
||||
* @ORM\OneToMany(targetEntity="Recording", mappedBy="meeting", cascade={"persist"}, orphanRemoval=true) |
||||
*/ |
||||
protected $recordings; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->registrants = new ArrayCollection(); |
||||
$this->recordings = new ArrayCollection(); |
||||
$this->activities = new ArrayCollection(); |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return sprintf('Meeting %d', $this->id); |
||||
} |
||||
|
||||
/** |
||||
* @return int |
||||
*/ |
||||
public function getId() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
/** |
||||
* @return int |
||||
*/ |
||||
public function getMeetingId() |
||||
{ |
||||
return $this->meetingId; |
||||
} |
||||
|
||||
/** |
||||
* @param int $meetingId |
||||
* |
||||
* @return Meeting |
||||
*/ |
||||
public function setMeetingId($meetingId) |
||||
{ |
||||
$this->meetingId = $meetingId; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return User |
||||
*/ |
||||
public function getUser() |
||||
{ |
||||
return $this->user; |
||||
} |
||||
|
||||
/** |
||||
* @return Course |
||||
*/ |
||||
public function getCourse() |
||||
{ |
||||
return $this->course; |
||||
} |
||||
|
||||
/** |
||||
* @return Session |
||||
*/ |
||||
public function getSession() |
||||
{ |
||||
return $this->session; |
||||
} |
||||
|
||||
/** |
||||
* @return Registrant[]|ArrayCollection |
||||
*/ |
||||
public function getRegistrants() |
||||
{ |
||||
return $this->registrants; |
||||
} |
||||
|
||||
/** |
||||
* @return Recording[]|ArrayCollection |
||||
*/ |
||||
public function getRecordings() |
||||
{ |
||||
return $this->recordings; |
||||
} |
||||
|
||||
/** |
||||
* @return MeetingActivity[]|ArrayCollection |
||||
*/ |
||||
public function getActivities() |
||||
{ |
||||
return $this->activities; |
||||
} |
||||
|
||||
public function addActivity(MeetingActivity $activity) |
||||
{ |
||||
$activity->setMeeting($this); |
||||
$this->activities[] = $activity; |
||||
} |
||||
|
||||
/** |
||||
* @param MeetingActivity[]|ArrayCollection $activities |
||||
* |
||||
* @return Meeting |
||||
*/ |
||||
public function setActivities($activities) |
||||
{ |
||||
$this->activities = $activities; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PostLoad |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function postLoad() |
||||
{ |
||||
if (null !== $this->meetingListItemJson) { |
||||
$this->meetingListItem = MeetingListItem::fromJson($this->meetingListItemJson); |
||||
} |
||||
if (null !== $this->meetingInfoGetJson) { |
||||
$this->meetingInfoGet = MeetingInfoGet::fromJson($this->meetingInfoGetJson); |
||||
} |
||||
$this->initializeDisplayableProperties(); |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PostUpdate |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function postUpdate() |
||||
{ |
||||
$this->initializeDisplayableProperties(); |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PreFlush |
||||
*/ |
||||
public function preFlush() |
||||
{ |
||||
if (null !== $this->meetingListItem) { |
||||
$this->meetingListItemJson = json_encode($this->meetingListItem); |
||||
} |
||||
if (null !== $this->meetingInfoGet) { |
||||
$this->meetingInfoGetJson = json_encode($this->meetingInfoGet); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @return MeetingListItem |
||||
*/ |
||||
public function getMeetingListItem() |
||||
{ |
||||
return $this->meetingListItem; |
||||
} |
||||
|
||||
/** |
||||
* @return MeetingInfoGet |
||||
*/ |
||||
public function getMeetingInfoGet() |
||||
{ |
||||
return $this->meetingInfoGet; |
||||
} |
||||
|
||||
/** |
||||
* @param User $user |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setUser($user) |
||||
{ |
||||
$this->user = $user; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param Course $course |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setCourse($course) |
||||
{ |
||||
$this->course = $course; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param Session $session |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setSession($session) |
||||
{ |
||||
$this->session = $session; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return CGroupInfo |
||||
*/ |
||||
public function getGroup() |
||||
{ |
||||
return $this->group; |
||||
} |
||||
|
||||
/** |
||||
* @param CGroupInfo $group |
||||
* |
||||
* @return Meeting |
||||
*/ |
||||
public function setGroup($group) |
||||
{ |
||||
$this->group = $group; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param MeetingListItem $meetingListItem |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return Meeting |
||||
*/ |
||||
public function setMeetingListItem($meetingListItem) |
||||
{ |
||||
if (null === $this->meetingId) { |
||||
$this->meetingId = $meetingListItem->id; |
||||
} elseif ($this->meetingId != $meetingListItem->id) { |
||||
throw new Exception('the Meeting identifier differs from the MeetingListItem identifier'); |
||||
} |
||||
$this->meetingListItem = $meetingListItem; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param MeetingInfoGet $meetingInfoGet |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return Meeting |
||||
*/ |
||||
public function setMeetingInfoGet($meetingInfoGet) |
||||
{ |
||||
if (null === $this->meetingId) { |
||||
$this->meetingId = $meetingInfoGet->id; |
||||
} elseif ($this->meetingId != $meetingInfoGet->id) { |
||||
throw new Exception('the Meeting identifier differs from the MeetingInfoGet identifier'); |
||||
} |
||||
$this->meetingInfoGet = $meetingInfoGet; |
||||
$this->initializeDisplayableProperties(); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isCourseMeeting() |
||||
{ |
||||
return null !== $this->course; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isCourseGroupMeeting() |
||||
{ |
||||
return null !== $this->course && null !== $this->group; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isUserMeeting() |
||||
{ |
||||
return null !== $this->user && null === $this->course; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isGlobalMeeting() |
||||
{ |
||||
return null === $this->user && null === $this->course; |
||||
} |
||||
|
||||
public function setStatus($status) |
||||
{ |
||||
$this->meetingInfoGet->status = $status; |
||||
} |
||||
|
||||
/** |
||||
* Builds the list of users that can register into this meeting. |
||||
* Zoom requires an email address, therefore users without an email address are excluded from the list. |
||||
* |
||||
* @return User[] the list of users |
||||
*/ |
||||
public function getRegistrableUsers() |
||||
{ |
||||
$users = []; |
||||
if (!$this->isCourseMeeting()) { |
||||
$criteria = ['active' => true]; |
||||
$users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy($criteria); |
||||
} elseif (null === $this->session) { |
||||
if (null !== $this->course) { |
||||
/** @var CourseRelUser $courseRelUser */ |
||||
foreach ($this->course->getUsers() as $courseRelUser) { |
||||
$users[] = $courseRelUser->getUser(); |
||||
} |
||||
} |
||||
} else { |
||||
if (null !== $this->course) { |
||||
$subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT); |
||||
if ($subscriptions) { |
||||
/** @var SessionRelCourseRelUser $sessionCourseUser */ |
||||
foreach ($subscriptions as $sessionCourseUser) { |
||||
$users[] = $sessionCourseUser->getUser(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
$activeUsersWithEmail = []; |
||||
foreach ($users as $user) { |
||||
if ($user->isActive() && !empty($user->getEmail())) { |
||||
$activeUsersWithEmail[] = $user; |
||||
} |
||||
} |
||||
|
||||
return $activeUsersWithEmail; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function requiresDateAndDuration() |
||||
{ |
||||
return MeetingInfoGet::TYPE_SCHEDULED === $this->meetingInfoGet->type |
||||
|| MeetingInfoGet::TYPE_RECURRING_WITH_FIXED_TIME === $this->meetingInfoGet->type; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function requiresRegistration() |
||||
{ |
||||
return |
||||
MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE === $this->meetingInfoGet->settings->approval_type; |
||||
/*return |
||||
MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $this->meetingInfoGet->settings->approval_type;*/ |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function hasCloudAutoRecordingEnabled() |
||||
{ |
||||
return \ZoomPlugin::RECORDING_TYPE_NONE !== $this->meetingInfoGet->settings->auto_recording; |
||||
} |
||||
|
||||
/** |
||||
* @param User $user |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function hasRegisteredUser($user) |
||||
{ |
||||
return $this->getRegistrants()->exists( |
||||
function (Registrant $registrantEntity) use (&$user) { |
||||
return $registrantEntity->getUser() === $user; |
||||
} |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @param User $user |
||||
* |
||||
* @return Registrant|null |
||||
*/ |
||||
public function getRegistrant($user) |
||||
{ |
||||
foreach ($this->getRegistrants() as $registrant) { |
||||
if ($registrant->getUser() === $user) { |
||||
return $registrant; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Generates a short presentation of the meeting for the future participant. |
||||
* To be displayed above the "Enter meeting" link. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function getIntroduction() |
||||
{ |
||||
$introduction = sprintf('<h1>%s</h1>', $this->meetingInfoGet->topic); |
||||
if (!$this->isGlobalMeeting()) { |
||||
if (!empty($this->formattedStartTime)) { |
||||
$introduction .= $this->formattedStartTime; |
||||
if (!empty($this->formattedDuration)) { |
||||
$introduction .= ' ('.$this->formattedDuration.')'; |
||||
} |
||||
} |
||||
} |
||||
if ($this->user) { |
||||
$introduction .= sprintf('<p>%s</p>', $this->user->getFullname()); |
||||
} elseif ($this->isCourseMeeting()) { |
||||
if (null === $this->session) { |
||||
$introduction .= sprintf('<p class="main">%s</p>', $this->course); |
||||
} else { |
||||
$introduction .= sprintf('<p class="main">%s (%s)</p>', $this->course, $this->session); |
||||
} |
||||
} |
||||
if (!empty($this->meetingInfoGet->agenda)) { |
||||
$introduction .= sprintf('<p>%s</p>', $this->meetingInfoGet->agenda); |
||||
} |
||||
|
||||
return $introduction; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception on unexpected start_time or duration |
||||
*/ |
||||
private function initializeDisplayableProperties() |
||||
{ |
||||
$zoomPlugin = new \ZoomPlugin(); |
||||
|
||||
$typeList = [ |
||||
API\Meeting::TYPE_INSTANT => $zoomPlugin->get_lang('InstantMeeting'), |
||||
API\Meeting::TYPE_SCHEDULED => $zoomPlugin->get_lang('ScheduledMeeting'), |
||||
API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithNoFixedTime'), |
||||
API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithFixedTime'), |
||||
]; |
||||
$this->typeName = $typeList[$this->meetingInfoGet->type]; |
||||
|
||||
if (property_exists($this, 'status')) { |
||||
$statusList = [ |
||||
'waiting' => $zoomPlugin->get_lang('Waiting'), |
||||
'started' => $zoomPlugin->get_lang('Started'), |
||||
'finished' => $zoomPlugin->get_lang('Finished'), |
||||
]; |
||||
$this->statusName = $statusList[$this->meetingInfoGet->status]; |
||||
} |
||||
$this->startDateTime = null; |
||||
$this->formattedStartTime = ''; |
||||
$this->durationInterval = null; |
||||
$this->formattedDuration = ''; |
||||
if (!empty($this->meetingInfoGet->start_time)) { |
||||
$this->startDateTime = new DateTime($this->meetingInfoGet->start_time); |
||||
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); |
||||
$this->formattedStartTime = $this->startDateTime->format('Y-m-d H:i'); |
||||
} |
||||
|
||||
if (!empty($this->meetingInfoGet->duration)) { |
||||
$now = new DateTime(); |
||||
$later = new DateTime(); |
||||
$later->add(new DateInterval('PT'.$this->meetingInfoGet->duration.'M')); |
||||
$this->durationInterval = $later->diff($now); |
||||
$this->formattedDuration = $this->durationInterval->format($zoomPlugin->get_lang('DurationFormat')); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,208 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use DateTime; |
||||
use Doctrine\ORM\Mapping as ORM; |
||||
|
||||
/** |
||||
* Class Meeting. |
||||
* |
||||
* @ORM\Entity() |
||||
* @ORM\Table(name="plugin_zoom_meeting_activity") |
||||
* @ORM\HasLifecycleCallbacks |
||||
*/ |
||||
class MeetingActivity |
||||
{ |
||||
/** |
||||
* @var int |
||||
* @ORM\Column(type="integer") |
||||
* @ORM\Id |
||||
* @ORM\GeneratedValue() |
||||
*/ |
||||
protected $id; |
||||
|
||||
/** |
||||
* @var Meeting |
||||
* |
||||
* @ORM\ManyToOne(targetEntity="Meeting", inversedBy="activities") |
||||
* @ORM\JoinColumn(name="meeting_id") |
||||
*/ |
||||
protected $meeting; |
||||
|
||||
/** |
||||
* @var Meeting |
||||
* |
||||
* @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User") |
||||
* @ORM\JoinColumn(name="user_id", referencedColumnName="id") |
||||
*/ |
||||
protected $user; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="string", name="name", length=255, nullable=false) |
||||
*/ |
||||
protected $name; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="string", name="type", length=255, nullable=false) |
||||
*/ |
||||
protected $type; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="text", name="event", nullable=true) |
||||
*/ |
||||
protected $event; |
||||
|
||||
/** |
||||
* @var \DateTime |
||||
* |
||||
* @ORM\Column(name="created_at", type="datetime", nullable=false) |
||||
*/ |
||||
protected $createdAt; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->createdAt = new \DateTime(); |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return sprintf('Activity %d', $this->id); |
||||
} |
||||
|
||||
/** |
||||
* @return int |
||||
*/ |
||||
public function getId() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
/** |
||||
* @return Meeting |
||||
*/ |
||||
public function getMeeting() |
||||
{ |
||||
return $this->meeting; |
||||
} |
||||
|
||||
/** |
||||
* @param Meeting $meeting |
||||
* |
||||
* @return MeetingActivity |
||||
*/ |
||||
public function setMeeting($meeting) |
||||
{ |
||||
$this->meeting = $meeting; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
/** |
||||
* @param string $name |
||||
* |
||||
* @return MeetingActivity |
||||
*/ |
||||
public function setName($name) |
||||
{ |
||||
$this->name = $name; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getType() |
||||
{ |
||||
return $this->type; |
||||
} |
||||
|
||||
/** |
||||
* @param string $type |
||||
* |
||||
* @return MeetingActivity |
||||
*/ |
||||
public function setType($type) |
||||
{ |
||||
$this->type = $type; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return DateTime |
||||
*/ |
||||
public function getCreatedAt() |
||||
{ |
||||
return $this->createdAt; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getEvent() |
||||
{ |
||||
return $this->event; |
||||
} |
||||
|
||||
/** |
||||
* @return Meeting |
||||
*/ |
||||
public function getUser() |
||||
{ |
||||
return $this->user; |
||||
} |
||||
|
||||
/** |
||||
* @param Meeting $user |
||||
* |
||||
* @return MeetingActivity |
||||
*/ |
||||
public function setUser($user) |
||||
{ |
||||
$this->user = $user; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getEventDecoded() |
||||
{ |
||||
if (!empty($this->event)) { |
||||
return json_decode($this->event); |
||||
} |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* @param string $event |
||||
* |
||||
* @return MeetingActivity |
||||
*/ |
||||
public function setEvent($event) |
||||
{ |
||||
$this->event = $event; |
||||
|
||||
return $this; |
||||
} |
||||
} |
||||
@ -0,0 +1,193 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\PluginBundle\Zoom\API\RecordingMeeting; |
||||
use Database; |
||||
use DateInterval; |
||||
use DateTime; |
||||
use DateTimeZone; |
||||
use Doctrine\ORM\Mapping as ORM; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class RecordingEntity. |
||||
* |
||||
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\RecordingRepository") |
||||
* @ORM\Table( |
||||
* name="plugin_zoom_recording", |
||||
* indexes={ |
||||
* @ORM\Index(name="meeting_id_index", columns={"meeting_id"}), |
||||
* } |
||||
* ) |
||||
* @ORM\HasLifecycleCallbacks |
||||
*/ |
||||
class Recording |
||||
{ |
||||
/** @var DateTime */ |
||||
public $startDateTime; |
||||
|
||||
/** @var string */ |
||||
public $formattedStartTime; |
||||
|
||||
/** @var DateInterval */ |
||||
public $durationInterval; |
||||
|
||||
/** @var string */ |
||||
public $formattedDuration; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="integer") |
||||
* @ORM\Id |
||||
* @ORM\GeneratedValue() |
||||
*/ |
||||
protected $id; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="string") |
||||
*/ |
||||
protected $uuid; |
||||
|
||||
/** |
||||
* @var Meeting |
||||
* |
||||
* @ORM\ManyToOne(targetEntity="Meeting", inversedBy="recordings") |
||||
* @ORM\JoinColumn(name="meeting_id") |
||||
*/ |
||||
protected $meeting; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="text", name="recording_meeting_json", nullable=true) |
||||
*/ |
||||
protected $recordingMeetingJson; |
||||
|
||||
/** @var RecordingMeeting */ |
||||
protected $recordingMeeting; |
||||
|
||||
/** |
||||
* @param $name |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return mixed |
||||
*/ |
||||
public function __get($name) |
||||
{ |
||||
$object = $this->getRecordingMeeting(); |
||||
if (property_exists($object, $name)) { |
||||
return $object->$name; |
||||
} |
||||
throw new Exception(sprintf('%s does not know property %s', $this, $name)); |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return sprintf('Recording %d', $this->uuid); |
||||
} |
||||
|
||||
/** |
||||
* @return Meeting |
||||
*/ |
||||
public function getMeeting() |
||||
{ |
||||
return $this->meeting; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return RecordingMeeting |
||||
*/ |
||||
public function getRecordingMeeting() |
||||
{ |
||||
return $this->recordingMeeting; |
||||
} |
||||
|
||||
/** |
||||
* @param Meeting $meeting |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setMeeting($meeting) |
||||
{ |
||||
$this->meeting = $meeting; |
||||
$this->meeting->getRecordings()->add($this); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param RecordingMeeting $recordingMeeting |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return Recording |
||||
*/ |
||||
public function setRecordingMeeting($recordingMeeting) |
||||
{ |
||||
if (null === $this->uuid) { |
||||
$this->uuid = $recordingMeeting->uuid; |
||||
} elseif ($this->uuid !== $recordingMeeting->uuid) { |
||||
throw new Exception('the RecordingEntity identifier differs from the RecordingMeeting identifier'); |
||||
} |
||||
if (null === $this->meeting) { |
||||
$this->meeting = Database::getManager()->getRepository(Meeting::class)->find($recordingMeeting->id); |
||||
} elseif ($this->meeting->getMeetingId() != $recordingMeeting->id) { |
||||
// $this->meeting remains null when the remote RecordingMeeting refers to a deleted meeting. |
||||
throw new Exception('The RecordingEntity meeting id differs from the RecordingMeeting meeting id'); |
||||
} |
||||
$this->recordingMeeting = $recordingMeeting; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PostLoad |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function postLoad() |
||||
{ |
||||
if (null !== $this->recordingMeetingJson) { |
||||
$this->recordingMeeting = RecordingMeeting::fromJson($this->recordingMeetingJson); |
||||
} |
||||
$this->initializeExtraProperties(); |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PreFlush |
||||
*/ |
||||
public function preFlush() |
||||
{ |
||||
if (null !== $this->recordingMeeting) { |
||||
$this->recordingMeetingJson = json_encode($this->recordingMeeting); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
$this->startDateTime = new DateTime($this->recordingMeeting->start_time); |
||||
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); |
||||
$this->formattedStartTime = $this->startDateTime->format('Y-m-d H:i'); |
||||
|
||||
$now = new DateTime(); |
||||
$later = new DateTime(); |
||||
$later->add(new DateInterval('PT'.$this->recordingMeeting->duration.'M')); |
||||
$this->durationInterval = $later->diff($now); |
||||
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat')); |
||||
} |
||||
} |
||||
@ -0,0 +1,265 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\PluginBundle\Zoom\API\CreatedRegistration; |
||||
use Chamilo\PluginBundle\Zoom\API\MeetingRegistrant; |
||||
use Chamilo\PluginBundle\Zoom\API\MeetingRegistrantListItem; |
||||
use Chamilo\UserBundle\Entity\User; |
||||
use Doctrine\ORM\Mapping as ORM; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class RegistrantEntity. |
||||
* |
||||
* @ORM\Entity(repositoryClass="RegistrantRepository") |
||||
* @ORM\Table( |
||||
* name="plugin_zoom_registrant", |
||||
* indexes={ |
||||
* @ORM\Index(name="user_id_index", columns={"user_id"}), |
||||
* @ORM\Index(name="meeting_id_index", columns={"meeting_id"}), |
||||
* } |
||||
* ) |
||||
* @ORM\HasLifecycleCallbacks |
||||
*/ |
||||
class Registrant |
||||
{ |
||||
/** @var string */ |
||||
public $fullName; |
||||
|
||||
/** |
||||
* @var string |
||||
* @ORM\Column(type="integer") |
||||
* @ORM\Id |
||||
* @ORM\GeneratedValue(strategy="AUTO") |
||||
*/ |
||||
protected $id; |
||||
|
||||
/** |
||||
* @var User |
||||
* @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User") |
||||
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false) |
||||
*/ |
||||
protected $user; |
||||
|
||||
/** |
||||
* @var Meeting |
||||
* @ORM\ManyToOne(targetEntity="Meeting", inversedBy="registrants") |
||||
* @ORM\JoinColumn(name="meeting_id", referencedColumnName="id") |
||||
*/ |
||||
protected $meeting; |
||||
|
||||
/** |
||||
* @var string |
||||
* @ORM\Column(type="text", name="created_registration_json", nullable=true) |
||||
*/ |
||||
protected $createdRegistrationJson; |
||||
|
||||
/** |
||||
* @var string |
||||
* @ORM\Column(type="text", name="meeting_registrant_list_item_json", nullable=true) |
||||
*/ |
||||
protected $meetingRegistrantListItemJson; |
||||
|
||||
/** |
||||
* @var string |
||||
* @ORM\Column(type="text", name="meeting_registrant_json", nullable=true) |
||||
*/ |
||||
protected $meetingRegistrantJson; |
||||
|
||||
/** @var CreatedRegistration */ |
||||
protected $createdRegistration; |
||||
|
||||
/** @var MeetingRegistrant */ |
||||
protected $meetingRegistrant; |
||||
|
||||
/** @var MeetingRegistrantListItem */ |
||||
protected $meetingRegistrantListItem; |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return sprintf('Registrant %d', $this->id); |
||||
} |
||||
|
||||
/** |
||||
* @return Meeting |
||||
*/ |
||||
public function getMeeting() |
||||
{ |
||||
return $this->meeting; |
||||
} |
||||
|
||||
/** |
||||
* @param Meeting $meeting |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setMeeting($meeting) |
||||
{ |
||||
$this->meeting = $meeting; |
||||
$this->meeting->getRegistrants()->add($this); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return User |
||||
*/ |
||||
public function getUser() |
||||
{ |
||||
return $this->user; |
||||
} |
||||
|
||||
/** |
||||
* @param User $user |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setUser($user) |
||||
{ |
||||
$this->user = $user; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrantListItem |
||||
*/ |
||||
public function getMeetingRegistrantListItem() |
||||
{ |
||||
return $this->meetingRegistrantListItem; |
||||
} |
||||
|
||||
/** |
||||
* @param MeetingRegistrantListItem $meetingRegistrantListItem |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setMeetingRegistrantListItem($meetingRegistrantListItem) |
||||
{ |
||||
if (!is_null($this->meeting) && $this->meeting->getId() != $meetingRegistrantListItem->id) { |
||||
throw new Exception('RegistrantEntity meeting id differs from MeetingRegistrantListItem id'); |
||||
} |
||||
$this->meetingRegistrantListItem = $meetingRegistrantListItem; |
||||
$this->computeFullName(); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function computeFullName() |
||||
{ |
||||
$this->fullName = api_get_person_name( |
||||
$this->meetingRegistrant->first_name, |
||||
$this->meetingRegistrant->last_name |
||||
); |
||||
} |
||||
|
||||
public function getJoinUrl() |
||||
{ |
||||
if (!$this->createdRegistration) { |
||||
return ''; |
||||
} |
||||
|
||||
return $this->createdRegistration->join_url; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return CreatedRegistration |
||||
*/ |
||||
public function getCreatedRegistration() |
||||
{ |
||||
return $this->createdRegistration; |
||||
} |
||||
|
||||
/** |
||||
* @param CreatedRegistration $createdRegistration |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setCreatedRegistration($createdRegistration) |
||||
{ |
||||
if (null === $this->id) { |
||||
$this->id = $createdRegistration->registrant_id; |
||||
} elseif ($this->id != $createdRegistration->registrant_id) { |
||||
throw new Exception('RegistrantEntity id differs from CreatedRegistration identifier'); |
||||
} |
||||
$this->createdRegistration = $createdRegistration; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrant |
||||
*/ |
||||
public function getMeetingRegistrant() |
||||
{ |
||||
return $this->meetingRegistrant; |
||||
} |
||||
|
||||
/** |
||||
* @param MeetingRegistrant $meetingRegistrant |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setMeetingRegistrant($meetingRegistrant) |
||||
{ |
||||
$this->meetingRegistrant = $meetingRegistrant; |
||||
$this->computeFullName(); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PostLoad |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function postLoad() |
||||
{ |
||||
if (null !== $this->meetingRegistrantJson) { |
||||
$this->meetingRegistrant = MeetingRegistrant::fromJson($this->meetingRegistrantJson); |
||||
} |
||||
if (null !== $this->createdRegistrationJson) { |
||||
$this->createdRegistration = CreatedRegistration::fromJson($this->createdRegistrationJson); |
||||
} |
||||
if (null !== $this->meetingRegistrantListItemJson) { |
||||
$this->meetingRegistrantListItem = MeetingRegistrantListItem::fromJson( |
||||
$this->meetingRegistrantListItemJson |
||||
); |
||||
} |
||||
$this->computeFullName(); |
||||
} |
||||
|
||||
/** |
||||
* @ORM\PreFlush |
||||
*/ |
||||
public function preFlush() |
||||
{ |
||||
if (null !== $this->meetingRegistrant) { |
||||
$this->meetingRegistrantJson = json_encode($this->meetingRegistrant); |
||||
} |
||||
if (null !== $this->createdRegistration) { |
||||
$this->createdRegistrationJson = json_encode($this->createdRegistration); |
||||
} |
||||
if (null !== $this->meetingRegistrantListItem) { |
||||
$this->meetingRegistrantListItemJson = json_encode($this->meetingRegistrantListItem); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@ |
||||
The Chamilo Zoom plugin class itself is defined in _plugin/zoom/lib/ZoomPlugin.php_ |
||||
|
||||
It manipulates both **remote Zoom server objects** and **local database entities**: |
||||
|
||||
# Local database entities |
||||
|
||||
The local entities map the remote objects to Chamilo courses/sessions and users. |
||||
|
||||
They also maintain a cache of the matching remote objects. |
||||
|
||||
_Entity/*Entity.php_ are the local database entity classes. |
||||
|
||||
Doctrine entity manager repository classes are in _lib/*EntityRepository.php_. |
||||
|
||||
# Remote Zoom server objets |
||||
|
||||
_lib/API/*.php_ contains the Zoom API data structure definition classes, |
||||
based on Zoom's own API specification: |
||||
|
||||
* https://marketplace.zoom.us/docs/api-reference/zoom-api |
||||
* https://marketplace.zoom.us/docs/api-reference/zoom-api/Zoom%20API.oas2.json |
||||
|
||||
These classes provide methods to list, create, update and delete the remote objects. |
||||
|
||||
# JWT Client |
||||
|
||||
API class methods use a JWT client implemented in _lib/API/JWTClient.php_. |
||||
|
||||
The plugin constructor initializes the JWT Client, giving it required API key and secret. |
||||
|
||||
# Event notification handler |
||||
|
||||
_endpoint.php_ is the Zoom API event notification web hook end point. |
||||
|
||||
It handles notifications sent by Zoom servers on useful events : |
||||
|
||||
* meeting start and end, |
||||
* registrant join and leave, |
||||
* recordings created and deleted |
||||
|
||||
# Administrative interface |
||||
|
||||
_admin.php_ is the administrative interface. |
||||
It lists all meetings and recordings. |
||||
|
||||
# Course tool |
||||
|
||||
_start.php_ is the **course** tool target: |
||||
|
||||
* to the course teacher, it shows a course meeting management interface; |
||||
* to the course learners, it shows the list of scheduled course meetings. |
||||
|
||||
# Home page's profile block (also on "My Courses" page) |
||||
|
||||
This plugin can add 3 kinds of links to "profile block" : |
||||
|
||||
1. _join_meeting.php?meetingId=…_ links to upcoming meetings accessible to the current user. |
||||
_join_meeting.php_ presents the meeting and shows a link to enter the meeting. |
||||
2. _user.php_ is the **user**'s own meeting management interface. |
||||
3. _global.php_ directs the user to _join_meeting.php_ with the **global** meeting. |
||||
|
||||
# Meeting management page |
||||
|
||||
_admin.php_, _start.php_ and _user.php_ link to _meeting.php_. |
||||
|
||||
_meeting.php_ is the meeting management page, where one can manage |
||||
|
||||
* the meeting properties, |
||||
* the list of its registrants and |
||||
* its recordings. |
||||
@ -0,0 +1,37 @@ |
||||
This plugin adds Zoom meetings, user registration to meetings and meeting recordings. |
||||
|
||||
## Meetings |
||||
|
||||
A **meeting** can be linked to a local **user** and/or a local **course**/**session**: |
||||
|
||||
* a meeting with a course is a _course meeting_; |
||||
* a meeting with a user and no course is a _user meeting_; |
||||
* a meeting with no course nor user is a _global meeting_. |
||||
|
||||
## Registrants |
||||
|
||||
A **registrant** is the registration of a local user to a meeting. |
||||
|
||||
Users do not register themselves to meetings. |
||||
|
||||
* They are registered to a course meeting by the course manager. |
||||
* They are registered to a user meeting by that user. |
||||
* They are registered automatically to the global meeting, when they enter it. |
||||
|
||||
## Recordings |
||||
|
||||
A **recording** is the list of files created during a past meeting instance. |
||||
|
||||
Course meeting files can be copied to the course by the course manager. |
||||
|
||||
# Required Zoom user account |
||||
|
||||
Recordings and user registration are only available to paying Zoom customers. |
||||
|
||||
For a non-paying Zoom user, this plugin still works but participants will join anonymously. |
||||
|
||||
The user that starts the meeting will be identified as the zoom account that is define in the plugin. Socreate a generic account that works for all the users that start meetings. |
||||
|
||||
# Contributing |
||||
|
||||
Read README.code.md for an introduction to the plugin's code. |
||||
@ -0,0 +1,55 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\Meeting; |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
$tool_name = $plugin->get_lang('ZoomVideoConferences'); |
||||
$meetingId = isset($_REQUEST['meetingId']) ? (int) $_REQUEST['meetingId'] : 0; |
||||
if (empty($meetingId)) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$content = ''; |
||||
/** @var Meeting $meeting */ |
||||
$meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $meetingId]); |
||||
if (null === $meeting) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
if (!$plugin->userIsConferenceManager($meeting)) { |
||||
api_not_allowed(true); |
||||
} |
||||
$returnURL = 'meetings.php'; |
||||
$urlExtra = ''; |
||||
if ($meeting->isCourseMeeting()) { |
||||
api_protect_course_script(true); |
||||
$urlExtra = api_get_cidreq(); |
||||
$returnURL = 'start.php?'.$urlExtra; |
||||
if (api_is_in_group()) { |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(), |
||||
'name' => get_lang('Groups'), |
||||
]; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(), |
||||
'name' => get_lang('GroupSpace').' '.$meeting->getGroup()->getName(), |
||||
]; |
||||
} |
||||
} |
||||
|
||||
$interbreadcrumb[] = [ |
||||
'url' => $returnURL, |
||||
'name' => $plugin->get_lang('ZoomVideoConferences'), |
||||
]; |
||||
$tpl = new Template($meeting->getMeetingId()); |
||||
$tpl->assign('actions', $plugin->getToolbar()); |
||||
$tpl->assign('meeting', $meeting); |
||||
$tpl->assign('url_extra', $urlExtra); |
||||
$tpl->assign('content', $tpl->fetch('zoom/view/activity.tpl')); |
||||
$tpl->display_one_col_template(); |
||||
@ -0,0 +1,5 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php'; |
||||
@ -0,0 +1,151 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\API\RecordingMeeting; |
||||
use Chamilo\PluginBundle\Zoom\Meeting; |
||||
use Chamilo\PluginBundle\Zoom\MeetingActivity; |
||||
use Chamilo\PluginBundle\Zoom\Recording; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
|
||||
if ('POST' !== $_SERVER['REQUEST_METHOD']) { |
||||
http_response_code(Response::HTTP_NOT_FOUND); // Not found |
||||
exit; |
||||
} |
||||
|
||||
// @todo handle non-apache installations |
||||
$authorizationHeaderValue = apache_request_headers()['Authorization']; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
if (api_get_plugin_setting('zoom', 'verificationToken') !== $authorizationHeaderValue) { |
||||
http_response_code(Response::HTTP_UNAUTHORIZED); |
||||
exit; |
||||
} |
||||
|
||||
$body = file_get_contents('php://input'); |
||||
$decoded = json_decode($body); |
||||
if (is_null($decoded) || !is_object($decoded) || !isset($decoded->event) || !isset($decoded->payload->object)) { |
||||
error_log(sprintf('Did not recognize event notification: %s', $body)); |
||||
http_response_code(Response::HTTP_UNPROCESSABLE_ENTITY); |
||||
exit; |
||||
} |
||||
|
||||
$object = $decoded->payload->object; |
||||
list($objectType, $action) = explode('.', $decoded->event); |
||||
|
||||
$em = Database::getManager(); |
||||
|
||||
$meetingRepository = $em->getRepository(Meeting::class); |
||||
$meeting = null; |
||||
if ($object->id) { |
||||
/** @var Meeting $meeting */ |
||||
$meeting = $meetingRepository->findOneBy(['meetingId' => $object->id]); |
||||
} |
||||
|
||||
if (null === $meeting) { |
||||
error_log("Meeting not found"); |
||||
error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); |
||||
http_response_code(Response::HTTP_NOT_FOUND); |
||||
exit; |
||||
} |
||||
|
||||
$activity = new MeetingActivity(); |
||||
$activity->setName($action); |
||||
$activity->setType($objectType); |
||||
$activity->setEvent(json_encode($object)); |
||||
|
||||
switch ($objectType) { |
||||
case 'meeting': |
||||
error_log('Meeting '.$action.' - '.$meeting->getId()); |
||||
error_log(print_r($object, 1)); |
||||
|
||||
switch ($action) { |
||||
case 'deleted': |
||||
$em->remove($meeting); |
||||
break; |
||||
case 'ended': |
||||
case 'started': |
||||
$meeting->setStatus($action); |
||||
$meeting->addActivity($activity); |
||||
$em->persist($meeting); |
||||
break; |
||||
default: |
||||
$meeting->addActivity($activity); |
||||
$em->persist($meeting); |
||||
break; |
||||
} |
||||
$em->flush(); |
||||
break; |
||||
case 'recording': |
||||
$recordingRepository = $em->getRepository(Recording::class); |
||||
|
||||
$recordingEntity = null; |
||||
if ($object->uuid) { |
||||
/** @var Recording $recordingEntity */ |
||||
$recordingEntity = $recordingRepository->findOneBy(['uuid' => $object->uuid, 'meeting' => $meeting]); |
||||
} |
||||
|
||||
error_log("Recording: $action"); |
||||
error_log(print_r($object, 1)); |
||||
|
||||
switch ($action) { |
||||
case 'completed': |
||||
$recording = new Recording(); |
||||
$recording->setRecordingMeeting(RecordingMeeting::fromObject($object)); |
||||
$recording->setMeeting($meeting); |
||||
$meeting->addActivity($activity); |
||||
$em->persist($meeting); |
||||
$em->persist($recording); |
||||
$em->flush(); |
||||
break; |
||||
case 'recovered': |
||||
/*if (null === $recordingEntity) { |
||||
$em->persist( |
||||
(new Recording())->setRecordingMeeting(RecordingMeeting::fromObject($object)) |
||||
); |
||||
$em->flush(); |
||||
}*/ |
||||
break; |
||||
case 'trashed': |
||||
case 'deleted': |
||||
$meeting->addActivity($activity); |
||||
if (null !== $recordingEntity) { |
||||
$recordMeeting = $recordingEntity->getRecordingMeeting(); |
||||
$recordingToDelete = RecordingMeeting::fromObject($object); |
||||
$files = []; |
||||
if ($recordingToDelete->recording_files) { |
||||
foreach ($recordingToDelete->recording_files as $fileToDelete) { |
||||
foreach ($recordMeeting->recording_files as $file) { |
||||
if ($fileToDelete->id != $file->id) { |
||||
$files[] = $file; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (empty($files)) { |
||||
$em->remove($recordingEntity); |
||||
} else { |
||||
$recordMeeting->recording_files = $files; |
||||
$recordingEntity->setRecordingMeeting($recordMeeting); |
||||
$em->persist($recordingEntity); |
||||
} |
||||
} |
||||
$em->persist($meeting); |
||||
$em->flush(); |
||||
break; |
||||
default: |
||||
$meeting->addActivity($activity); |
||||
$em->persist($meeting); |
||||
$em->flush(); |
||||
//error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); |
||||
//http_response_code(501); // Not Implemented |
||||
break; |
||||
} |
||||
break; |
||||
default: |
||||
error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); |
||||
http_response_code(501); // Not Implemented |
||||
break; |
||||
} |
||||
@ -0,0 +1,13 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
if (!ZoomPlugin::currentUserCanJoinGlobalMeeting()) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
api_location('join_meeting.php?meetingId='.ZoomPlugin::create()->getGlobalMeeting()->getMeetingId()); |
||||
@ -0,0 +1 @@ |
||||
<?php |
||||
@ -0,0 +1,8 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
if (!api_is_platform_admin()) { |
||||
die('You must have admin permissions to install plugins'); |
||||
} |
||||
|
||||
ZoomPlugin::create()->install(); |
||||
@ -0,0 +1,65 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\Meeting; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_block_anonymous_users(); |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
$meetingId = isset($_REQUEST['meetingId']) ? (int) $_REQUEST['meetingId'] : 0; |
||||
if (empty($meetingId)) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
$content = ''; |
||||
/** @var Meeting $meeting */ |
||||
$meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $meetingId]); |
||||
if (null === $meeting) { |
||||
api_not_allowed(true, $plugin->get_lang('MeetingNotFound')); |
||||
} |
||||
|
||||
if ($meeting->isCourseMeeting()) { |
||||
api_protect_course_script(true); |
||||
if (api_is_in_group()) { |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(), |
||||
'name' => get_lang('Groups'), |
||||
]; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(), |
||||
'name' => get_lang('GroupSpace').' '.$meeting->getGroup()->getName(), |
||||
]; |
||||
} |
||||
} |
||||
|
||||
try { |
||||
$startJoinURL = $plugin->getStartOrJoinMeetingURL($meeting); |
||||
$content .= $meeting->getIntroduction(); |
||||
|
||||
if (!empty($startJoinURL)) { |
||||
$content .= Display::url($plugin->get_lang('EnterMeeting'), $startJoinURL, ['class' => 'btn btn-primary']); |
||||
} else { |
||||
$content .= Display::return_message($plugin->get_lang('ConferenceNotAvailable'), 'warning'); |
||||
} |
||||
|
||||
if ($plugin->userIsConferenceManager($meeting)) { |
||||
$content .= ' '.Display::url( |
||||
get_lang('Details'), |
||||
api_get_path(WEB_PLUGIN_PATH).'zoom/meeting.php?meetingId='.$meeting->getMeetingId(), |
||||
['class' => 'btn btn-default'] |
||||
); |
||||
} |
||||
} catch (Exception $exception) { |
||||
Display::addFlash( |
||||
Display::return_message($exception->getMessage(), 'warning') |
||||
); |
||||
} |
||||
|
||||
Display::display_header($plugin->get_title()); |
||||
echo $plugin->getToolbar(); |
||||
echo $content; |
||||
Display::display_footer(); |
||||
@ -0,0 +1,144 @@ |
||||
<?php |
||||
/* License: see /license.txt */ |
||||
|
||||
// Needed in order to show the plugin title |
||||
$strings['plugin_title'] = "Zoom Videoconference"; |
||||
$strings['plugin_comment'] = "Zoom Videoconference integration in courses and sessions"; |
||||
|
||||
$strings['tool_enable'] = 'Zoom videoconference tool enabled'; |
||||
$strings['apiKey'] = 'API Key'; |
||||
$strings['apiSecret'] = 'API Secret'; |
||||
$strings['verificationToken'] = 'Verification Token'; |
||||
$strings['enableParticipantRegistration'] = 'Enable participant registration'; |
||||
$strings['enableCloudRecording'] = 'Automatic recording type'; |
||||
$strings['enableGlobalConference'] = 'Enable global conference'; |
||||
$strings['enableGlobalConferencePerUser'] = 'Enable global conference per user'; |
||||
$strings['globalConferenceAllowRoles'] = "Global conference link only visible for these user roles"; |
||||
$strings['globalConferencePerUserAllowRoles'] = "Global conference per user link only visible for these user roles"; |
||||
|
||||
$strings['tool_enable_help'] = "Choose whether you want to enable the Zoom videoconference tool. |
||||
Once enabled, it will show as an additional course tool in all courses' homepage : |
||||
teachers will be able to <strong>launch</strong> a conference and student to <strong>join</strong> it. |
||||
<br/> |
||||
This plugin requires a Zoom account to manage meetings. |
||||
The Zoom API uses JSON Web Tokens (JWT) to authenticate account-level access. |
||||
<br/> |
||||
JWT apps provide an <strong>API <em>Key</em> and <em>Secret</em></strong> required to authenticate with JWT. |
||||
|
||||
To get them, create a <em>JWT App</em> : |
||||
<br/>1. log into <a href=\"https://zoom.us/profile\">your Zoom profile page</a> |
||||
<br/>2. click on <em>Advanced / Application Marketplace</em> |
||||
<br/>3. click on <em><a href=\"https://marketplace.zoom.us/develop/create\">Develop / build App</a></em> |
||||
<br/>4. choose <em>JWT / Create</em> |
||||
<br/>5. Information: fill in fields about your \"App\" |
||||
(application and company names, contact name and email address) |
||||
<br/>6. Click on <em>Continue</em> |
||||
<br/>7. App Credentials: <strong>copy your API Key and Secret to these fields below</strong> |
||||
<br/>8. click on <em>Continue</em> |
||||
<br/>9. Feature: |
||||
enable <em>Event Subscriptions</em> to add a new one with endpoint URL |
||||
<code>https://your.chamilo.url/plugin/zoom/endpoint.php</code> |
||||
and add these event types: |
||||
<br/>- Start Meeting |
||||
<br/>- End Meeting |
||||
<br/>- Participant/Host joined meeting |
||||
<br/>- Participant/Host left meeting |
||||
<br/>- All Recordings have completed |
||||
<br/>- Recording transcript files have completed |
||||
<br/>then click on <em>Done</em> then on <em>Save</em> |
||||
and <strong>copy your Verification Token to the field below</strong>. |
||||
<br/>10. click on <em>Continue</em> |
||||
<br/> |
||||
<strong>Attention</strong>: |
||||
<br/>Zoom is <em>NOT</em> free software and specific rules apply to personal data protection. |
||||
Please check with Zoom and make sure they satisfy you and learning users."; |
||||
|
||||
$strings['enableParticipantRegistration_help'] = "Requires a paying Zoom profile. |
||||
Will not work for a <em>basic</em> profile."; |
||||
|
||||
$strings['enableCloudRecording_help'] = "Requires a paying Zoom profile. |
||||
Will not work for a <em>basic</em> profile."; |
||||
|
||||
// please keep these lines alphabetically sorted |
||||
$strings['AllCourseUsersWereRegistered'] = "All course students were registered"; |
||||
$strings['Agenda'] = "Agenda"; |
||||
$strings['CannotRegisterWithoutEmailAddress'] = "Cannot register without email address"; |
||||
$strings['CopyingJoinURL'] = "Copying join URL"; |
||||
$strings['CopyJoinAsURL'] = "Copy 'join as' URL"; |
||||
$strings['CopyToCourse'] = "Copy to course"; |
||||
$strings['CouldNotCopyJoinURL'] = "Could not copy join URL"; |
||||
$strings['Course'] = "Cours"; |
||||
$strings['CreatedAt'] = "Created at"; |
||||
$strings['CreateLinkInCourse'] = "Create link(s) in course"; |
||||
$strings['CreateUserVideoConference'] = "Create user conference"; |
||||
$strings['DateMeetingTitle'] = "%s: %s"; |
||||
$strings['DeleteMeeting'] = "Delete meeting"; |
||||
$strings['DeleteFile'] = "Delete file(s)"; |
||||
$strings['Details'] = "Details"; |
||||
$strings['DoIt'] = "Do it"; |
||||
$strings['Duration'] = "Duration"; |
||||
$strings['DurationFormat'] = "%hh%I"; |
||||
$strings['DurationInMinutes'] = "Duration (in minutes)"; |
||||
$strings['EndDate'] = "End Date"; |
||||
$strings['EnterMeeting'] = "Enter meeting"; |
||||
$strings['ViewMeeting'] = "View meeting"; |
||||
$strings['Files'] = "Files"; |
||||
$strings['Finished'] = "finished"; |
||||
$strings['FileWasCopiedToCourse'] = "The file was copied to the course"; |
||||
$strings['FileWasDeleted'] = "The file was deleted"; |
||||
$strings['GlobalMeeting'] = "Global conference"; |
||||
$strings['GlobalMeetingPerUser'] = "Global conference per user"; |
||||
$strings['GroupUsersWereRegistered'] = "Group members were registered"; |
||||
$strings['InstantMeeting'] = "Instant meeting"; |
||||
$strings['Join'] = "Join"; |
||||
$strings['JoinGlobalVideoConference'] = "Join global conference"; |
||||
$strings['JoinURLCopied'] = "Join URL copied"; |
||||
$strings['JoinURLToSendToParticipants'] = "Join URL to send to participants"; |
||||
$strings['LiveMeetings'] = "Live meetings"; |
||||
$strings['LinkToFileWasCreatedInCourse'] = "A link to the file was added to the course"; |
||||
$strings['MeetingDeleted'] = "Meeting deleted"; |
||||
$strings['MeetingsFound'] = "Meetings found"; |
||||
$strings['MeetingUpdated'] = "Meeting updated"; |
||||
$strings['NewMeetingCreated'] = "New meeting created"; |
||||
$strings['Password'] = "Password"; |
||||
$strings['RecurringWithFixedTime'] = "Recurring with fixed time"; |
||||
$strings['RecurringWithNoFixedTime'] = "Recurring with no fixed time"; |
||||
$strings['RegisterAllCourseUsers'] = "Register all course users"; |
||||
$strings['RegisteredUserListWasUpdated'] = "Registered user list updated"; |
||||
$strings['RegisteredUsers'] = "Registered users"; |
||||
$strings['RegisterNoUser'] = "Register no user"; |
||||
$strings['RegisterTheseGroupMembers'] = "Register these group members"; |
||||
$strings['ScheduleAMeeting'] = "Schedule a meeting"; |
||||
$strings['ScheduledMeeting'] = "Scheduled meeting"; |
||||
$strings['ScheduledMeetings'] = "Scheduled Meetings"; |
||||
$strings['ScheduleAMeeting'] = "Schedule a meeting"; |
||||
$strings['SearchMeeting'] = "Search meeting"; |
||||
$strings['Session'] = "Session"; |
||||
$strings['StartDate'] = "Start Date"; |
||||
$strings['Started'] = "started"; |
||||
$strings['StartInstantMeeting'] = "Start instant meeting"; |
||||
$strings['StartMeeting'] = "Start meeting"; |
||||
$strings['StartTime'] = "Start time"; |
||||
$strings['Topic'] = "Topic"; |
||||
$strings['TopicAndAgenda'] = "Topic and agenda"; |
||||
$strings['Type'] = "Type"; |
||||
$strings['UpcomingMeetings'] = "Upcoming meetings"; |
||||
$strings['UpdateMeeting'] = "Update meeting"; |
||||
$strings['UpdateRegisteredUserList'] = "Update registered user list"; |
||||
$strings['UserRegistration'] = "User registration"; |
||||
$strings['Y-m-d H:i'] = "Y-m-d H:i"; |
||||
$strings['Waiting'] = "waiting"; |
||||
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "%s recording of meeting %s from %s (%s).%s"; |
||||
$strings['YouAreNotRegisteredToThisMeeting'] = "You are not registered to this meeting"; |
||||
$strings['ZoomVideoConferences'] = "Zoom Video Conferences"; |
||||
$strings['Recordings'] = "Recordings"; |
||||
$strings['CreateGlobalVideoConference'] = "Create global video conference"; |
||||
$strings['ConferenceNotStarted'] = "Conference not started"; |
||||
$strings['MeetingNotFound'] = "Meeting not found"; |
||||
$strings['JoinURLNotAvailable'] = "URL not available"; |
||||
$strings['Meetings'] = "Meetings"; |
||||
$strings['ConferenceType'] = "Conference type"; |
||||
$strings['ForEveryone'] = "Everyone"; |
||||
$strings['SomeUsers'] = "Some users (Select later)"; |
||||
$strings['Activity'] = "Activity"; |
||||
$strings['ConferenceNotAvailable'] = "Conference not available"; |
||||
@ -0,0 +1,138 @@ |
||||
<?php |
||||
/* License: see /license.txt */ |
||||
|
||||
// Needed in order to show the plugin title |
||||
$strings['plugin_title'] = "Conférence vidéo Zoom"; |
||||
$strings['plugin_comment'] = "Intégration de conférences vidéo Zoom dans les cours et les sessions"; |
||||
|
||||
$strings['tool_enable'] = 'Outil de conférence vidéos Zoom activé'; |
||||
$strings['apiKey'] = "Clé d'API (<em>API Key</em>)"; |
||||
$strings['apiSecret'] = "Code secret d'API (<em>API Secret</em>)"; |
||||
$strings['enableParticipantRegistration'] = "Activer l'inscription des participants"; |
||||
$strings['enableCloudRecording'] = "Type d'enregistrement automatique"; |
||||
$strings['enableGlobalConference'] = "Activer les conférences globales"; |
||||
$strings['enableGlobalConferencePerUser'] = "Activer les conférences globales par utilisateur"; |
||||
$strings['globalConferenceAllowRoles'] = "Visibilité du lien de vidéo conférence global pour les profils suivant"; |
||||
$strings['globalConferencePerUserAllowRoles'] = "Visibilité du lien de vidéo conférence global par utilisateur pour les profils suivant"; |
||||
|
||||
$strings['tool_enable_help'] = "Choisissez si vous voulez activer l'outil de conférence vidéo Zoom. |
||||
Une fois activé, il apparaitra dans les pages d'accueil de tous les cours : |
||||
les enseignants pourront <strong>démarrer</strong> une conférence et les étudiants la <strong>rejoindre</strong>. |
||||
<br/> |
||||
Ce plugin requiert un compte Zoom pour gérer les conférences. |
||||
L'API de Zoom utilise les <em>JSON Web Tokens (JWT)</em> pour autoriser l'accès à un compte. |
||||
<strong>Une <em>clé</em> et un <em>code secret</em> d'API sont requis</strong> pour s'authentifier avec JWT. |
||||
Pour les obtenir, créez une <em>JWT app</em> : |
||||
<br/>1. logguez vous sur <a href=\"https://zoom.us/profile\">Votre profil Zoom</a> |
||||
<br/>2. cliquez sur <em>Avancé / Marketplace d'application</em> |
||||
<br/>3. cliquez sur <em><a href=\"https://marketplace.zoom.us/develop/create\">Develop / build App</a></em> |
||||
<br/>4. choisissez <em>JWT / Create</em> |
||||
<br/>5. Information: remplissez quelques champs à propos de votre \"App\" |
||||
(noms de l'application, de l'entreprise, nom et adresse de courriel de contact) |
||||
<br/>6. cliquez sur <em>Continue</em> |
||||
<br/>7. App Credentials : |
||||
<strong>copiez la clé (API Key) et le code secret (API Secret) dans les champs ci-dessous.</strong> |
||||
<br/>8. cliquez sur <em>Continue</em> |
||||
<br/>9. Feature : |
||||
activez <em>Event Subscriptions</em> pour en ajouter une avec comme endpoint URL |
||||
<code>https://your.chamilo.url/plugin/zoom/endpoint.php</code> |
||||
et ajoutez ces types d'événements : |
||||
<br/>- Start Meeting |
||||
<br/>- End Meeting |
||||
<br/>- Participant/Host joined meeting |
||||
<br/>- Participant/Host left meeting |
||||
<br/>- All Recordings have completed |
||||
<br/>- Recording transcript files have completed |
||||
<br/>puis cliquez sur <em>Done</em> puis sur <em>Save</em> |
||||
et <strong>copiez votre Verification Token dans le champ ci-dessous</strong>. |
||||
<br/>10. cliquez sur <em>Continue</em> |
||||
<br/> |
||||
<strong>Attention</strong> : |
||||
<br/>Zoom n'est <em>PAS</em> un logiciel libre |
||||
et des règles spécifiques de protection des données personnelles s'y appliquent. |
||||
Merci de vérifier auprès de Zoom qu'elles sont satisfaisantes pour vous et les apprenants qui l'utiliseront."; |
||||
|
||||
$strings['enableParticipantRegistration_help'] = "Nécessite un profil Zoom payant. |
||||
Ne fonctionnera pas pour un profil <em>de base</em>."; |
||||
|
||||
$strings['enableCloudRecording_help'] = "Nécessite un profil Zoom payant. |
||||
Ne fonctionnera pas pour un profil <em>de base</em>."; |
||||
|
||||
// please keep these lines alphabetically sorted |
||||
$strings['AllCourseUsersWereRegistered'] = "Tous les étudiants du cours sont inscrits"; |
||||
$strings['Agenda'] = "Ordre du jour"; |
||||
$strings['CannotRegisterWithoutEmailAddress'] = "Impossible d'inscrire un utilisateur sans adresse de courriel"; |
||||
$strings['CopyingJoinURL'] = "Copie de l'URL pour rejoindre en cours"; |
||||
$strings['CopyJoinAsURL'] = "Copier l'URL pour 'rejoindre en tant que'"; |
||||
$strings['CopyToCourse'] = "Copier dans le cours"; |
||||
$strings['CouldNotCopyJoinURL'] = "Échec de la copie de l'URL pour rejoindre"; |
||||
$strings['Course'] = "Cours"; |
||||
$strings['CreatedAt'] = "Créé à"; |
||||
$strings['CreateLinkInCourse'] = "Créer dans le cours un ou des lien(s) vers le(s) fichier(s)"; |
||||
$strings['CreateUserVideoConference'] = "Créer des conferences par utilisateur"; |
||||
$strings['DateMeetingTitle'] = "%s : %s"; |
||||
$strings['DeleteMeeting'] = "Effacer la conférence"; |
||||
$strings['DeleteFile'] = "Supprimer ce(s) fichier(s)"; |
||||
$strings['Details'] = "Détail"; |
||||
$strings['DoIt'] = "Fais-le"; |
||||
$strings['Duration'] = "Durée"; |
||||
$strings['DurationFormat'] = "%hh%I"; |
||||
$strings['DurationInMinutes'] = "Durée (en minutes)"; |
||||
$strings['EndDate'] = "Date de fin"; |
||||
$strings['EnterMeeting'] = "Entrer dans la conférence"; |
||||
$strings['ViewMeeting'] = "Voir la conférence"; |
||||
$strings['Files'] = "Fichiers"; |
||||
$strings['Finished'] = "terminée"; |
||||
$strings['FileWasCopiedToCourse'] = "Le fichier a été copié dans le cours"; |
||||
$strings['FileWasDeleted'] = "Le fichier a été effacé"; |
||||
$strings['GlobalMeeting'] = "Conférence globale"; |
||||
$strings['GroupUsersWereRegistered'] = "Les membres des groupes ont été inscrits"; |
||||
$strings['InstantMeeting'] = "Conférence instantanée"; |
||||
$strings['Join'] = "Rejoindre"; |
||||
$strings['JoinGlobalVideoConference'] = "Rejoindre la conférence globale"; |
||||
$strings['JoinURLCopied'] = "URL pour rejoindre copiée"; |
||||
$strings['JoinURLToSendToParticipants'] = "URL pour assister à la conférence (à envoyer aux participants)"; |
||||
$strings['LiveMeetings'] = "Conférences en cours"; |
||||
$strings['LinkToFileWasCreatedInCourse'] = "Un lien vers le fichier a été ajouter au cours"; |
||||
$strings['MeetingDeleted'] = "Conférence effacée"; |
||||
$strings['MeetingsFound'] = "Conférences trouvées"; |
||||
$strings['MeetingUpdated'] = "Conférence mise à jour"; |
||||
$strings['NewMeetingCreated'] = "Nouvelle conférence créée"; |
||||
$strings['Password'] = "Mot de passe"; |
||||
$strings['RecurringWithFixedTime'] = "Recurrent, à heure fixe"; |
||||
$strings['RecurringWithNoFixedTime'] = "Recurrent, sans heure fixe"; |
||||
$strings['RegisterAllCourseUsers'] = "Inscrire tous les utilisateurs du cours"; |
||||
$strings['RegisteredUserListWasUpdated'] = "Liste des utilisateurs inscrits mise à jour"; |
||||
$strings['RegisteredUsers'] = "Utilisateurs inscrits"; |
||||
$strings['RegisterNoUser'] = "N'inscrire aucun utilisateur"; |
||||
$strings['RegisterTheseGroupMembers'] = "Inscrire les membres de ces groupes"; |
||||
$strings['ScheduleAMeeting'] = "Programmer une conférence"; |
||||
$strings['ScheduledMeeting'] = "Conférence programmée"; |
||||
$strings['ScheduledMeetings'] = "Conférences programmées"; |
||||
$strings['ScheduleAMeeting'] = "Programmer une conférence"; |
||||
$strings['SearchMeeting'] = "Rechercher une conférence"; |
||||
$strings['Session'] = "Session"; |
||||
$strings['StartDate'] = "Date de début"; |
||||
$strings['Started'] = "démarrée"; |
||||
$strings['StartInstantMeeting'] = "Démarrer une conférence instantanée"; |
||||
$strings['StartMeeting'] = "Démarrer la conférence"; |
||||
$strings['StartTime'] = "Heure de début"; |
||||
$strings['Topic'] = "Objet"; |
||||
$strings['TopicAndAgenda'] = "Objet et ordre du jour"; |
||||
$strings['Type'] = "Type"; |
||||
$strings['UpcomingMeeting'] = "Conférences à venir"; |
||||
$strings['UpdateMeeting'] = "Mettre à jour la conférence"; |
||||
$strings['UpdateRegisteredUserList'] = "Mettre à jour la liste des utilisateurs inscrits"; |
||||
$strings['UserRegistration'] = "Inscription des utilisateurs"; |
||||
$strings['Y-m-d H:i'] = "d/m/Y à H\hi"; |
||||
$strings['verificationToken'] = 'Verification Token'; |
||||
$strings['Waiting'] = "en attente"; |
||||
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "Enregistrement (%s) de la conférence %s de %s (%s).%s"; |
||||
$strings['YouAreNotRegisteredToThisMeeting'] = "Vous n'êtes pas inscrit à cette conférence"; |
||||
$strings['ZoomVideoConferences'] = "Conférences vidéo Zoom"; |
||||
$strings['Recordings'] = "Enregistrements"; |
||||
$strings['CreateGlobalVideoConference'] = "Créer une conférence global"; |
||||
$strings['JoinURLNotAvailable'] = "URL pas disponible"; |
||||
$strings['Meetings'] = "Conférences"; |
||||
$strings['Activity'] = "Activité"; |
||||
$strings['ConferenceNotAvailable'] = "Conférence non disponible"; |
||||
@ -0,0 +1,138 @@ |
||||
<?php |
||||
/* License: see /license.txt */ |
||||
|
||||
// Needed in order to show the plugin title |
||||
$strings['plugin_title'] = "Videoconferencia Zoom"; |
||||
$strings['plugin_comment'] = "Integración de videoconferencias Zoom en los cursos y las sesiones"; |
||||
|
||||
$strings['tool_enable'] = 'Herramienta activada'; |
||||
$strings['apiKey'] = "Clave API (<em>API Key</em>)"; |
||||
$strings['apiSecret'] = "Código secreto de API (<em>API Secret</em>)"; |
||||
$strings['enableParticipantRegistration'] = "Activar la inscripción de participantes"; |
||||
$strings['enableCloudRecording'] = "Tipo de grabación automática"; |
||||
$strings['enableGlobalConference'] = "Activar las conferencias globales"; |
||||
$strings['enableGlobalConferencePerUser'] = "Activar las conferencias globales por usuario"; |
||||
$strings['globalConferenceAllowRoles'] = "Visibilidad del enlace global de videoconferencia para los perfiles siguientes"; |
||||
$strings['globalConferencePerUserAllowRoles'] = "Visibilidad del enlace global de videoconferencia por usuario para los perfiles siguientes"; |
||||
|
||||
$strings['tool_enable_help'] = "Escoja si desea activar la herramienta Zoom. |
||||
Una vez activada, aparecerá en las páginas principales de todos los cursos. Los profesores podrán |
||||
<strong>iniciar</strong> una conferencia y los alumnos <strong>juntarse</strong> a ella. |
||||
<br/> |
||||
Este plugin requiere una cuenta Zoom para gestionar las conferencias. |
||||
El API de Zoom utiliza los <em>JSON Web Tokens (JWT)</em> para autorizar el acceso a una cuenta. |
||||
<strong>Una <em>clave</em> y un <em>código secreto</em> de API son necesarios</strong> para identificarse con JWT. |
||||
Para obtenerlos, crea una <em>app JWT</em> : |
||||
<br/>1. logéase en <a href=\"https://zoom.us/profile\">Su perfil Zoom</a> |
||||
<br/>2. de clic en <em>Avanzado / Marketplace de aplicaciones</em> |
||||
<br/>3. de clic en <em><a href=\"https://marketplace.zoom.us/develop/create\">Develop / build App</a></em> |
||||
<br/>4. escoja <em>JWT / Create</em> |
||||
<br/>5. Information: ingrese algunas informaciones sobre vuestra \"App\" |
||||
(nombres de la aplicación, de la empresa, nombre y dirección de correo de contacto) |
||||
<br/>6. de clic en <em>Continue</em> |
||||
<br/>7. App Credentials: |
||||
muestra la clave (API Key) y el código secreto (API Secret) por ingresar aquí. |
||||
<strong>copiez la clé (API Key) et le code secret (API Secret) dans les champs ci-dessous.</strong> |
||||
<br/>8. de clic en <em>Continue</em> |
||||
<br/>9. Feature : |
||||
activez <em>Event Subscriptions</em> para agregar uno con su endpoint URL |
||||
<code>https://your.chamilo.url/plugin/zoom/endpoint.php</code> |
||||
y agrega este tipo de eventos: |
||||
<br/>- Start Meeting |
||||
<br/>- End Meeting |
||||
<br/>- Participant/Host joined meeting |
||||
<br/>- Participant/Host left meeting |
||||
<br/>- All Recordings have completed |
||||
<br/>- Recording transcript files have completed |
||||
<br/>de clic en <em>Done</em> y luego en <em>Save</em> |
||||
y <strong>copie su Verification Token en el campo a continuación</strong>. |
||||
<br/>10. de clic en <em>Continue</em> |
||||
<br/> |
||||
<strong>Atención</strong> : |
||||
<br/>Zoom <em>NO ES</em> un software libre, y reglas específicas de protección de datos se aplican a este. |
||||
Por favor verifique con Zoom que éstas le den satisfacción a Usted y los alumnos que la usarán."; |
||||
|
||||
$strings['enableParticipantRegistration_help'] = "Requiere un perfil Zoom de pago. |
||||
No funcionará para un perfil <em>base/gratuito</em>."; |
||||
|
||||
$strings['enableCloudRecording_help'] = "Requiere un perfil Zoom de pago. |
||||
No funcionará para un perfil <em>base/gratuito</em>."; |
||||
|
||||
// please keep these lines alphabetically sorted |
||||
$strings['AllCourseUsersWereRegistered'] = "Todos los alumnos del curso están inscritos"; |
||||
$strings['Agenda'] = "Orden del día"; |
||||
$strings['CannotRegisterWithoutEmailAddress'] = "No se puede registrar usuario sin dirección de correo electrónico"; |
||||
$strings['CopyingJoinURL'] = "Copia de la URL para ingresar"; |
||||
$strings['CopyJoinAsURL'] = "Copiar la URL para 'ingresar como'"; |
||||
$strings['CopyToCourse'] = "Copiar en el curso"; |
||||
$strings['CouldNotCopyJoinURL'] = "Falló la copia de la URL de ingreso"; |
||||
$strings['Course'] = "Curso"; |
||||
$strings['CreatedAt'] = "Creado el"; |
||||
$strings['CreateLinkInCourse'] = "Crear en el curso uno o más vínculos hacia el/los archivo(s)"; |
||||
$strings['CreateUserVideoConference'] = "Crear conferencias de usario"; |
||||
$strings['DateMeetingTitle'] = "%s: %s"; |
||||
$strings['DeleteMeeting'] = "Borrar la conferencia"; |
||||
$strings['DeleteFile'] = "Borrar este/estos archivo(s)"; |
||||
$strings['Details'] = "Detalle"; |
||||
$strings['DoIt'] = "Hágalo"; |
||||
$strings['Duration'] = "Duración"; |
||||
$strings['DurationFormat'] = "%hh%I"; |
||||
$strings['DurationInMinutes'] = "Duración (en minutos)"; |
||||
$strings['EndDate'] = "Fecha de fin"; |
||||
$strings['EnterMeeting'] = "Ingresar la conferencia"; |
||||
$strings['ViewMeeting'] = "Ver la conferencia"; |
||||
$strings['Files'] = "Archivos"; |
||||
$strings['Finished'] = "terminada"; |
||||
$strings['FileWasCopiedToCourse'] = "El archivo ha sido copiado en el curso"; |
||||
$strings['FileWasDeleted'] = "El archivo ha sido borrado"; |
||||
$strings['GlobalMeeting'] = "Conferencia global"; |
||||
$strings['GroupUsersWereRegistered'] = "Miembros de los grupos han sido registrados"; |
||||
$strings['InstantMeeting'] = "Conferencia instantánea"; |
||||
$strings['Join'] = "Ingresar"; |
||||
$strings['JoinGlobalVideoConference'] = "Ingresar la conrencia global"; |
||||
$strings['JoinURLCopied'] = "URL para juntarse copiada"; |
||||
$strings['JoinURLToSendToParticipants'] = "URL para asistir a la conferencia (para enviar a los participantes)"; |
||||
$strings['LiveMeetings'] = "Conferencias activas"; |
||||
$strings['LinkToFileWasCreatedInCourse'] = "Un enlace al archivo ha sido añadido al curso"; |
||||
$strings['MeetingDeleted'] = "Conferencia borrada"; |
||||
$strings['MeetingsFound'] = "Conferencias encontradas"; |
||||
$strings['MeetingUpdated'] = "Conferencias actualizadas"; |
||||
$strings['NewMeetingCreated'] = "Nueva conferencia creada"; |
||||
$strings['Password'] = "Contraseña"; |
||||
$strings['RecurringWithFixedTime'] = "Recurrente, a una hora fija"; |
||||
$strings['RecurringWithNoFixedTime'] = "Recurrente, sin hora fija"; |
||||
$strings['RegisterAllCourseUsers'] = "Inscribir todos los usuarios del curso"; |
||||
$strings['RegisteredUserListWasUpdated'] = "Lista de usuarios inscritos actualizada"; |
||||
$strings['RegisteredUsers'] = "Usuarios inscritos"; |
||||
$strings['RegisterNoUser'] = "No inscribir ningún usuario"; |
||||
$strings['RegisterTheseGroupMembers'] = "Inscribir los miembros de estos grupos"; |
||||
$strings['ScheduleAMeeting'] = "Programar una conferencia"; |
||||
$strings['ScheduledMeeting'] = "Conferencia programada"; |
||||
$strings['ScheduledMeetings'] = "Conferencias programadas"; |
||||
$strings['ScheduleAMeeting'] = "Programar una conferencia"; |
||||
$strings['SearchMeeting'] = "Buscar una conferencia"; |
||||
$strings['Session'] = "Sesión"; |
||||
$strings['StartDate'] = "Fecha de inicio"; |
||||
$strings['Started'] = "iniciada"; |
||||
$strings['StartInstantMeeting'] = "Iniciar una conferencia instantánea"; |
||||
$strings['StartMeeting'] = "Iniciar la conferencia"; |
||||
$strings['StartTime'] = "Hora de inicio"; |
||||
$strings['Topic'] = "Objeto"; |
||||
$strings['TopicAndAgenda'] = "Objeto y orden del día"; |
||||
$strings['Type'] = "Tipo"; |
||||
$strings['UpcomingMeeting'] = "Próximas conferencias"; |
||||
$strings['UpdateMeeting'] = "Actualizar la conferencia"; |
||||
$strings['UpdateRegisteredUserList'] = "Actualizar la lista de usuarios inscritos"; |
||||
$strings['UserRegistration'] = "Inscripción de los usuarios"; |
||||
$strings['Y-m-d H:i'] = "d/m/Y a las H\hi"; |
||||
$strings['verificationToken'] = 'Verification Token'; |
||||
$strings['Waiting'] = "en espera"; |
||||
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "Grabación (%s) de la conferencia %s de %s (%s).%s"; |
||||
$strings['YouAreNotRegisteredToThisMeeting'] = "No estás registrado en esta reunión"; |
||||
$strings['ZoomVideoConferences'] = "Videoconferencias Zoom"; |
||||
$strings['Recordings'] = "Grabaciones"; |
||||
$strings['CreateGlobalVideoConference'] = "Crear una videoconferencia global"; |
||||
$strings['JoinURLNotAvailable'] = "URL no disponible"; |
||||
$strings['Meetings'] = "Conferencias"; |
||||
$strings['Activity'] = "Actividad"; |
||||
$strings['ConferenceNotAvailable'] = "Conferencia no disponible"; |
||||
@ -0,0 +1,32 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Trait BaseMeetingTrait. |
||||
* Common meeting properties definitions. |
||||
*/ |
||||
trait BaseMeetingTrait |
||||
{ |
||||
/** @var string */ |
||||
public $topic; |
||||
|
||||
/** @var int */ |
||||
public $type; |
||||
|
||||
/** @var string "yyyy-MM-dd'T'HH:mm:ss'Z'" for GMT, same without 'Z' for local time (as set on zoom account) */ |
||||
public $start_time; |
||||
|
||||
/** @var int in minutes, for scheduled meetings only */ |
||||
public $duration; |
||||
|
||||
/** @var string the timezone for start_time */ |
||||
public $timezone; |
||||
|
||||
/** @var string description */ |
||||
public $agenda; |
||||
/** @var string description */ |
||||
public $host_email; |
||||
} |
||||
@ -0,0 +1,56 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Interface Client. |
||||
* Two implementations are currently possible : OAuth and JWT. |
||||
* |
||||
* @see https://marketplace.zoom.us/docs/api-reference/zoom-api |
||||
*/ |
||||
abstract class Client |
||||
{ |
||||
/** @var Client */ |
||||
private static $instance; |
||||
|
||||
/** |
||||
* Returns an initialized Client. |
||||
* |
||||
* @return Client |
||||
*/ |
||||
public static function getInstance() |
||||
{ |
||||
return self::$instance; |
||||
} |
||||
|
||||
/** |
||||
* Sends a Zoom API-compliant HTTP request and retrieves the response. |
||||
* |
||||
* On success, returns the body of the response |
||||
* On error, throws an exception with an detailed error message |
||||
* |
||||
* @param string $httpMethod GET, POST, PUT, DELETE ... |
||||
* @param string $relativePath to append to https://api.zoom.us/v2/ |
||||
* @param array $parameters request query parameters |
||||
* @param object $requestBody json-encoded body of the request |
||||
* |
||||
* @throws Exception describing the error (message and code) |
||||
* |
||||
* @return string response body (not json-decoded) |
||||
*/ |
||||
abstract public function send($httpMethod, $relativePath, $parameters = [], $requestBody = null); |
||||
|
||||
/** |
||||
* Registers an initialized Client. |
||||
* |
||||
* @param Client $instance |
||||
*/ |
||||
protected static function register($instance) |
||||
{ |
||||
self::$instance = $instance; |
||||
} |
||||
} |
||||
@ -0,0 +1,42 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class CreatedRegistration. |
||||
* An instance of this class is returned by the Zoom server upon recording a registrant to a meeting. |
||||
*/ |
||||
class CreatedRegistration |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var int meeting ID */ |
||||
public $id; |
||||
|
||||
/** @var string Unique URL for this registrant to join the meeting. |
||||
* This URL should only be shared with the registrant for whom the API request was made. |
||||
* If the meeting was created with manual approval type (1), the join URL will not be returned in the response. |
||||
*/ |
||||
public $join_url; |
||||
|
||||
/** @var string Unique identifier of the registrant */ |
||||
public $registrant_id; |
||||
|
||||
/** @var string The start time for the meeting. */ |
||||
public $start_time; |
||||
|
||||
/** @var string Topic of the meeting. */ |
||||
public $topic; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Class CustomQuestion. |
||||
* A list of instances of this class is included in a MeetingRegistrant instance. |
||||
*/ |
||||
class CustomQuestion |
||||
{ |
||||
/** @var string */ |
||||
public $title; |
||||
|
||||
/** @var string */ |
||||
public $value; |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class GlobalDialInNumber. |
||||
* A list of these is included in a meeting settings. |
||||
*/ |
||||
class GlobalDialInNumber |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string Country code. For example, BR. */ |
||||
public $country; |
||||
|
||||
/** @var string Full name of country. For example, Brazil. */ |
||||
public $country_name; |
||||
|
||||
/** @var string City of the number, if any. For example, Chicago. */ |
||||
public $city; |
||||
|
||||
/** @var string Phone number. For example, +1 2332357613. */ |
||||
public $number; |
||||
|
||||
/** @var string Type of number. Either "toll" or "tollfree". */ |
||||
public $type; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,94 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
use Firebase\JWT\JWT; |
||||
|
||||
/** |
||||
* Class JWTClient. |
||||
* |
||||
* @see https://marketplace.zoom.us/docs/guides/auth/jwt |
||||
*/ |
||||
class JWTClient extends Client |
||||
{ |
||||
public $token; |
||||
|
||||
/** |
||||
* JWTClient constructor. |
||||
* Requires JWT app credentials. |
||||
* |
||||
* @param string $apiKey JWT API Key |
||||
* @param string $apiSecret JWT API Secret |
||||
*/ |
||||
public function __construct($apiKey, $apiSecret) |
||||
{ |
||||
$this->token = JWT::encode( |
||||
[ |
||||
'iss' => $apiKey, |
||||
'exp' => (time() + 60) * 1000, // will expire in one minute |
||||
], |
||||
$apiSecret |
||||
); |
||||
self::register($this); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function send($httpMethod, $relativePath, $parameters = [], $requestBody = null) |
||||
{ |
||||
$options = [ |
||||
CURLOPT_CUSTOMREQUEST => $httpMethod, |
||||
CURLOPT_ENCODING => '', |
||||
CURLOPT_HTTPHEADER => [ |
||||
'authorization: Bearer '.$this->token, |
||||
'content-type: application/json', |
||||
], |
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, |
||||
CURLOPT_MAXREDIRS => 10, |
||||
CURLOPT_RETURNTRANSFER => true, |
||||
CURLOPT_TIMEOUT => 30, |
||||
]; |
||||
if (!is_null($requestBody)) { |
||||
$jsonRequestBody = json_encode($requestBody); |
||||
if (false === $jsonRequestBody) { |
||||
throw new Exception('Could not generate JSON request body'); |
||||
} |
||||
$options[CURLOPT_POSTFIELDS] = $jsonRequestBody; |
||||
} |
||||
|
||||
$url = "https://api.zoom.us/v2/$relativePath"; |
||||
if (!empty($parameters)) { |
||||
$url .= '?'.http_build_query($parameters); |
||||
} |
||||
$curl = curl_init($url); |
||||
if (false === $curl) { |
||||
throw new Exception("curl_init returned false"); |
||||
} |
||||
curl_setopt_array($curl, $options); |
||||
$responseBody = curl_exec($curl); |
||||
$responseCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); |
||||
$curlError = curl_error($curl); |
||||
curl_close($curl); |
||||
|
||||
if ($curlError) { |
||||
throw new Exception("cURL Error: $curlError"); |
||||
} |
||||
|
||||
if (false === $responseBody || !is_string($responseBody)) { |
||||
throw new Exception('cURL Error'); |
||||
} |
||||
|
||||
if (empty($responseCode) |
||||
|| $responseCode < 200 |
||||
|| $responseCode >= 300 |
||||
) { |
||||
throw new Exception($responseBody, $responseCode); |
||||
} |
||||
|
||||
return $responseBody; |
||||
} |
||||
} |
||||
@ -0,0 +1,122 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Trait JsonDeserializableTrait. |
||||
* Utility functions to help convert server-generated JSON to API class instances. |
||||
*/ |
||||
trait JsonDeserializableTrait |
||||
{ |
||||
/** |
||||
* Builds a class instance from the Json description of the object. |
||||
* |
||||
* @param string $json |
||||
* |
||||
* @throws Exception on JSON-decode error or unexpected object property |
||||
* |
||||
* @return static |
||||
*/ |
||||
public static function fromJson($json) |
||||
{ |
||||
if (empty($json)) { |
||||
throw new Exception('Cannot JSON-decode empty string'); |
||||
} |
||||
$object = json_decode($json); |
||||
if (null === $object) { |
||||
throw new Exception('Could not decode JSON: '.$json); |
||||
} |
||||
|
||||
return static::fromObject($object); |
||||
} |
||||
|
||||
/** |
||||
* Builds a class instance from an already json-decoded object. |
||||
* |
||||
* @param object $object |
||||
* |
||||
* @throws Exception on unexpected object property |
||||
* |
||||
* @return static |
||||
*/ |
||||
public static function fromObject($object) |
||||
{ |
||||
$instance = new static(); |
||||
static::recursivelyCopyObjectProperties($object, $instance); |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* Returns the class name of the items to be found in the named array property. |
||||
* |
||||
* To override in classes that have a property of type array |
||||
* |
||||
* @param string $propertyName array property name |
||||
* |
||||
* @throws Exception if not implemented for this propertyName |
||||
* |
||||
* @return string class name of the items to be found in the named array property |
||||
*/ |
||||
abstract public function itemClass($propertyName); |
||||
|
||||
/** |
||||
* Initializes properties that can be calculated from json-decoded properties. |
||||
* |
||||
* Called at the end of method recursivelyCopyObjectProperties() |
||||
* and indirectly at the end of static method fromJson(). |
||||
* |
||||
* By default it does nothing. |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
// default does nothing |
||||
} |
||||
|
||||
/** |
||||
* Copies values from another object properties to an instance, recursively. |
||||
* |
||||
* @param object $source source object |
||||
* @param object $destination specific class instance, with already initialized properties |
||||
* |
||||
* @throws Exception when the source object has an unexpected property |
||||
*/ |
||||
protected static function recursivelyCopyObjectProperties($source, &$destination) |
||||
{ |
||||
foreach (get_object_vars($source) as $name => $value) { |
||||
if (property_exists($destination, $name)) { |
||||
if (is_object($value)) { |
||||
if (is_object($destination->$name)) { |
||||
static::recursivelyCopyObjectProperties($value, $destination->$name); |
||||
} else { |
||||
throw new Exception("Source property $name is an object, which is not expected"); |
||||
} |
||||
} elseif (is_array($value)) { |
||||
if (is_array($destination->$name)) { |
||||
$itemClass = $destination->itemClass($name); |
||||
foreach ($value as $sourceItem) { |
||||
if ('string' === $itemClass) { |
||||
$destination->$name[] = $sourceItem; |
||||
} else { |
||||
$item = new $itemClass(); |
||||
static::recursivelyCopyObjectProperties($sourceItem, $item); |
||||
$destination->$name[] = $item; |
||||
} |
||||
} |
||||
} else { |
||||
throw new Exception("Source property $name is an array, which is not expected"); |
||||
} |
||||
} else { |
||||
$destination->$name = $value; |
||||
} |
||||
} else { |
||||
error_log("Source object has property $name, which was not expected: ".json_encode($source)); |
||||
} |
||||
} |
||||
$destination->initializeExtraProperties(); |
||||
} |
||||
} |
||||
@ -0,0 +1,84 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class Meeting, minimal meeting definition required to create one from scratch or update an existing one |
||||
* Also referred to as MeetingUpdate in the API documentation |
||||
* Does not represent an actual created meeting. |
||||
*/ |
||||
class Meeting |
||||
{ |
||||
use BaseMeetingTrait; |
||||
use JsonDeserializableTrait; |
||||
|
||||
const TYPE_INSTANT = 1; |
||||
const TYPE_SCHEDULED = 2; |
||||
const TYPE_RECURRING_WITH_NO_FIXED_TIME = 3; |
||||
const TYPE_RECURRING_WITH_FIXED_TIME = 8; |
||||
|
||||
/** @var string password to join. [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. */ |
||||
public $password; |
||||
|
||||
/** @var TrackingField[] Tracking fields */ |
||||
public $tracking_fields; |
||||
|
||||
/** @var object, only for a recurring meeting with fixed time (type 8) */ |
||||
public $recurrence; |
||||
|
||||
/** @var MeetingSettings */ |
||||
public $settings; |
||||
|
||||
/** |
||||
* Meeting constructor. |
||||
*/ |
||||
protected function __construct() |
||||
{ |
||||
$this->tracking_fields = []; |
||||
$this->settings = new MeetingSettings(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('tracking_fields' === $propertyName) { |
||||
return TrackingField::class; |
||||
} |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
|
||||
/** |
||||
* Creates a meeting on the server and returns the resulting MeetingInfoGet. |
||||
* |
||||
* @throws Exception describing the error (message and code) |
||||
* |
||||
* @return MeetingInfoGet meeting |
||||
*/ |
||||
public function create() |
||||
{ |
||||
return MeetingInfoGet::fromJson(Client::getInstance()->send('POST', 'users/me/meetings', [], $this)); |
||||
} |
||||
|
||||
/** |
||||
* Creates a Meeting instance from a topic. |
||||
* |
||||
* @param string $topic |
||||
* @param int $type |
||||
* |
||||
* @return static |
||||
*/ |
||||
public static function fromTopicAndType($topic, $type = self::TYPE_SCHEDULED) |
||||
{ |
||||
$instance = new static(); |
||||
$instance->topic = $topic; |
||||
$instance->type = $type; |
||||
|
||||
return $instance; |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Class MeetingInfo |
||||
* Used to define MeetingInfoGet |
||||
* Does not seem to be used directly. |
||||
*/ |
||||
class MeetingInfo extends Meeting |
||||
{ |
||||
/** @var string */ |
||||
public $created_at; |
||||
|
||||
/** @var string, allows host to start the meeting as the host (without password) - not to be shared */ |
||||
public $start_url; |
||||
|
||||
/** @var string, for participants to join the meeting - to share with users to invite */ |
||||
public $join_url; |
||||
|
||||
/** @var string undocumented */ |
||||
public $registration_url; |
||||
|
||||
/** @var string H.323/SIP room system password */ |
||||
public $h323_password; |
||||
|
||||
/** @var int Personal Meeting Id. Only used for scheduled meetings and recurring meetings with no fixed time */ |
||||
public $pmi; |
||||
|
||||
/** @var object[] */ |
||||
public $occurrences; |
||||
} |
||||
@ -0,0 +1,148 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingInfoGet |
||||
* Full Meeting as returned by the server, with unique identifiers and current status. |
||||
*/ |
||||
class MeetingInfoGet extends MeetingInfo |
||||
{ |
||||
/** @var string unique meeting instance ID */ |
||||
public $uuid; |
||||
|
||||
/** @var string meeting number */ |
||||
public $id; |
||||
|
||||
/** @var string host Zoom user id */ |
||||
public $host_id; |
||||
|
||||
/** @var string meeting status, either "waiting", "started" or "finished" */ |
||||
public $status; |
||||
|
||||
/** @var string undocumented */ |
||||
public $pstn_password; |
||||
|
||||
/** @var string Encrypted password for third party endpoints (H323/SIP). */ |
||||
public $encrypted_password; |
||||
|
||||
/** |
||||
* Retrieves a meeting from its numeric identifier. |
||||
* |
||||
* @param int $id |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return static the meeting |
||||
*/ |
||||
public static function fromId($id) |
||||
{ |
||||
return static::fromJson(Client::getInstance()->send('GET', "meetings/$id")); |
||||
} |
||||
|
||||
/** |
||||
* Updates the meeting on server. |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function update() |
||||
{ |
||||
Client::getInstance()->send('PATCH', 'meetings/'.$this->id, [], $this); |
||||
} |
||||
|
||||
/** |
||||
* Ends the meeting on server. |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function endNow() |
||||
{ |
||||
Client::getInstance()->send('PUT', "meetings/$this->id/status", [], (object) ['action' => 'end']); |
||||
} |
||||
|
||||
/** |
||||
* Deletes the meeting on server. |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function delete() |
||||
{ |
||||
Client::getInstance()->send('DELETE', "meetings/$this->id"); |
||||
} |
||||
|
||||
/** |
||||
* Adds a registrant to the meeting. |
||||
* |
||||
* @param MeetingRegistrant $registrant with at least 'email' and 'first_name'. |
||||
* 'last_name' will also be recorded by Zoom. |
||||
* Other properties remain ignored, or not returned by Zoom |
||||
* (at least while using profile "Pro") |
||||
* @param string $occurrenceIds separated by comma |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return CreatedRegistration with unique join_url and registrant_id properties |
||||
*/ |
||||
public function addRegistrant($registrant, $occurrenceIds = '') |
||||
{ |
||||
return CreatedRegistration::fromJson( |
||||
Client::getInstance()->send( |
||||
'POST', |
||||
"meetings/$this->id/registrants", |
||||
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds], |
||||
$registrant |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Removes registrants from the meeting. |
||||
* |
||||
* @param MeetingRegistrant[] $registrants registrants to remove (id and email) |
||||
* @param string $occurrenceIds separated by comma |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function removeRegistrants($registrants, $occurrenceIds = '') |
||||
{ |
||||
if (!empty($registrants)) { |
||||
Client::getInstance()->send( |
||||
'PUT', |
||||
"meetings/$this->id/registrants/status", |
||||
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds], |
||||
(object) [ |
||||
'action' => 'cancel', |
||||
'registrants' => $registrants, |
||||
] |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Retrieves meeting registrants. |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrantListItem[] the meeting registrants |
||||
*/ |
||||
public function getRegistrants() |
||||
{ |
||||
return MeetingRegistrantList::loadMeetingRegistrants($this->id); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves the meeting's instances. |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingInstance[] |
||||
*/ |
||||
public function getInstances() |
||||
{ |
||||
return MeetingInstances::fromMeetingId($this->id)->meetings; |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingInstance |
||||
* A meeting (numerical id) can have one or more instances (string UUID). |
||||
* Each instance has its own start time, participants and recording files. |
||||
* |
||||
* @see MeetingInstances |
||||
* @see PastMeeting for the full record |
||||
*/ |
||||
class MeetingInstance |
||||
{ |
||||
/** @var string */ |
||||
public $uuid; |
||||
|
||||
/** @var string */ |
||||
public $start_time; |
||||
|
||||
/** |
||||
* Retrieves the recording of the instance. |
||||
* |
||||
* @throws Exception with code 404 when there is no recording for this meeting |
||||
* |
||||
* @return RecordingMeeting the recording |
||||
*/ |
||||
public function getRecordings() |
||||
{ |
||||
return RecordingMeeting::fromJson( |
||||
Client::getInstance()->send('GET', 'meetings/'.htmlentities($this->uuid).'/recordings') |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves the instance's participants. |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return ParticipantListItem[] |
||||
*/ |
||||
public function getParticipants() |
||||
{ |
||||
return ParticipantList::loadInstanceParticipants($this->uuid); |
||||
} |
||||
} |
||||
@ -0,0 +1,53 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingInstances. The list of one meeting's ended instances. |
||||
* |
||||
* @see MeetingInstance |
||||
*/ |
||||
class MeetingInstances |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var MeetingInstance[] List of ended meeting instances. */ |
||||
public $meetings; |
||||
|
||||
/** |
||||
* MeetingInstances constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->meetings = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves a meeting's instances. |
||||
* |
||||
* @param int $meetingId |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingInstances the meeting's instances |
||||
*/ |
||||
public static function fromMeetingId($meetingId) |
||||
{ |
||||
return static::fromJson(Client::getInstance()->send('GET', "past_meetings/$meetingId/instances")); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('meetings' === $propertyName) { |
||||
return MeetingInstance::class; |
||||
} |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,58 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingList. Lists Meetings. |
||||
* |
||||
* @see MeetingListItem |
||||
*/ |
||||
class MeetingList |
||||
{ |
||||
use Pagination; |
||||
|
||||
const TYPE_SCHEDULED = 'scheduled'; // all valid past meetings (unexpired), |
||||
// live meetings and upcoming scheduled meetings. |
||||
const TYPE_LIVE = 'live'; // all the ongoing meetings. |
||||
const TYPE_UPCOMING = 'upcoming'; // all upcoming meetings, including live meetings. |
||||
|
||||
/** @var MeetingListItem[] */ |
||||
public $meetings; |
||||
|
||||
/** |
||||
* MeetingList constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->meetings = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all meetings of a type. |
||||
* |
||||
* @param int $type TYPE_SCHEDULED, TYPE_LIVE or TYPE_UPCOMING |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingListItem[] all meetings |
||||
*/ |
||||
public static function loadMeetings($type) |
||||
{ |
||||
return static::loadItems('meetings', 'users/me/meetings', ['type' => $type]); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('meetings' === $propertyName) { |
||||
return MeetingListItem::class; |
||||
} |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingListItem. Item of a list of meetings. |
||||
* |
||||
* @see MeetingList |
||||
*/ |
||||
class MeetingListItem |
||||
{ |
||||
use BaseMeetingTrait; |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string unique meeting instance ID */ |
||||
public $uuid; |
||||
|
||||
/** @var string meeting number */ |
||||
public $id; |
||||
|
||||
/** @var string host Zoom user id */ |
||||
public $host_id; |
||||
|
||||
/** @var string */ |
||||
public $created_at; |
||||
|
||||
/** @var string */ |
||||
public $join_url; |
||||
|
||||
/** @var string truncated to 250 characters */ |
||||
// public $agenda; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,105 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingRegistrant. |
||||
* Structure of the information to send the server in order to register someone to a meeting. |
||||
*/ |
||||
class MeetingRegistrant |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string */ |
||||
public $email; |
||||
|
||||
/** @var string */ |
||||
public $first_name; |
||||
|
||||
/** @var string */ |
||||
public $last_name; |
||||
|
||||
/** @var string */ |
||||
public $address; |
||||
|
||||
/** @var string */ |
||||
public $city; |
||||
|
||||
/** @var string */ |
||||
public $country; |
||||
|
||||
/** @var string */ |
||||
public $zip; |
||||
|
||||
/** @var string */ |
||||
public $state; |
||||
|
||||
/** @var string */ |
||||
public $phone; |
||||
|
||||
/** @var string */ |
||||
public $industry; |
||||
|
||||
/** @var string */ |
||||
public $org; |
||||
|
||||
/** @var string */ |
||||
public $job_title; |
||||
|
||||
/** @var string */ |
||||
public $purchasing_time_frame; |
||||
|
||||
/** @var string */ |
||||
public $role_in_purchase_process; |
||||
|
||||
/** @var string */ |
||||
public $no_of_employees; |
||||
|
||||
/** @var string */ |
||||
public $comments; |
||||
|
||||
/** @var object[] title => value */ |
||||
public $custom_questions; |
||||
|
||||
/** |
||||
* MeetingRegistrant constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->custom_questions = []; |
||||
} |
||||
|
||||
/** |
||||
* @param string $email |
||||
* @param string $firstName |
||||
* @param string $lastName |
||||
* |
||||
* @return MeetingRegistrant |
||||
*/ |
||||
public static function fromEmailAndFirstName($email, $firstName, $lastName = null) |
||||
{ |
||||
$instance = new static(); |
||||
$instance->first_name = $firstName; |
||||
$instance->email = $email; |
||||
if (null !== $lastName) { |
||||
$instance->last_name = $lastName; |
||||
} |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('custom_questions' === $propertyName) { |
||||
return CustomQuestion::class; |
||||
} |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,53 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingRegistrantList. List of meeting registrants. |
||||
* |
||||
* @see MeetingRegistrantListItem |
||||
*/ |
||||
class MeetingRegistrantList |
||||
{ |
||||
use Pagination; |
||||
|
||||
/** @var MeetingRegistrantListItem[] */ |
||||
public $registrants; |
||||
|
||||
/** |
||||
* MeetingRegistrantList constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->registrants = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all registrant for a meeting. |
||||
* |
||||
* @param int $meetingId |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrantListItem[] all registrants of the meeting |
||||
*/ |
||||
public static function loadMeetingRegistrants($meetingId) |
||||
{ |
||||
return static::loadItems('registrants', "meetings/$meetingId/registrants"); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('registrants' === $propertyName) { |
||||
return MeetingRegistrantListItem::class; |
||||
} |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Class MeetingRegistrantListItem. Item in a list of meeting registrants. |
||||
* |
||||
* @see MeetingRegistrantList |
||||
*/ |
||||
class MeetingRegistrantListItem extends MeetingRegistrant |
||||
{ |
||||
/** @var string Registrant ID. */ |
||||
public $id; |
||||
|
||||
/** @var string The status of the registrant's registration. |
||||
* `approved`: User has been successfully approved for the webinar. |
||||
* `pending`: The registration is still pending. |
||||
* `denied`: User has been denied from joining the webinar. |
||||
*/ |
||||
public $status; |
||||
|
||||
/** @var string The time at which the registrant registered. */ |
||||
public $create_time; |
||||
|
||||
/** @var string The URL using which an approved registrant can join the webinar. */ |
||||
public $join_url; |
||||
} |
||||
@ -0,0 +1,143 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingSettings. An instance of this class is included in each Meeting instance. |
||||
*/ |
||||
class MeetingSettings |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
const APPROVAL_TYPE_AUTOMATICALLY_APPROVE = 0; |
||||
const APPROVAL_TYPE_MANUALLY_APPROVE = 1; |
||||
const APPROVAL_TYPE_NO_REGISTRATION_REQUIRED = 2; |
||||
|
||||
const REGISTRATION_TYPE_REGISTER_ONCE_ATTEND_ANY = 1; |
||||
const REGISTRATION_TYPE_REGISTER_EACH = 2; |
||||
const REGISTRATION_TYPE_REGISTER_ONCE_CHOOSE = 3; |
||||
|
||||
/** @var bool Start video when the host joins the meeting */ |
||||
public $host_video; |
||||
|
||||
/** @var bool Start video when participants join the meeting */ |
||||
public $participant_video; |
||||
|
||||
/** @var bool Host meeting in China */ |
||||
public $cn_meeting; |
||||
|
||||
/** @var bool Host meeting in India */ |
||||
public $in_meeting; |
||||
|
||||
/** @var bool Allow participants to join the meeting before the host starts the meeting. |
||||
* Only used for scheduled or recurring meetings. |
||||
*/ |
||||
public $join_before_host; |
||||
|
||||
/** @var bool Mute participants upon entry */ |
||||
public $mute_upon_entry; |
||||
|
||||
/** @var bool Add watermark when viewing a shared screen */ |
||||
public $watermark; |
||||
|
||||
/** @var bool Use a personal meeting ID. |
||||
* Only used for scheduled meetings and recurring meetings with no fixed time. |
||||
*/ |
||||
public $use_pmi; |
||||
|
||||
/** @var int Enable registration and set approval for the registration. |
||||
* Note that this feature requires the host to be of **Licensed** user type. |
||||
* **Registration cannot be enabled for a basic user.** |
||||
*/ |
||||
public $approval_type; |
||||
|
||||
/** @var int Used for recurring meeting with fixed time only. */ |
||||
public $registration_type; |
||||
|
||||
/** @var string either both, telephony or voip */ |
||||
public $audio; |
||||
|
||||
/** @var string either local, cloud or none */ |
||||
public $auto_recording; |
||||
|
||||
/** @var bool @deprecated only signed in users can join this meeting */ |
||||
public $enforce_login; |
||||
|
||||
/** @var string @deprecated only signed in users with specified domains can join meetings */ |
||||
public $enforce_login_domains; |
||||
|
||||
/** @var string Alternative host's emails or IDs: multiple values separated by a comma. */ |
||||
public $alternative_hosts; |
||||
|
||||
/** @var bool Close registration after event date */ |
||||
public $close_registration; |
||||
|
||||
/** @var bool Enable waiting room */ |
||||
public $waiting_room; |
||||
|
||||
/** @var bool undocumented */ |
||||
public $request_permission_to_unmute_participants; |
||||
|
||||
/** @var string[] List of global dial-in countries */ |
||||
public $global_dial_in_countries; |
||||
|
||||
/** @var GlobalDialInNumber[] Global Dial-in Countries/Regions */ |
||||
public $global_dial_in_numbers; |
||||
|
||||
/** @var string Contact name for registration */ |
||||
public $contact_name; |
||||
|
||||
/** @var string Contact email for registration */ |
||||
public $contact_email; |
||||
|
||||
/** @var bool Send confirmation email to registrants upon successful registration */ |
||||
public $registrants_confirmation_email; |
||||
|
||||
/** @var bool Send email notifications to registrants about approval, cancellation, denial of the registration. |
||||
* The value of this field must be set to true in order to use the `registrants_confirmation_email` field. |
||||
*/ |
||||
public $registrants_email_notification; |
||||
|
||||
/** @var bool Only authenticated users can join meetings. */ |
||||
public $meeting_authentication; |
||||
|
||||
/** @var string Meeting authentication option id. */ |
||||
public $authentication_option; |
||||
|
||||
/** @var string |
||||
* @see https://support.zoom.us/hc/en-us/articles/360037117472-Authentication-Profiles-for-Meetings-and-Webinars#h_5c0df2e1-cfd2-469f-bb4a-c77d7c0cca6f |
||||
*/ |
||||
public $authentication_domains; |
||||
|
||||
/** @var string |
||||
* @see https://support.zoom.us/hc/en-us/articles/360037117472-Authentication-Profiles-for-Meetings-and-Webinars#h_5c0df2e1-cfd2-469f-bb4a-c77d7c0cca6f |
||||
*/ |
||||
public $authentication_name; |
||||
|
||||
/** |
||||
* MeetingSettings constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->global_dial_in_countries = []; |
||||
$this->global_dial_in_numbers = []; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('global_dial_in_countries' === $propertyName) { |
||||
return 'string'; |
||||
} |
||||
if ('global_dial_in_numbers' === $propertyName) { |
||||
return GlobalDialInNumber::class; |
||||
} |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,68 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Trait Pagination |
||||
* properties for Pagination objects, which are paginated lists of items, |
||||
* retrieved in chunks from the server over one or several API calls, one per page. |
||||
*/ |
||||
trait Pagination |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var int The number of pages returned for the request made. */ |
||||
public $page_count; |
||||
|
||||
/** @var int The page number of the current results, counting from 1 */ |
||||
public $page_number; |
||||
|
||||
/** @var int The number of records returned with a single API call. Default 30, max 300. */ |
||||
public $page_size; |
||||
|
||||
/** @var int The total number of all the records available across pages. */ |
||||
public $total_records; |
||||
|
||||
/** |
||||
* Retrieves all items from the server, possibly generating several API calls. |
||||
* |
||||
* @param string $arrayPropertyName item array property name |
||||
* @param string $relativePath relative path to pass to Client::send |
||||
* @param array $parameters parameter array to pass to Client::send |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return array united list of items |
||||
*/ |
||||
protected static function loadItems($arrayPropertyName, $relativePath, $parameters = []) |
||||
{ |
||||
$items = []; |
||||
$pageCount = 1; |
||||
$pageSize = 300; |
||||
$totalRecords = 0; |
||||
for ($pageNumber = 1; $pageNumber <= $pageCount; $pageNumber++) { |
||||
$response = static::fromJson( |
||||
Client::getInstance()->send( |
||||
'GET', |
||||
$relativePath, |
||||
array_merge(['page_size' => $pageSize, 'page_number' => $pageNumber], $parameters) |
||||
) |
||||
); |
||||
$items = array_merge($items, $response->$arrayPropertyName); |
||||
if (0 === $totalRecords) { |
||||
$pageCount = $response->page_count; |
||||
$pageSize = $response->page_size; |
||||
$totalRecords = $response->total_records; |
||||
} |
||||
} |
||||
if (count($items) !== $totalRecords) { |
||||
error_log('Zoom announced '.$totalRecords.' records but returned '.count($items)); |
||||
} |
||||
|
||||
return $items; |
||||
} |
||||
} |
||||
@ -0,0 +1,71 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Trait PaginationToken |
||||
* properties for PaginationToken objects, which are paginated lists of items, |
||||
* retrieved in chunks from the server over one or several API calls, one per page. |
||||
*/ |
||||
trait PaginationToken |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var int The number of pages returned for the request made. */ |
||||
public $page_count; |
||||
|
||||
/** @var int The number of records returned within a single API call. Default 30, max 300. */ |
||||
public $page_size; |
||||
|
||||
/** @var int The number of all records available across pages. */ |
||||
public $total_records; |
||||
|
||||
/** @var string The next page token is used to paginate through large result sets. |
||||
* A next page token will be returned whenever the set of available results exceeds the current page size. |
||||
* The expiration period for this token is 15 minutes. |
||||
*/ |
||||
public $next_page_token; |
||||
|
||||
/** |
||||
* Retrieves all items from the server, possibly generating several API calls. |
||||
* |
||||
* @param string $arrayPropertyName item array property name |
||||
* @param string $relativePath relative path to pass to Client::send |
||||
* @param array $parameters parameter array to pass to Client::send |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return array united list of items |
||||
*/ |
||||
protected static function loadItems($arrayPropertyName, $relativePath, $parameters = []) |
||||
{ |
||||
$items = []; |
||||
$pageSize = 300; |
||||
$totalRecords = 0; |
||||
$nextPageToken = ''; |
||||
do { |
||||
$response = static::fromJson( |
||||
Client::getInstance()->send( |
||||
'GET', |
||||
$relativePath, |
||||
array_merge(['page_size' => $pageSize, 'next_page_token' => $nextPageToken], $parameters) |
||||
) |
||||
); |
||||
$items = array_merge($items, $response->$arrayPropertyName); |
||||
$nextPageToken = $response->next_page_token; |
||||
if (0 === $totalRecords) { |
||||
$pageSize = $response->page_size; |
||||
$totalRecords = $response->total_records; |
||||
} |
||||
} while (!empty($nextPagetoken)); |
||||
if (count($items) !== $totalRecords) { |
||||
error_log('Zoom announced '.$totalRecords.' records but returned '.count($items)); |
||||
} |
||||
|
||||
return $items; |
||||
} |
||||
} |
||||
@ -0,0 +1,57 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class ParticipantList |
||||
* List of past meeting instance participants. |
||||
* |
||||
* @see ParticipantListItem; |
||||
*/ |
||||
class ParticipantList |
||||
{ |
||||
use PaginationToken; |
||||
|
||||
/** @var ParticipantListItem[] */ |
||||
public $participants; |
||||
|
||||
/** |
||||
* ParticipantList constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->participants = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves a meeting instance's participants. |
||||
* |
||||
* @param string $instanceUUID |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return ParticipantListItem[] participants |
||||
*/ |
||||
public static function loadInstanceParticipants($instanceUUID) |
||||
{ |
||||
return static::loadItems( |
||||
'participants', |
||||
'past_meetings/'.htmlentities($instanceUUID).'/participants' |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('participants' === $propertyName) { |
||||
return ParticipantListItem::class; |
||||
} |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,22 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Class ParticipantListItem. Item in a list of past meeting instance participants. |
||||
* |
||||
* @see ParticipantList |
||||
*/ |
||||
class ParticipantListItem |
||||
{ |
||||
/** @var string participant UUID */ |
||||
public $id; |
||||
|
||||
/** @var string display name */ |
||||
public $name; |
||||
|
||||
/** @var string Email address of the user; will be returned if the user logged into Zoom to join the meeting. */ |
||||
public $user_email; |
||||
} |
||||
@ -0,0 +1,74 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class PastMeeting. |
||||
* A past meeting, really a past meeting instance, as returned from the server. |
||||
* |
||||
* Each past meeting instance is identified by its own UUID. |
||||
* Many past meeting instances can be part of the same meeting, identified by property 'id'. |
||||
* Each instance has its own start time, participants and recording files. |
||||
*/ |
||||
class PastMeeting extends Meeting |
||||
{ |
||||
/** @var string unique meeting instance ID */ |
||||
public $uuid; |
||||
|
||||
/** @var string meeting number */ |
||||
public $id; |
||||
|
||||
/** @var string host Zoom user id */ |
||||
public $host_id; |
||||
|
||||
/** @var string user display name */ |
||||
public $user_name; |
||||
|
||||
/** @var string */ |
||||
public $user_email; |
||||
|
||||
/** @var string "yyyy-MM-dd'T'HH:mm:ss'Z'" (GMT) */ |
||||
public $start_time; |
||||
|
||||
/** @var string "yyyy-MM-dd'T'HH:mm:ss'Z'" (GMT) */ |
||||
public $end_time; |
||||
|
||||
/** @var int sum of meeting minutes from all participants in the meeting. */ |
||||
public $total_minutes; |
||||
|
||||
/** @var int number of meeting participants */ |
||||
public $participants_count; |
||||
|
||||
/** @var string undocumented */ |
||||
public $dept; |
||||
|
||||
/** |
||||
* Retrieves a past meeting instance from its identifier. |
||||
* |
||||
* @param string $uuid |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return PastMeeting the past meeting |
||||
*/ |
||||
public static function fromUUID($uuid) |
||||
{ |
||||
return static::fromJson(Client::getInstance()->send('GET', 'past_meetings/'.htmlentities($uuid))); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves information on participants from a past meeting instance. |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return ParticipantListItem[] participants |
||||
*/ |
||||
public function getParticipants() |
||||
{ |
||||
return ParticipantList::loadInstanceParticipants($this->uuid); |
||||
} |
||||
} |
||||
@ -0,0 +1,115 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class RecordingFile. A video, audio or text file, part of a past meeting instance recording. |
||||
* |
||||
* @see RecordingMeeting |
||||
*/ |
||||
class RecordingFile |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string The recording file ID. Included in the response of general query. */ |
||||
public $id; |
||||
|
||||
/** @var string The meeting ID. */ |
||||
public $meeting_id; |
||||
|
||||
/** @var string The recording start time. */ |
||||
public $recording_start; |
||||
|
||||
/** @var string The recording end time. Response in general query. */ |
||||
public $recording_end; |
||||
|
||||
/** @var string The recording file type. The value of this field could be one of the following:<br> |
||||
* `MP4`: Video file of the recording.<br> |
||||
* `M4A` Audio-only file of the recording.<br> |
||||
* `TIMELINE`: Timestamp file of the recording. |
||||
* To get a timeline file, the "Add a timestamp to the recording" setting must be enabled in the recording settings |
||||
* (https://support.zoom.us/hc/en-us/articles/203741855-Cloud-recording#h_3f14c3a4-d16b-4a3c-bbe5-ef7d24500048). |
||||
* The time will display in the host's timezone, set on their Zoom profile. |
||||
* `TRANSCRIPT`: Transcription file of the recording. |
||||
* `CHAT`: A TXT file containing in-meeting chat messages that were sent during the meeting. |
||||
* `CC`: File containing closed captions of the recording. |
||||
* A recording file object with file type of either `CC` or `TIMELINE` **does not have** the following properties: |
||||
* `id`, `status`, `file_size`, `recording_type`, and `play_url`. |
||||
*/ |
||||
public $file_type; |
||||
|
||||
/** @var int The recording file size. */ |
||||
public $file_size; |
||||
|
||||
/** @var string The URL using which a recording file can be played. */ |
||||
public $play_url; |
||||
|
||||
/** @var string The URL using which the recording file can be downloaded. |
||||
* To access a private or password protected cloud recording, you must use a [Zoom JWT App Type] |
||||
* (https://marketplace.zoom.us/docs/guides/getting-started/app-types/create-jwt-app). |
||||
* Use the generated JWT token as the value of the `access_token` query parameter |
||||
* and include this query parameter at the end of the URL as shown in the example. |
||||
* Example: `https://api.zoom.us/recording/download/{{ Download Path }}?access_token={{ JWT Token }}` |
||||
*/ |
||||
public $download_url; |
||||
|
||||
/** @var string The recording status. "completed". */ |
||||
public $status; |
||||
|
||||
/** @var string The time at which recording was deleted. Returned in the response only for trash query. */ |
||||
public $deleted_time; |
||||
|
||||
/** @var string The recording type. The value of this field can be one of the following: |
||||
* `shared_screen_with_speaker_view(CC)` |
||||
* `shared_screen_with_speaker_view` |
||||
* `shared_screen_with_gallery_view` |
||||
* `speaker_view` |
||||
* `gallery_view` |
||||
* `shared_screen` |
||||
* `audio_only` |
||||
* `audio_transcript` |
||||
* `chat_file` |
||||
* `TIMELINE` |
||||
*/ |
||||
public $recording_type; |
||||
|
||||
/** |
||||
* Builds the recording file download URL with the access_token query parameter. |
||||
* |
||||
* @see RecordingFile::$download_url |
||||
* |
||||
* @param string $token |
||||
* |
||||
* @return string full URL |
||||
*/ |
||||
public function getFullDownloadURL($token) |
||||
{ |
||||
return $this->download_url.'?access_token='.$token; |
||||
} |
||||
|
||||
/** |
||||
* Deletes the file. |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function delete() |
||||
{ |
||||
Client::getInstance()->send( |
||||
'DELETE', |
||||
"/meetings/$this->meeting_id/recordings/$this->id", |
||||
['action' => 'delete'] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,65 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use DateTime; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class RecordingList. A list of past meeting instance recordings generated between two dates. |
||||
* |
||||
* @see RecordingMeeting |
||||
*/ |
||||
class RecordingList |
||||
{ |
||||
use PaginationToken; |
||||
|
||||
/** @var string Start Date */ |
||||
public $from; |
||||
|
||||
/** @var string End Date */ |
||||
public $to; |
||||
|
||||
/** @var RecordingMeeting[] List of recordings */ |
||||
public $meetings; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->meetings = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all recordings from a period of time. |
||||
* |
||||
* @param DateTime $startDate first day of the period |
||||
* @param DateTime $endDate last day of the period |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return RecordingMeeting[] all recordings from that period |
||||
*/ |
||||
public static function loadPeriodRecordings($startDate, $endDate) |
||||
{ |
||||
return static::loadItems( |
||||
'meetings', |
||||
'users/me/recordings', |
||||
[ |
||||
'from' => $startDate->format('Y-m-d'), |
||||
'to' => $endDate->format('Y-m-d'), |
||||
] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('meetings' === $propertyName) { |
||||
return RecordingMeeting::class; |
||||
} |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,95 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class RecordingMeeting. |
||||
* A meeting instance can be recorded, hence creating an instance of this class. |
||||
* Contains a list of recording files. |
||||
* |
||||
* @see PastMeeting |
||||
* @see RecordingFile |
||||
*/ |
||||
class RecordingMeeting |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string Unique Meeting Identifier. Each instance of the meeting will have its own UUID. */ |
||||
public $uuid; |
||||
|
||||
/** @var string Meeting ID - also known as the meeting number. */ |
||||
public $id; |
||||
|
||||
/** @var string Unique Identifier of the user account. */ |
||||
public $account_id; |
||||
|
||||
/** @var string ID of the user set as host of meeting. */ |
||||
public $host_id; |
||||
|
||||
/** @var string Meeting topic. */ |
||||
public $topic; |
||||
|
||||
/** @var int undocumented */ |
||||
public $type; |
||||
|
||||
/** @var string The time at which the meeting started. */ |
||||
public $start_time; |
||||
|
||||
/** @var string undocumented */ |
||||
public $timezone; |
||||
|
||||
/** @var int Meeting duration. */ |
||||
public $duration; |
||||
|
||||
/** @var string Total size of the recording. */ |
||||
public $total_size; |
||||
|
||||
/** @var string Number of recording files returned in the response of this API call. */ |
||||
public $recording_count; |
||||
|
||||
/** @var string undocumented */ |
||||
public $share_url; |
||||
|
||||
/** @var string */ |
||||
public $password; |
||||
|
||||
/** @var RecordingFile[] List of recording file. */ |
||||
public $recording_files; |
||||
|
||||
/** |
||||
* RecordingMeeting constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->recording_files = []; |
||||
} |
||||
|
||||
/** |
||||
* Deletes the recording on the server. |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function delete() |
||||
{ |
||||
Client::getInstance()->send( |
||||
'DELETE', |
||||
'meetings/'.htmlentities($this->uuid).'/recordings', |
||||
['action' => 'delete'] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('recording_files' === $propertyName) { |
||||
return RecordingFile::class; |
||||
} |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class TrackingField. Instances of this class can be listed in a meeting object. |
||||
*/ |
||||
class TrackingField |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string Tracking fields type */ |
||||
public $field; |
||||
|
||||
/** @var string Tracking fields value */ |
||||
public $value; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,204 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\Session; |
||||
use Chamilo\CourseBundle\Entity\CGroupInfo; |
||||
use Chamilo\PageBundle\Entity\User; |
||||
use DateTime; |
||||
use Doctrine\Common\Collections\ArrayCollection; |
||||
use Doctrine\Common\Collections\Collection; |
||||
use Doctrine\Common\Collections\Criteria; |
||||
use Doctrine\ORM\EntityRepository; |
||||
use Doctrine\ORM\QueryBuilder; |
||||
|
||||
/** |
||||
* Class MeetingRepository. |
||||
*/ |
||||
class MeetingRepository extends EntityRepository |
||||
{ |
||||
/** |
||||
* Retrieves information about meetings having a start_time between two dates. |
||||
* |
||||
* @param DateTime $startDate |
||||
* @param DateTime $endDate |
||||
* |
||||
* @return Meeting[] |
||||
*/ |
||||
public function periodMeetings($startDate, $endDate) |
||||
{ |
||||
$matching = []; |
||||
$all = $this->findAll(); |
||||
foreach ($all as $candidate) { |
||||
if ($candidate->startDateTime >= $startDate && $candidate->startDateTime <= $endDate) { |
||||
$matching[] = $candidate; |
||||
} |
||||
} |
||||
|
||||
return $matching; |
||||
} |
||||
|
||||
/** |
||||
* @return ArrayCollection|Collection|Meeting[] |
||||
*/ |
||||
public function globalMeetings() |
||||
{ |
||||
return $this->matching( |
||||
Criteria::create()->where( |
||||
Criteria::expr()->andX( |
||||
Criteria::expr()->eq('course', null), |
||||
Criteria::expr()->eq('user', null) |
||||
) |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @return ArrayCollection|Collection|Meeting[] |
||||
*/ |
||||
public function unfinishedGlobalMeetings() |
||||
{ |
||||
return $this->globalMeetings()->filter( |
||||
function ($meeting) { |
||||
return 'finished' !== $meeting->getMeetingInfoGet()->status; |
||||
} |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Returns either a user's meetings or all user meetings. |
||||
* |
||||
* @param User|null $user |
||||
* |
||||
* @return QueryBuilder |
||||
*/ |
||||
public function userMeetings($user = null) |
||||
{ |
||||
$qb = $this->createQueryBuilder('m'); |
||||
$qb |
||||
->select('m') |
||||
->leftJoin('m.registrants', 'r'); |
||||
|
||||
//$qb->select('m'); |
||||
/*$criteria = Criteria::create()->where( |
||||
Criteria::expr()->andX( |
||||
Criteria::expr()->isNull('course'), |
||||
Criteria::expr()->orX( |
||||
Criteria::expr()->isNull('user'), |
||||
Criteria::expr()->eq('user', $user) |
||||
) |
||||
));*/ |
||||
|
||||
/*$qb->where(Criteria::expr()->andX( |
||||
Criteria::expr()->isNull('course'), |
||||
Criteria::expr()->orX( |
||||
Criteria::expr()->isNull('user'), |
||||
Criteria::expr()->eq('user', $user) |
||||
) |
||||
));*/ |
||||
|
||||
$qb |
||||
->andWhere('m.course IS NULL') |
||||
->andWhere('m.user IS NULL OR m.user = :user OR r.user = :user'); |
||||
|
||||
$qb->setParameters(['user' => $user]); |
||||
|
||||
return $qb; |
||||
|
||||
/*return $this->matching( |
||||
, |
||||
Criteria::expr()->andX( |
||||
Criteria::expr()->eq('registrants', null), |
||||
Criteria::expr()->orX( |
||||
Criteria::expr()->eq('user', null), |
||||
Criteria::expr()->eq('user', $user) |
||||
) |
||||
) |
||||
) |
||||
);*/ |
||||
|
||||
/*return $this->matching( |
||||
Criteria::create()->where( |
||||
Criteria::expr()->andX( |
||||
Criteria::expr()->eq('course', null), |
||||
Criteria::expr()->orX( |
||||
Criteria::expr()->eq('user', null), |
||||
Criteria::expr()->eq('user', $user) |
||||
) |
||||
) |
||||
) |
||||
);*/ |
||||
} |
||||
|
||||
/** |
||||
* @param User|null $user |
||||
* |
||||
* @return Meeting[] |
||||
*/ |
||||
public function unfinishedUserMeetings($user = null) |
||||
{ |
||||
/*return $this->userMeetings($user)->filter( |
||||
function ($meeting) { |
||||
return 'finished' !== $meeting->getMeetingInfoGet()->status; |
||||
} |
||||
);*/ |
||||
|
||||
$results = @$this->userMeetings($user)->getQuery()->getResult(); |
||||
$list = []; |
||||
foreach ($results as $meeting) { |
||||
if ('finished' === $meeting->getMeetingInfoGet()->status) { |
||||
$list[] = $meeting; |
||||
} |
||||
} |
||||
|
||||
return $list; |
||||
} |
||||
|
||||
/** |
||||
* @param DateTime $start |
||||
* @param DateTime $end |
||||
* @param User $user |
||||
* |
||||
* @return ArrayCollection|Collection|Meeting[] |
||||
*/ |
||||
public function periodUserMeetings($start, $end, $user = null) |
||||
{ |
||||
/*return $this->userMeetings($user)->filter( |
||||
function ($meeting) use ($start, $end) { |
||||
return $meeting->startDateTime >= $start && $meeting->startDateTime <= $end; |
||||
} |
||||
);*/ |
||||
|
||||
$results = @$this->userMeetings($user)->getQuery()->getResult(); |
||||
$list = []; |
||||
if ($results) { |
||||
foreach ($results as $meeting) { |
||||
if ($meeting->startDateTime >= $start && $meeting->startDateTime <= $end) { |
||||
$list[] = $meeting; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return $list; |
||||
} |
||||
|
||||
/** |
||||
* Returns either a course's meetings or all course meetings. |
||||
* |
||||
* @return ArrayCollection|Collection|Meeting[] |
||||
*/ |
||||
public function courseMeetings(Course $course, CGroupInfo $group = null, Session $session = null) |
||||
{ |
||||
return $this->matching( |
||||
Criteria::create()->where( |
||||
Criteria::expr()->andX( |
||||
Criteria::expr()->eq('group', $group), |
||||
Criteria::expr()->eq('course', $course), |
||||
Criteria::expr()->eq('session', $session) |
||||
) |
||||
) |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,65 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\ClassificationBundle\Entity\Collection; |
||||
use Chamilo\UserBundle\Entity\User; |
||||
use DateTime; |
||||
use Doctrine\Common\Collections\ArrayCollection; |
||||
use Doctrine\ORM\EntityRepository; |
||||
|
||||
/** |
||||
* Class RecordingRepository. |
||||
*/ |
||||
class RecordingRepository extends EntityRepository |
||||
{ |
||||
public function getPeriodRecordings($startDate, $endDate) |
||||
{ |
||||
$matching = []; |
||||
$all = $this->findAll(); |
||||
foreach ($all as $candidate) { |
||||
if ($candidate->startDateTime >= $startDate && $candidate->startDateTime <= $endDate) { |
||||
$matching[] = $candidate; |
||||
} |
||||
} |
||||
|
||||
return $matching; |
||||
} |
||||
|
||||
/** |
||||
* Returns a user's meeting recordings. |
||||
* |
||||
* @param User $user |
||||
* |
||||
* @return ArrayCollection|Collection|Recording[] |
||||
*/ |
||||
/*public function userRecordings($user) |
||||
{ |
||||
return $this->matching( |
||||
Criteria::create()->where( |
||||
Criteria::expr()->in( |
||||
'meeting', |
||||
$this->getEntityManager()->getRepository(Meeting::class)->userMeetings($user)->toArray() |
||||
) |
||||
) |
||||
); |
||||
}*/ |
||||
|
||||
/** |
||||
* @param DateTime $start |
||||
* @param DateTime $end |
||||
* @param User $user |
||||
* |
||||
* @return ArrayCollection|Recording[] |
||||
*/ |
||||
/*public function getPeriodUserRecordings($start, $end, $user = null) |
||||
{ |
||||
return $this->userRecordings($user)->filter( |
||||
function ($meeting) use ($start, $end) { |
||||
return $meeting->startDateTime >= $start && $meeting->startDateTime <= $end; |
||||
} |
||||
); |
||||
}*/ |
||||
} |
||||
@ -0,0 +1,33 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\UserBundle\Entity\User; |
||||
use DateInterval; |
||||
use DateTime; |
||||
use Doctrine\ORM\EntityRepository; |
||||
|
||||
/** |
||||
* Class RegistrantEntityRepository. |
||||
*/ |
||||
class RegistrantRepository extends EntityRepository |
||||
{ |
||||
/** |
||||
* Returns the upcoming meeting registrations for the given user. |
||||
* |
||||
* @param User $user |
||||
* |
||||
* @return array|Registrant[] |
||||
*/ |
||||
public function meetingsComingSoonRegistrationsForUser($user) |
||||
{ |
||||
$start = new DateTime(); |
||||
$end = new DateTime(); |
||||
$end->add(new DateInterval('P7D')); |
||||
$meetings = $this->getEntityManager()->getRepository(Meeting::class)->periodMeetings($start, $end); |
||||
|
||||
return $this->findBy(['meeting' => $meetings, 'user' => $user]); |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,94 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\Meeting; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
$meetingId = isset($_REQUEST['meetingId']) ? (int) $_REQUEST['meetingId'] : 0; |
||||
if (empty($meetingId)) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
/** @var Meeting $meeting */ |
||||
$meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $meetingId]); |
||||
|
||||
if (null === $meeting) { |
||||
api_not_allowed(true, $plugin->get_lang('MeetingNotFound')); |
||||
} |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
$returnURL = 'meetings.php'; |
||||
$urlExtra = ''; |
||||
if ($meeting->isCourseMeeting()) { |
||||
api_protect_course_script(true); |
||||
$this_section = SECTION_COURSES; |
||||
$urlExtra = api_get_cidreq(); |
||||
$returnURL = 'start.php?'.$urlExtra; |
||||
|
||||
if (api_is_in_group()) { |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.$urlExtra, |
||||
'name' => get_lang('Groups'), |
||||
]; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.$urlExtra, |
||||
'name' => get_lang('GroupSpace').' '.$meeting->getGroup()->getName(), |
||||
]; |
||||
} |
||||
} |
||||
|
||||
$logInfo = [ |
||||
'tool' => 'Videoconference Zoom', |
||||
]; |
||||
Event::registerLog($logInfo); |
||||
|
||||
$interbreadcrumb[] = [ |
||||
'url' => $returnURL, |
||||
'name' => $plugin->get_lang('ZoomVideoConferences'), |
||||
]; |
||||
|
||||
$tpl = new Template($meeting->getMeetingId()); |
||||
|
||||
if ($plugin->userIsConferenceManager($meeting)) { |
||||
// user can edit, start and delete meeting |
||||
$tpl->assign('isConferenceManager', true); |
||||
$tpl->assign('editMeetingForm', $plugin->getEditMeetingForm($meeting)->returnForm()); |
||||
$tpl->assign('deleteMeetingForm', $plugin->getDeleteMeetingForm($meeting, $returnURL)->returnForm()); |
||||
|
||||
if (false === $meeting->isGlobalMeeting() && false == $meeting->isCourseMeeting()) { |
||||
if ('true' === $plugin->get('enableParticipantRegistration') && $meeting->requiresRegistration()) { |
||||
$tpl->assign('registerParticipantForm', $plugin->getRegisterParticipantForm($meeting)->returnForm()); |
||||
$tpl->assign('registrants', $meeting->getRegistrants()); |
||||
} |
||||
} |
||||
|
||||
if (ZoomPlugin::RECORDING_TYPE_NONE !== $plugin->getRecordingSetting() && |
||||
$meeting->hasCloudAutoRecordingEnabled() |
||||
) { |
||||
$tpl->assign('fileForm', $plugin->getFileForm($meeting, $returnURL)->returnForm()); |
||||
$tpl->assign('recordings', $meeting->getRecordings()); |
||||
} |
||||
} elseif ($meeting->requiresRegistration()) { |
||||
$userId = api_get_user_id(); |
||||
try { |
||||
foreach ($meeting->getRegistrants() as $registrant) { |
||||
if ($registrant->getUser()->getId() == $userId) { |
||||
$tpl->assign('currentUserJoinURL', $registrant->getJoinUrl()); |
||||
break; |
||||
} |
||||
} |
||||
} catch (Exception $exception) { |
||||
Display::addFlash( |
||||
Display::return_message($exception->getMessage(), 'error') |
||||
); |
||||
} |
||||
} |
||||
|
||||
$tpl->assign('actions', $plugin->getToolbar()); |
||||
$tpl->assign('meeting', $meeting); |
||||
$tpl->assign('url_extra', $urlExtra); |
||||
$tpl->assign('content', $tpl->fetch('zoom/view/meeting.tpl')); |
||||
$tpl->display_one_col_template(); |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
$cidReset = true; |
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
if (!ZoomPlugin::currentUserCanJoinGlobalMeeting()) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
$user = api_get_user_entity(api_get_user_id()); |
||||
|
||||
$form = $plugin->getAdminSearchForm(); |
||||
$startDate = new DateTime($form->getElement('start')->getValue()); |
||||
$endDate = new DateTime($form->getElement('end')->getValue()); |
||||
$scheduleForm = $plugin->getScheduleMeetingForm($user); |
||||
$tpl = new Template(); |
||||
$tpl->assign('meetings', $plugin->getMeetingRepository()->periodUserMeetings($startDate, $endDate, $user)); |
||||
$tpl->assign('allow_recording', $plugin->hasRecordingAvailable()); |
||||
$tpl->assign('actions', $plugin->getToolbar()); |
||||
$tpl->assign('search_form', $form->returnForm()); |
||||
$tpl->assign('schedule_form', $scheduleForm->returnForm()); |
||||
$tpl->assign('content', $tpl->fetch('zoom/view/meetings.tpl')); |
||||
$tpl->display_one_col_template(); |
||||
@ -0,0 +1,4 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
$plugin_info = ZoomPlugin::create()->get_info(); |
||||
@ -0,0 +1,118 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_course_script(true); |
||||
|
||||
$this_section = SECTION_COURSES; |
||||
$logInfo = [ |
||||
'tool' => 'Videoconference Zoom', |
||||
]; |
||||
Event::registerLog($logInfo); |
||||
|
||||
$course = api_get_course_entity(); |
||||
if (null === $course) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$group = api_get_group_entity(); |
||||
$session = api_get_session_entity(); |
||||
$plugin = ZoomPlugin::create(); |
||||
|
||||
if (null !== $group) { |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(), |
||||
'name' => get_lang('Groups'), |
||||
]; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(), |
||||
'name' => get_lang('GroupSpace').' '.$group->getName(), |
||||
]; |
||||
} |
||||
|
||||
$url = api_get_self().'?'.api_get_cidreq(true, false).'&gidReq='; |
||||
$htmlHeadXtra[] = '<script> |
||||
$(function() { |
||||
$("#group_select").on("change", function() { |
||||
var groupId = $(this).find("option:selected").val(); |
||||
var url = "'.$url.'"; |
||||
window.location.replace(url+groupId); |
||||
}); |
||||
}); |
||||
</script>'; |
||||
|
||||
$tool_name = $plugin->get_lang('ZoomVideoConferences'); |
||||
$tpl = new Template($tool_name); |
||||
|
||||
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; |
||||
|
||||
$isManager = $plugin->userIsCourseConferenceManager(); |
||||
if ($isManager) { |
||||
$groupId = api_get_group_id(); |
||||
$groups = GroupManager::get_groups(); |
||||
if (!empty($groups)) { |
||||
$form = new FormValidator('group_filter'); |
||||
$groupList[0] = get_lang('Select'); |
||||
foreach ($groups as $groupData) { |
||||
$itemGroupId = $groupData['iid']; |
||||
/*if (isset($meetingsGroup[$itemGroupId]) && $meetingsGroup[$itemGroupId] == 1) { |
||||
$groupData['name'] .= ' ('.get_lang('Active').')'; |
||||
}*/ |
||||
$groupList[$itemGroupId] = $groupData['name']; |
||||
} |
||||
$form->addSelect('group_id', get_lang('Groups'), $groupList, ['id' => 'group_select']); |
||||
$form->setDefaults(['group_id' => $groupId]); |
||||
$formToString = $form->returnForm(); |
||||
|
||||
$tpl->assign('group_form', $formToString); |
||||
} |
||||
|
||||
switch ($action) { |
||||
case 'delete': |
||||
$meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $_REQUEST['meetingId']]); |
||||
if ($meeting && $meeting->isCourseMeeting()) { |
||||
$plugin->deleteMeeting($meeting, api_get_self().'?'.api_get_cidreq()); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
$user = api_get_user_entity(api_get_user_id()); |
||||
|
||||
$tpl->assign( |
||||
'instant_meeting_form', |
||||
$plugin->getCreateInstantMeetingForm( |
||||
$user, |
||||
$course, |
||||
$group, |
||||
$session |
||||
)->returnForm() |
||||
); |
||||
$tpl->assign( |
||||
'schedule_meeting_form', |
||||
$plugin->getScheduleMeetingForm( |
||||
$user, |
||||
$course, |
||||
$group, |
||||
$session |
||||
)->returnForm() |
||||
); |
||||
} |
||||
|
||||
try { |
||||
$tpl->assign( |
||||
'meetings', |
||||
$plugin->getMeetingRepository()->courseMeetings($course, $group, $session) |
||||
); |
||||
} catch (Exception $exception) { |
||||
Display::addFlash( |
||||
Display::return_message('Could not retrieve scheduled meeting list: '.$exception->getMessage(), 'error') |
||||
); |
||||
} |
||||
|
||||
$tpl->assign('is_manager', $isManager); |
||||
$tpl->assign('content', $tpl->fetch('zoom/view/start.tpl')); |
||||
$tpl->display_one_col_template(); |
||||
@ -0,0 +1,8 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
if (!api_is_platform_admin()) { |
||||
die('You must have admin permissions to uninstall plugins'); |
||||
} |
||||
|
||||
ZoomPlugin::create()->uninstall(); |
||||
@ -0,0 +1,57 @@ |
||||
<h4> |
||||
{{ meeting.typeName }} {{ meeting.meetingId }} |
||||
</h4> |
||||
|
||||
<a class="btn btn-primary" href="meeting.php?meetingId={{ meeting.meetingId }}&{{ url_extra }}"> |
||||
{{ 'Edit'|get_lang }} |
||||
</a> |
||||
|
||||
<table class="table"> |
||||
<thead> |
||||
<tr> |
||||
<th>{{ 'Type'|get_lang }}</th> |
||||
<th>{{ 'Action'|get_plugin_lang('ZoomPlugin') }}</th> |
||||
{# <th>{{ 'User'|get_lang }}</th>#} |
||||
<th>{{ 'Date'|get_lang }}</th> |
||||
<th>{{ 'Details'|get_lang }} </th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{% for activity in meeting.activities %} |
||||
<tr> |
||||
<td> |
||||
{{ activity.type }} |
||||
</td> |
||||
<td> |
||||
{{ activity.name }} |
||||
</td> |
||||
<td> |
||||
{{ activity.createdAt | api_convert_and_format_date(3)}} |
||||
</td> |
||||
{# <td>#} |
||||
{# {% if _u.is_admin %}#} |
||||
{# <a href="{{ _p.web_main }}admin/user_information.php?user_id={{ activity.user.id }}" >#} |
||||
{# {{ activity.user.firstname }} {{ activity.user.lastname }} ({{ activity.user.username }})#} |
||||
{# </a>#} |
||||
{# {% else %}#} |
||||
{# {{ activity.user.firstname }} {{ activity.user.lastname }} ({{ activity.user.username }})#} |
||||
{# {% endif %}#} |
||||
{# </td>#} |
||||
<td> |
||||
{% if activity.eventDecoded.registrant %} |
||||
{{ 'User' | get_lang }} : |
||||
{{ activity.eventDecoded.registrant.first_name }} - |
||||
{{ activity.eventDecoded.registrant.last_name }} - |
||||
{{ activity.eventDecoded.registrant.email }} - |
||||
{{ activity.eventDecoded.registrant.status }} |
||||
{% endif %} |
||||
|
||||
{% if activity.eventDecoded.participant %} |
||||
{{ 'User' | get_lang }} : |
||||
{{ activity.eventDecoded.participant.user_name }} |
||||
{% endif %} |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
</table> |
||||
@ -0,0 +1,116 @@ |
||||
<h4> |
||||
{{ meeting.typeName }} {{ meeting.meetingId }} ({{ meeting.meetingInfoGet.status }}) |
||||
</h4> |
||||
|
||||
<div class="btn-group" role="group"> |
||||
|
||||
{% if meeting.meetingInfoGet.status != 'finished' %} |
||||
<a class="btn btn-primary" href="join_meeting.php?meetingId={{ meeting.meetingId }}&{{ url_extra }}"> |
||||
{{ 'ViewMeeting'|get_plugin_lang('ZoomPlugin') }} |
||||
</a> |
||||
{% endif %} |
||||
|
||||
{% if isConferenceManager %} |
||||
{% if meeting.status == 'waiting' %} |
||||
<a class="btn btn-primary" href="{{ meeting.meetingInfoGet.start_url }}" target="_blank"> |
||||
{{ 'StartMeeting'|get_plugin_lang('ZoomPlugin') }} |
||||
</a> |
||||
{% endif %} |
||||
|
||||
<a class="btn btn-default" href="activity.php?meetingId={{ meeting.meetingId }}&{{ url_extra }}"> |
||||
{{ 'Activity'|get_plugin_lang('ZoomPlugin') }} |
||||
</a> |
||||
{% endif %} |
||||
</div> |
||||
|
||||
{% if isConferenceManager %} |
||||
<br /> |
||||
<br /> |
||||
<div class="panel panel-default conference"> |
||||
<div class="panel-body"> |
||||
<div class="share"> |
||||
{{ 'JoinURLToSendToParticipants'| get_plugin_lang('ZoomPlugin') }} |
||||
</div> |
||||
<div class="form-inline"> |
||||
<div class="form-group"> |
||||
<input id="share_button_flash" type="text" |
||||
style="width:460px" |
||||
class="form-control" readonly |
||||
value="{{ _p.web }}plugin/zoom/join_meeting.php?meetingId={{ meeting.meetingId }}&{{ url_extra }}" |
||||
> |
||||
<button onclick="copyTextToClipBoard('share_button_flash');" class="btn btn-default"> |
||||
<span class="fa fa-copy"></span> {{ 'CopyTextToClipboard' | get_lang }} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{% endif %} |
||||
|
||||
{% if currentUserJoinURL %} |
||||
{#<p>#} |
||||
{# <a href="{{ currentUserJoinURL }}" target="_blank">#} |
||||
{# {{ 'JoinMeeting'|get_plugin_lang('ZoomPlugin') }}#} |
||||
{# </a>#} |
||||
{#</p>#} |
||||
{% endif %} |
||||
|
||||
{% if isConferenceManager %} |
||||
{{ editMeetingForm }} |
||||
{{ deleteMeetingForm }} |
||||
{{ registerParticipantForm }} |
||||
{{ fileForm }} |
||||
|
||||
{# {% if registrants and meeting.meetingInfoGet.settings.approval_type != 2 %}#} |
||||
{% if registrants.count > 0 %} |
||||
<script> |
||||
function copyJoinURL(event, url) { |
||||
event.target.textContent = '{{ 'CopyingJoinURL'|get_plugin_lang('ZoomPlugin')|escape }}'; |
||||
navigator.clipboard.writeText(url).then( |
||||
function() { |
||||
event.target.textContent = '{{ 'JoinURLCopied'|get_plugin_lang('ZoomPlugin')|escape }}'; |
||||
}, function() { |
||||
event.target.textContent = '{{ 'CouldNotCopyJoinURL'|get_plugin_lang('ZoomPlugin')|escape }}' + ' ' + url; |
||||
} |
||||
); |
||||
} |
||||
</script> |
||||
<h3>{{ 'Users' | get_lang }}</h3> |
||||
<br /> |
||||
<table class="table"> |
||||
{% for registrant in registrants %} |
||||
<tr> |
||||
<td> |
||||
{{ registrant.fullName }} |
||||
</td> |
||||
<td> |
||||
{# {% if registrant.joinUrl %}#} |
||||
{# <a class="btn btn-primary" onclick="copyJoinURL(event, '{{ registrant.joinUrl }}')">#} |
||||
{# {{ 'CopyJoinAsURL'|get_plugin_lang('ZoomPlugin') }}#} |
||||
{# </a>#} |
||||
{# {% else %}#} |
||||
{# <a class="btn btn-primary disabled" >#} |
||||
{# {{ 'JoinURLNotAvailable'|get_plugin_lang('ZoomPlugin') }}#} |
||||
{# </a>#} |
||||
{# {% endif %}#} |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</table> |
||||
{% endif %} |
||||
{% else %} |
||||
<h2>{{ meeting.meetingInfoGet.topic }}</h2> |
||||
{% if meeting.meetingInfoGet.agenda %} |
||||
<blockquote>{{ meeting.meetingInfoGet.agenda| nl2br }}</blockquote> |
||||
{% endif %} |
||||
|
||||
{% if meeting.meetingInfoGet.type == 2 or meeting.meetingInfoGet.type == 8 %} |
||||
<dl class="meeting_properties"> |
||||
<dt>{{ 'StartTime'|get_lang }}</dt> |
||||
<dd>{{ meeting.formattedStartTime }}</dd> |
||||
|
||||
<dt>{{ 'Duration'|get_lang }}</dt> |
||||
<dd>{{ meeting.formattedDuration }}</dd> |
||||
</dl> |
||||
{% endif %} |
||||
{% endif %} |
||||
@ -0,0 +1,62 @@ |
||||
{% import "default/document/recycle.tpl" as macro %} |
||||
|
||||
{{ schedule_form }} |
||||
{{ search_form }} |
||||
|
||||
{% if meetings %} |
||||
<h4>{{ 'MeetingsFound'|get_plugin_lang('ZoomPlugin') }}: </h4> |
||||
<table class="table table-hover table-striped"> |
||||
<thead> |
||||
<tr> |
||||
<th>{{ 'Topic'|get_plugin_lang('ZoomPlugin') }}</th> |
||||
<th>{{ 'StartTime'|get_lang }}</th> |
||||
<th>{{ 'ForEveryone'|get_plugin_lang('ZoomPlugin') }}</th> |
||||
{# <th>{{ 'Course'|get_lang }}</th>#} |
||||
{# <th>{{ 'Session'|get_lang }}</th>#} |
||||
{% if allow_recording %} |
||||
<th>{{ 'Recordings'|get_plugin_lang('ZoomPlugin') }}</th> |
||||
{% endif %} |
||||
<th></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{% for meeting in meetings %} |
||||
<tr> |
||||
<td>{{ meeting.meetingInfoGet.topic }}</td> |
||||
<td>{{ meeting.formattedStartTime }}</td> |
||||
<td>{{ meeting.user ? 'No' : 'Yes' }}</td> |
||||
{# <td>{{ meeting.course ? meeting.course : '-' }}</td>#} |
||||
{# <td>{{ meeting.session ? meeting.session : '-' }}</td>#} |
||||
<td> |
||||
{% if allow_recording and meeting.recordings.count > 0 %} |
||||
{% for recording in meeting.recordings %} |
||||
<dl> |
||||
<dt> |
||||
{{ recording.formattedStartTime }} ({{ recording.formattedDuration }}) {{ 'Password' | get_lang }}: {{ recording.recordingMeeting.password }} |
||||
</dt> |
||||
<dd> |
||||
<ul> |
||||
{% for file in recording.recordingMeeting.recording_files %} |
||||
<li> |
||||
<a href="{{ file.play_url }}" target="_blank"> |
||||
{{ file.recording_type }}.{{ file.file_type }} |
||||
({{ macro.bytesToSize(file.file_size) }}) |
||||
</a> |
||||
</li> |
||||
{% endfor %} |
||||
</ul> |
||||
</dd> |
||||
</dl> |
||||
{% endfor %} |
||||
{% endif %} |
||||
</td> |
||||
<td> |
||||
<a class="btn btn-primary" href="meeting.php?meetingId={{ meeting.meetingId }}"> |
||||
{{ 'Details'|get_lang }} |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
</table> |
||||
{% endif %} |
||||
@ -0,0 +1,56 @@ |
||||
{% if instant_meeting_form %} |
||||
{{ instant_meeting_form }} |
||||
{% endif %} |
||||
|
||||
{% if group_form %} |
||||
{{ group_form }} |
||||
{% endif %} |
||||
|
||||
{% if meetings.count %} |
||||
<div class="page-header"> |
||||
<h2>{{ 'ScheduledMeetings'|get_lang }}</h2> |
||||
</div> |
||||
<table class="table"> |
||||
<tr> |
||||
<th>{{ 'Topic'|get_plugin_lang('ZoomPlugin') }}</th> |
||||
<th>{{ 'Agenda'|get_plugin_lang('ZoomPlugin') }}</th> |
||||
<th>{{ 'StartTime'|get_lang }}</th> |
||||
<th>{{ 'Duration'|get_lang }}</th> |
||||
<th>{{ 'Actions'|get_lang }}</th> |
||||
</tr> |
||||
{% for meeting in meetings %} |
||||
<tr> |
||||
<td> |
||||
{{ meeting.meetingInfoGet.topic }} |
||||
</td> |
||||
<td> |
||||
{{ meeting.meetingInfoGet.agenda|nl2br }} |
||||
</td> |
||||
<td>{{ meeting.formattedStartTime }}</td> |
||||
<td>{{ meeting.formattedDuration }}</td> |
||||
<td> |
||||
<a class="btn btn-primary" href="join_meeting.php?meetingId={{ meeting.meetingId }}&{{ _p.web_cid_query }}"> |
||||
{{ 'Join'|get_plugin_lang('ZoomPlugin') }} |
||||
</a> |
||||
|
||||
{% if is_manager %} |
||||
<a class="btn btn-default" href="meeting.php?meetingId={{ meeting.meetingId }}&{{ _p.web_cid_query }}"> |
||||
{{ 'Details'|get_plugin_lang('ZoomPlugin') }} |
||||
</a> |
||||
|
||||
<a class="btn btn-danger" |
||||
href="start.php?action=delete&meetingId={{ meeting.meetingId }}&{{ _p.web_cid_query }}" |
||||
onclick="javascript:if(!confirm('{{ 'AreYouSureToDelete' | get_lang }}')) return false;" |
||||
> |
||||
{{ 'Delete'|get_lang }} |
||||
</a> |
||||
{% endif %} |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</table> |
||||
{% endif %} |
||||
|
||||
{% if schedule_meeting_form %} |
||||
{{ schedule_meeting_form }} |
||||
{% endif %} |
||||
Loading…
Reference in new issue