commit
1fc5d992c8
@ -0,0 +1 @@ |
||||
This plugin allows teachers to launch a Zoom conference at any time and students to join it. |
@ -0,0 +1,33 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\CourseMeetingList; |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
$cidReset = true; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_admin_script(); |
||||
|
||||
$tool_name = get_lang('ZoomVideoConferences'); |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
|
||||
// the section (for the tabs) |
||||
$this_section = SECTION_PLATFORM_ADMIN; |
||||
|
||||
$form = $plugin->getAdminSearchForm(); |
||||
$startDate = new DateTime($form->getElement('start')->getValue()); |
||||
$endDate = new DateTime($form->getElement('end')->getValue()); |
||||
$type = $form->getElement('type')->getValue(); |
||||
|
||||
$tpl = new Template($tool_name); |
||||
$tpl->assign('meetings', $plugin->getPeriodMeetings($type, $startDate, $endDate)); |
||||
if ($plugin->get('enableCloudRecording')) { |
||||
$tpl->assign('recordings', $plugin->getRecordings($startDate, $endDate)); |
||||
} |
||||
$tpl->assign('search_form', $form->returnForm()); |
||||
$tpl->assign('content', $tpl->fetch('zoom/view/admin.tpl')); |
||||
$tpl->display_one_col_template(); |
@ -0,0 +1,4 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php'; |
@ -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,108 @@ |
||||
<?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['enableParticipantRegistration'] = 'Enable participant registration'; |
||||
$strings['enableCloudRecording'] = 'Enable cloud recording'; |
||||
$strings['enableGlobalConference'] = 'Enable global conference'; |
||||
$strings['enableGlobalConferencePerUser'] = 'Enable global conference per user'; |
||||
$strings['globalConferenceAllowRoles'] = "Global conference 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. fill in information about your \"App\" |
||||
(application and company names, contact name and email address) |
||||
<br/>6. click on <em>Continue</em> |
||||
Locate your API Key and Secret in the App Credentials page. |
||||
<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['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['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['Files'] = "Files"; |
||||
$strings['Finished'] = "finished"; |
||||
$strings['FileWasCopiedToCourse'] = "The file was copied to the course"; |
||||
$strings['FileWasDeleted'] = "The file was deleted"; |
||||
$strings['InstantMeeting'] = "Instant meeting"; |
||||
$strings['Join'] = "Join"; |
||||
$strings['JoinMeetingAsMyself'] = "Join meeting as myself"; |
||||
$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['ScheduleTheMeeting'] = "Schedule the meeting"; |
||||
$strings['Search'] = "Search"; |
||||
$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['ZoomVideoConferences'] = "Zoom Video Conferences"; |
@ -0,0 +1,107 @@ |
||||
<?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'] = "Activer l'enregistrement sur les serveurs de Zoom"; |
||||
$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['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. saisissez quelques informations sur votre \"App\" |
||||
(noms de l'application, de l'entreprise, nom et adresse de courriel de contact) |
||||
<br/>6. cliquez sur <em>Continue</em> |
||||
<br/>La page <em>App Credentials</em> affiche la clé (API Key) and le code secret (API Secret) à saisir ici. |
||||
<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['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['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['Files'] = "Fichiers"; |
||||
$strings['Finished'] = "terminée"; |
||||
$strings['FileWasCopiedToCourse'] = "Le fichier a été copié dans le cours"; |
||||
$strings['FileWasDeleted'] = "Le fichier a été effacé"; |
||||
$strings['InstantMeeting'] = "Conférence instantanée"; |
||||
$strings['Join'] = "Rejoindre"; |
||||
$strings['JoinMeetingAsMyself'] = "Rejoindre la conférence en tant que moi-même"; |
||||
$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'] = "A link to the file was added to the course"; |
||||
$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['ScheduleTheMeeting'] = "Programmer la conférence"; |
||||
$strings['Search'] = "Rechercher"; |
||||
$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['Waiting'] = "en attente"; |
||||
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "Enregistrement (%s) de la conférence %s de %s (%s).%s"; |
||||
$strings['ZoomVideoConferences'] = "Conférences vidéo Zoom"; |
@ -0,0 +1,31 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Trait BaseMeetingTrait. |
||||
* Common meeting properties definitions. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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; |
||||
} |
@ -0,0 +1,34 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
interface Client |
||||
{ |
||||
/** |
||||
* 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) |
||||
*/ |
||||
public function send($httpMethod, $relativePath, $parameters = [], $requestBody = null); |
||||
} |
@ -0,0 +1,43 @@ |
||||
<?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 serveur upon recording a registrant to a meeting. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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,19 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
class CustomQuestion |
||||
{ |
||||
/** @var string */ |
||||
public $title; |
||||
|
||||
/** @var string */ |
||||
public $value; |
||||
} |
@ -0,0 +1,40 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class JWTClient implements 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 |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@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,109 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Trait JsonDeserializableTrait. |
||||
* Utility fonctions to help convert server-generated JSON to API class instances. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 (is_null($object)) { |
||||
throw new Exception('Could not decode JSON: '.$json); |
||||
} |
||||
|
||||
$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 { |
||||
throw new Exception("Source object has property $name, which was not expected."); |
||||
} |
||||
} |
||||
$destination->initializeExtraProperties(); |
||||
} |
||||
} |
@ -0,0 +1,89 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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. |
||||
* |
||||
* @param Client $client an API client |
||||
* |
||||
* @throws Exception describing the error (message and code) |
||||
* |
||||
* @return MeetingInfoGet meeting |
||||
*/ |
||||
public function create($client) |
||||
{ |
||||
return MeetingInfoGet::fromJson($client->send('POST', 'users/me/meetings', [], $this)); |
||||
} |
||||
|
||||
/** |
||||
* Creates a Meeting instance from a topic. |
||||
* |
||||
* @param string $topic |
||||
* @param int $type |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return static |
||||
*/ |
||||
protected static function fromTopicAndType($topic, $type = self::TYPE_SCHEDULED) |
||||
{ |
||||
$instance = new static(); |
||||
$instance->topic = $topic; |
||||
$instance->type = $type; |
||||
|
||||
return $instance; |
||||
} |
||||
} |
@ -0,0 +1,35 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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,162 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @param int $id |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return static the meeting |
||||
*/ |
||||
public static function fromId($client, $id) |
||||
{ |
||||
return static::fromJson($client->send('GET', "meetings/$id")); |
||||
} |
||||
|
||||
/** |
||||
* Updates the meeting on server. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function update($client) |
||||
{ |
||||
$client->send('PATCH', 'meetings/'.$this->id, [], $this); |
||||
} |
||||
|
||||
/** |
||||
* Ends the meeting on server. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function endNow($client) |
||||
{ |
||||
$client->send('PUT', "meetings/$this->id/status", [], (object) ['action' => 'end']); |
||||
} |
||||
|
||||
/** |
||||
* Deletes the meeting on server. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function delete($client) |
||||
{ |
||||
$client->send('DELETE', "meetings/$this->id"); |
||||
} |
||||
|
||||
/** |
||||
* Adds a registrant to the meeting. |
||||
* |
||||
* @param Client $client |
||||
* @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($client, $registrant, $occurrenceIds = '') |
||||
{ |
||||
return CreatedRegistration::fromJson( |
||||
$client->send( |
||||
'POST', |
||||
"meetings/$this->id/registrants", |
||||
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds], |
||||
$registrant |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Removes registrants from the meeting. |
||||
* |
||||
* @param Client $client |
||||
* @param MeetingRegistrant[] $registrants registrants to remove (id and email) |
||||
* @param string $occurrenceIds separated by comma |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function removeRegistrants($client, $registrants, $occurrenceIds = '') |
||||
{ |
||||
if (!empty($registrants)) { |
||||
$client->send( |
||||
'PUT', |
||||
"meetings/$this->id/registrants/status", |
||||
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds], |
||||
(object) [ |
||||
'action' => 'cancel', |
||||
'registrants' => $registrants, |
||||
] |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Retrieves meeting registrants. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrantListItem[] the meeting registrants |
||||
*/ |
||||
public function getRegistrants($client) |
||||
{ |
||||
return MeetingRegistrantList::loadMeetingRegistrants($client, $this->id); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves the meeting's instances. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingInstance[] |
||||
*/ |
||||
public function getInstances($client) |
||||
{ |
||||
return MeetingInstances::fromMeetingId($client, $this->id)->meetings; |
||||
} |
||||
} |
@ -0,0 +1,53 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
class MeetingInstance |
||||
{ |
||||
/** @var string */ |
||||
public $uuid; |
||||
|
||||
/** @var string */ |
||||
public $start_time; |
||||
|
||||
/** |
||||
* Retrieves the recording of the instance. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception with code 404 when there is no recording for this meeting |
||||
* |
||||
* @return RecordingMeeting the recording |
||||
*/ |
||||
public function getRecordings($client) |
||||
{ |
||||
return RecordingMeeting::fromJson($client->send('GET', 'meetings/'.htmlentities($this->uuid).'/recordings')); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves the instance's participants. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return ParticipantListItem[] |
||||
*/ |
||||
public function getParticipants($client) |
||||
{ |
||||
return ParticipantList::loadInstanceParticipants($client, $this->uuid); |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @param int $meetingId |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingInstances the meeting's instances |
||||
*/ |
||||
public static function fromMeetingId($client, $meetingId) |
||||
{ |
||||
return static::fromJson($client->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,60 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingList. Lists Meetings. |
||||
* |
||||
* @see MeetingListItem |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @param int $type TYPE_SCHEDULED, TYPE_LIVE or TYPE_UPCOMING |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingListItem[] all meetings |
||||
*/ |
||||
public static function loadMeetings($client, $type) |
||||
{ |
||||
return static::loadItems('meetings', $client, '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,45 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingListItem. Item of a list of meetings. |
||||
* |
||||
* @see MeetingList |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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,102 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 |
||||
* |
||||
* @return MeetingRegistrant |
||||
*/ |
||||
public static function fromEmailAndFirstName($email, $firstName) |
||||
{ |
||||
$instance = new static(); |
||||
$instance->first_name = $firstName; |
||||
$instance->email = $email; |
||||
|
||||
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,55 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class MeetingRegistrantList. List of meeting registrants. |
||||
* |
||||
* @see MeetingRegistrantListItem |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
class MeetingRegistrantList |
||||
{ |
||||
use Pagination; |
||||
|
||||
/** @var MeetingRegistrantListItem[] */ |
||||
public $registrants; |
||||
|
||||
/** |
||||
* MeetingRegistrantList constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->registrants = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all registrant for a meeting. |
||||
* |
||||
* @param Client $client |
||||
* @param int $meetingId |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrantListItem[] all registrants of the meeting |
||||
*/ |
||||
public static function loadMeetingRegistrants($client, $meetingId) |
||||
{ |
||||
return static::loadItems('registrants', $client, "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,30 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
/** |
||||
* Class MeetingRegistrantListItem. Item in a list of meeting registrants. |
||||
* |
||||
* @see MeetingRegistrantList |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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,141 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 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,70 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @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, $client, $relativePath, $parameters = []) |
||||
{ |
||||
$items = []; |
||||
$pageCount = 1; |
||||
$pageSize = 300; |
||||
$totalRecords = 0; |
||||
for ($pageNumber = 1; $pageNumber <= $pageCount; $pageNumber++) { |
||||
$response = static::fromJson( |
||||
$client->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,73 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @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, $client, $relativePath, $parameters = []) |
||||
{ |
||||
$items = []; |
||||
$pageSize = 300; |
||||
$totalRecords = 0; |
||||
$nextPageToken = ''; |
||||
do { |
||||
$response = static::fromJson( |
||||
$client->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,60 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class ParticipantList |
||||
* List of past meeting instance participants. |
||||
* |
||||
* @see ParticipantListItem; |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
class ParticipantList |
||||
{ |
||||
use PaginationToken; |
||||
|
||||
/** @var ParticipantListItem[] */ |
||||
public $participants; |
||||
|
||||
/** |
||||
* ParticipantList constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->participants = []; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves a meeting instance's participants. |
||||
* |
||||
* @param Client $client |
||||
* @param string $instanceUUID |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return ParticipantListItem[] participants |
||||
*/ |
||||
public static function loadInstanceParticipants($client, $instanceUUID) |
||||
{ |
||||
return static::loadItems( |
||||
'participants', |
||||
$client, |
||||
'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,23 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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,78 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @param string $uuid |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return PastMeeting the past meeting |
||||
*/ |
||||
public static function fromUUID($client, $uuid) |
||||
{ |
||||
return static::fromJson($client->send('GET', 'past_meetings/'.htmlentities($uuid))); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves information on participants from a past meeting instance. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return ParticipantListItem[] participants |
||||
*/ |
||||
public function getParticipants($client) |
||||
{ |
||||
return ParticipantList::loadInstanceParticipants($client, $this->uuid); |
||||
} |
||||
} |
@ -0,0 +1,118 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function delete($client) |
||||
{ |
||||
$client->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,68 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 Client $client |
||||
* @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($client, $startDate, $endDate) |
||||
{ |
||||
return static::loadItems( |
||||
'meetings', |
||||
$client, |
||||
'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,91 @@ |
||||
<?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 |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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 RecordingFile[] List of recording file. */ |
||||
public $recording_files; |
||||
|
||||
/** |
||||
* RecordingMeeting constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->recording_files = []; |
||||
} |
||||
|
||||
/** |
||||
* Deletes the recording on the server. |
||||
* |
||||
* @param Client $client |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function delete($client) |
||||
{ |
||||
$client->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,30 @@ |
||||
<?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. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom\API |
||||
*/ |
||||
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,69 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class CourseMeeting. A remote Zoom meeting linked to a local course. |
||||
* An instance of this class is required to create a remote meeting from scratch. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class CourseMeeting extends API\Meeting |
||||
{ |
||||
use CourseMeetingTrait; |
||||
use DisplayableMeetingTrait; |
||||
|
||||
/** |
||||
* Creates a CourseMeeting instance from a topic. |
||||
* |
||||
* @param int $courseId |
||||
* @param int $sessionId |
||||
* @param string $topic |
||||
* @param int $type |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return static |
||||
*/ |
||||
public static function fromCourseSessionTopicAndType($courseId, $sessionId, $topic, $type) |
||||
{ |
||||
$instance = static::fromTopicAndType($topic, $type); |
||||
$instance->setCourseAndSessionId($courseId, $sessionId); |
||||
$instance->initializeDisplayableProperties(); |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
$this->decodeAndRemoveTag(); |
||||
$this->initializeDisplayableProperties(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* Creates a tagged meeting |
||||
* |
||||
* @return CourseMeetingInfoGet |
||||
*/ |
||||
public function create($client) |
||||
{ |
||||
$new = new CourseMeetingInfoGet(); |
||||
|
||||
$this->tagAgenda(); |
||||
static::recursivelyCopyObjectProperties(parent::create($client), $new); |
||||
$this->untagAgenda(); |
||||
|
||||
return $new; |
||||
} |
||||
} |
@ -0,0 +1,57 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class CourseMeetingInfoGet. A full Meeting as returned by the server and locally linked to a course. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class CourseMeetingInfoGet extends API\MeetingInfoGet |
||||
{ |
||||
use CourseMeetingTrait; |
||||
use DisplayableMeetingTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
$this->decodeAndRemoveTag(); |
||||
$this->initializeDisplayableProperties(); |
||||
} |
||||
|
||||
/** |
||||
* Updates the meeting on server, tagging it so to remember its course and session. |
||||
* |
||||
* @param API\Client $client |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function update($client) |
||||
{ |
||||
$this->tagAgenda(); |
||||
parent::update($client); |
||||
$this->untagAgenda(); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves meeting registrants. |
||||
* |
||||
* @param API\Client $client |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return UserMeetingRegistrantListItem[] |
||||
*/ |
||||
public function getUserRegistrants($client) |
||||
{ |
||||
return UserMeetingRegistrantList::loadUserMeetingRegistrants($client, $this->id); |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
/** |
||||
* Class CourseMeetingList. A List of course meetings. |
||||
* |
||||
* @see CourseMeetingListItem |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class CourseMeetingList extends API\MeetingList |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('meetings' === $propertyName) { |
||||
return CourseMeetingListItem::class; |
||||
} |
||||
|
||||
return parent::itemClass($propertyName); |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class CourseMeetingListItem. An item from a course meeting list. |
||||
* |
||||
* @see CourseMeetingList |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class CourseMeetingListItem extends API\MeetingListItem |
||||
{ |
||||
use CourseMeetingTrait; |
||||
use DisplayableMeetingTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
$this->decodeAndRemoveTag(); |
||||
$this->initializeDisplayableProperties(); |
||||
} |
||||
} |
@ -0,0 +1,142 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\Session; |
||||
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser; |
||||
use Chamilo\UserBundle\Entity\User; |
||||
use Database; |
||||
|
||||
/** |
||||
* Trait CourseMeetingTrait. |
||||
* A Zoom meeting linked to a (course, session) pair. |
||||
* The course and session IDs are stored in the meeting agenda on write operations, read and removed on retrieval. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
trait CourseMeetingTrait |
||||
{ |
||||
use API\BaseMeetingTrait; |
||||
|
||||
/** @var bool whether the agenda contains the course and session identifiers */ |
||||
public $isTaggedWithCourseId; |
||||
|
||||
/** @var int meeting course id as found in the agenda field */ |
||||
public $courseId; |
||||
|
||||
/** @var Course meeting course */ |
||||
public $course; |
||||
|
||||
/** @var int meeting session id as found in the agenda field */ |
||||
public $sessionId; |
||||
|
||||
/** @var Session meeting session */ |
||||
public $session; |
||||
|
||||
public function loadCourse() |
||||
{ |
||||
$this->course = Database::getManager()->getRepository('ChamiloCoreBundle:Course')->find($this->courseId); |
||||
} |
||||
|
||||
public function loadSession() |
||||
{ |
||||
$this->session = $this->sessionId |
||||
? Database::getManager()->getRepository('ChamiloCoreBundle:Session')->find($this->sessionId) |
||||
: null; |
||||
} |
||||
|
||||
public function setCourseAndSessionId($courseId, $sessionId) |
||||
{ |
||||
$this->courseId = $courseId; |
||||
$this->sessionId = $sessionId; |
||||
} |
||||
|
||||
public function tagAgenda() |
||||
{ |
||||
$this->agenda = $this->getUntaggedAgenda().$this->getTag(); |
||||
} |
||||
|
||||
public function untagAgenda() |
||||
{ |
||||
$this->agenda = $this->getUntaggedAgenda(); |
||||
} |
||||
|
||||
/** |
||||
* Builds the list of users that can register into this meeting. |
||||
* |
||||
* @return User[] the list of users |
||||
*/ |
||||
public function getCourseAndSessionUsers() |
||||
{ |
||||
if ($this->sessionId && is_null($this->session)) { |
||||
$this->loadSession(); |
||||
} |
||||
|
||||
if (is_null($this->course)) { |
||||
$this->loadCourse(); |
||||
} |
||||
|
||||
$users = []; |
||||
|
||||
if (is_null($this->session)) { |
||||
$users = Database::getManager()->getRepository( |
||||
'ChamiloCoreBundle:Course' |
||||
)->getSubscribedUsers($this->course)->getQuery()->getResult(); |
||||
} else { |
||||
$subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT); |
||||
if ($subscriptions) { |
||||
/** @var SessionRelCourseRelUser $sessionCourseUser */ |
||||
foreach ($subscriptions as $sessionCourseUser) { |
||||
$users[$sessionCourseUser->getUser()->getUserId()] = $sessionCourseUser->getUser(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return $users; |
||||
} |
||||
|
||||
/** |
||||
* @param int $courseId |
||||
* @param int $sessionId |
||||
* |
||||
* @return bool whether both values match this CourseMeeting |
||||
*/ |
||||
public function matches($courseId, $sessionId) |
||||
{ |
||||
return $courseId == $this->courseId && $sessionId == $this->sessionId; |
||||
} |
||||
|
||||
protected function decodeAndRemoveTag() |
||||
{ |
||||
$this->isTaggedWithCourseId = preg_match(self::getTagPattern(), $this->agenda, $matches); |
||||
if ($this->isTaggedWithCourseId) { |
||||
$this->setCourseAndSessionId($matches['courseId'], $matches['sessionId']); |
||||
$this->untagAgenda(); |
||||
} else { |
||||
$this->setCourseAndSessionId(0, 0); |
||||
} |
||||
$this->course = null; |
||||
$this->session = null; |
||||
} |
||||
|
||||
protected function getUntaggedAgenda() |
||||
{ |
||||
return str_replace($this->getTag(), '', $this->agenda); |
||||
} |
||||
|
||||
/** |
||||
* @return string a tag to append to a meeting agenda so to link it to a (course, session) tuple |
||||
*/ |
||||
private function getTag() |
||||
{ |
||||
return "\n(course $this->courseId, session $this->sessionId)"; |
||||
} |
||||
|
||||
private static function getTagPattern() |
||||
{ |
||||
return '/course (?P<courseId>\d+), session (?P<sessionId>\d+)/m'; |
||||
} |
||||
} |
@ -0,0 +1,74 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use DateInterval; |
||||
use DateTime; |
||||
use DateTimeZone; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Trait DisplayableMeetingTrait. Extra properties to help formatting web views and time operations. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
trait DisplayableMeetingTrait |
||||
{ |
||||
use API\BaseMeetingTrait; |
||||
|
||||
/** @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; |
||||
|
||||
/** |
||||
* @throws Exception on unexpected start_time or duration |
||||
*/ |
||||
public function initializeDisplayableProperties() |
||||
{ |
||||
$this->typeName = [ |
||||
API\Meeting::TYPE_INSTANT => get_lang('InstantMeeting'), |
||||
API\Meeting::TYPE_SCHEDULED => get_lang('ScheduledMeeting'), |
||||
API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => get_lang('RecurringWithNoFixedTime'), |
||||
API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => get_lang('RecurringWithFixedTime'), |
||||
][$this->type]; |
||||
if (property_exists($this, 'status')) { |
||||
$this->statusName = [ |
||||
'waiting' => get_lang('Waiting'), |
||||
'started' => get_lang('Started'), |
||||
'finished' => get_lang('Finished'), |
||||
][$this->status]; |
||||
} |
||||
$this->startDateTime = null; |
||||
$this->formattedStartTime = ''; |
||||
$this->durationInterval = null; |
||||
$this->formattedDuration = ''; |
||||
if (!empty($this->start_time)) { |
||||
$this->startDateTime = new DateTime($this->start_time); |
||||
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); |
||||
$this->formattedStartTime = $this->startDateTime->format(get_lang('Y-m-d H:i')); |
||||
} |
||||
if (!empty($this->duration)) { |
||||
$now = new DateTime(); |
||||
$later = new DateTime(); |
||||
$later->add(new DateInterval('PT'.$this->duration.'M')); |
||||
$this->durationInterval = $later->diff($now); |
||||
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat')); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class File. A RecordingFile with extra help properties for the web view. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class File extends API\RecordingFile |
||||
{ |
||||
/** @var string */ |
||||
public $formattedFileSize; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
$this->formattedFileSize = format_file_size($this->file_size); |
||||
} |
||||
} |
@ -0,0 +1,65 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use DateInterval; |
||||
use DateTime; |
||||
use DateTimeZone; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class Recording. A RecordingMeeting with extra help properties and a list of File instances |
||||
* (instead of RecordingFile instances). |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class Recording extends API\RecordingMeeting |
||||
{ |
||||
/** @var File[] List of recording file. */ |
||||
public $recording_files; |
||||
|
||||
/** @var DateTime */ |
||||
public $startDateTime; |
||||
|
||||
/** @var string */ |
||||
public $formattedStartTime; |
||||
|
||||
/** @var DateInterval */ |
||||
public $durationInterval; |
||||
|
||||
/** @var string */ |
||||
public $formattedDuration; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
|
||||
$this->startDateTime = new DateTime($this->start_time); |
||||
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); |
||||
$this->formattedStartTime = $this->startDateTime->format(get_lang('Y-m-d H:i')); |
||||
|
||||
$now = new DateTime(); |
||||
$later = new DateTime(); |
||||
$later->add(new DateInterval('PT'.$this->duration.'M')); |
||||
$this->durationInterval = $later->diff($now); |
||||
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat')); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('recording_files' === $propertyName) { |
||||
return File::class; |
||||
} |
||||
|
||||
return parent::itemClass($propertyName); |
||||
} |
||||
} |
@ -0,0 +1,51 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use DateTime; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class RecordingList. A list of past meeting instance recordings generated between two dates. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class RecordingList extends API\RecordingList |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('meetings' === $propertyName) { |
||||
return Recording::class; |
||||
} |
||||
|
||||
return parent::itemClass($propertyName); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all recordings from a period of time. |
||||
* |
||||
* @param API\Client $client |
||||
* @param DateTime $startDate first day of the period |
||||
* @param DateTime $endDate last day of the period |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return Recording[] all recordings from that period |
||||
*/ |
||||
public static function loadRecordings($client, $startDate, $endDate) |
||||
{ |
||||
return static::loadItems( |
||||
'meetings', |
||||
$client, |
||||
'users/me/recordings', |
||||
[ |
||||
'from' => $startDate->format('Y-m-d'), |
||||
'to' => $endDate->format('Y-m-d'), |
||||
] |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,51 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\UserBundle\Entity\User; |
||||
use Exception; |
||||
|
||||
/** |
||||
* Class UserMeetingRegistrant. Used to register a local user to a meeting. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class UserMeetingRegistrant extends API\MeetingRegistrant |
||||
{ |
||||
use UserMeetingRegistrantTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
$this->decodeAndRemoveTag(); |
||||
$this->computeFullName(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a UserMeetingRegistrant instance from a user. |
||||
* |
||||
* @param User $user |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return static |
||||
*/ |
||||
public static function fromUser($user) |
||||
{ |
||||
$instance = new static(); |
||||
$instance->email = $user->getEmail(); |
||||
$instance->first_name = $user->getFirstname(); |
||||
$instance->last_name = $user->getLastname(); |
||||
$instance->userId = $user->getId(); |
||||
$instance->user = $user; |
||||
$instance->computeFullName(); |
||||
|
||||
return $instance; |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class UserMeetingRegistrantList. A list of users registered to a meeting. |
||||
* |
||||
* @see UserMeetingRegistrantListItem |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class UserMeetingRegistrantList extends API\MeetingRegistrantList |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName) |
||||
{ |
||||
if ('registrants' === $propertyName) { |
||||
return UserMeetingRegistrantListItem::class; |
||||
} |
||||
|
||||
return parent::itemClass($propertyName); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all registrant for a meeting. |
||||
* |
||||
* @param API\Client $client |
||||
* @param int $meetingId |
||||
* |
||||
* @throws Exception |
||||
* |
||||
* @return UserMeetingRegistrantListItem[] all registrants of the meeting |
||||
*/ |
||||
public static function loadUserMeetingRegistrants($client, $meetingId) |
||||
{ |
||||
return static::loadItems('registrants', $client, "meetings/$meetingId/registrants"); |
||||
} |
||||
} |
@ -0,0 +1,30 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Exception; |
||||
|
||||
/** |
||||
* Class UserMeetingRegistrantListItem. An item of a user registrant list. |
||||
* |
||||
* @see UserMeetingRegistrantList |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
class UserMeetingRegistrantListItem extends API\MeetingRegistrantListItem |
||||
{ |
||||
use UserMeetingRegistrantTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
public function initializeExtraProperties() |
||||
{ |
||||
parent::initializeExtraProperties(); |
||||
$this->decodeAndRemoveTag(); |
||||
$this->computeFullName(); |
||||
} |
||||
} |
@ -0,0 +1,89 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\UserBundle\Entity\User; |
||||
use Database; |
||||
|
||||
/** |
||||
* Trait UserMeetingRegistrantTrait. |
||||
* A Zoom meeting registrant linked to a local user. |
||||
* The user id is stored in the registrant's email address on write operations, read and removed on retrieval. |
||||
* |
||||
* @package Chamilo\PluginBundle\Zoom |
||||
*/ |
||||
trait UserMeetingRegistrantTrait |
||||
{ |
||||
/** @var bool whether the remote zoom record contains a local user's identifier */ |
||||
public $isTaggedWithUserId; |
||||
|
||||
/** @var int */ |
||||
public $userId; |
||||
|
||||
/** @var User */ |
||||
public $user; |
||||
|
||||
/** @var string */ |
||||
public $fullName; |
||||
|
||||
public function loadUser() |
||||
{ |
||||
$this->user = Database::getManager()->getRepository('ChamiloUserBundle:User')->find($this->userId); |
||||
} |
||||
|
||||
public function setUserId($userId) |
||||
{ |
||||
$this->userId = $userId; |
||||
} |
||||
|
||||
public function tagEmail() |
||||
{ |
||||
$this->email = str_replace('@', $this->getTag(), $this->getUntaggedEmail()); |
||||
} |
||||
|
||||
public function untagEmail() |
||||
{ |
||||
$this->email = $this->getUntaggedEmail(); |
||||
} |
||||
|
||||
public function matches($userId) |
||||
{ |
||||
return $userId == $this->userId; |
||||
} |
||||
|
||||
public function computeFullName() |
||||
{ |
||||
$this->fullName = api_get_person_name($this->first_name, $this->last_name); |
||||
} |
||||
|
||||
protected function decodeAndRemoveTag() |
||||
{ |
||||
$this->isTaggedWithUserId = preg_match(self::getTagPattern(), $this->email, $matches); |
||||
if ($this->isTaggedWithUserId) { |
||||
$this->setUserId($matches['userId']); |
||||
$this->untagEmail(); |
||||
} else { |
||||
$this->setUserId(0); |
||||
} |
||||
$this->user = null; |
||||
} |
||||
|
||||
protected function getUntaggedEmail() |
||||
{ |
||||
return str_replace($this->getTag(), '@', $this->email); |
||||
} |
||||
|
||||
/** |
||||
* @return string a tag to append to a registrant comments so to link it to a user |
||||
*/ |
||||
private function getTag() |
||||
{ |
||||
return "+user_$this->userId@"; |
||||
} |
||||
|
||||
private static function getTagPattern() |
||||
{ |
||||
return '/\+user_(?P<userId>\d+)@/m'; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\API\MeetingSettings; |
||||
|
||||
if (!isset($returnURL)) { |
||||
exit; |
||||
} |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
$logInfo = [ |
||||
'tool' => 'Videoconference Zoom', |
||||
]; |
||||
|
||||
Event::registerLog($logInfo); |
||||
|
||||
$interbreadcrumb[] = [ // used in templates |
||||
'url' => $returnURL, |
||||
'name' => get_lang('ZoomVideoConferences'), |
||||
]; |
||||
|
||||
if (!array_key_exists('meetingId', $_REQUEST)) { |
||||
throw new Exception('MeetingNotFound'); |
||||
} |
||||
$plugin = ZoomPlugin::create(); |
||||
|
||||
$meeting = $plugin->getMeeting($_REQUEST['meetingId']); |
||||
|
||||
$tpl = new Template($meeting->id); |
||||
|
||||
if ($plugin->userIsConferenceManager()) { |
||||
// 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 ($plugin->get('enableParticipantRegistration') |
||||
&& MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $meeting->settings->approval_type) { |
||||
list($registerParticipantForm, $registrants) = $plugin->getRegisterParticipantForm($meeting); |
||||
$tpl->assign('registerParticipantForm', $registerParticipantForm->returnForm()); |
||||
$tpl->assign('registrants', $registrants); // FIXME cache |
||||
} |
||||
if ($plugin->get('enableCloudRecording') |
||||
&& 'cloud' === $meeting->settings->auto_recording |
||||
// && 'finished' === $meeting->status |
||||
) { |
||||
list($fileForm, $recordings) = $plugin->getFileForm($meeting); |
||||
$tpl->assign('fileForm', $fileForm->returnForm()); |
||||
$tpl->assign('recordings', $recordings); |
||||
} |
||||
} elseif (MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $meeting->settings->approval_type) { |
||||
$userId = api_get_user_id(); |
||||
try { |
||||
foreach ($plugin->getRegistrants($meeting) as $registrant) { |
||||
if ($registrant->userId == $userId) { |
||||
$tpl->assign('currentUserJoinURL', $registrant->join_url); |
||||
break; |
||||
} |
||||
} |
||||
} catch (Exception $exception) { |
||||
Display::addFlash( |
||||
Display::return_message($exception->getMessage(), 'error') |
||||
); |
||||
} |
||||
} |
||||
$tpl->assign('meeting', $meeting); |
||||
$tpl->assign('content', $tpl->fetch('zoom/view/meeting.tpl')); |
||||
$tpl->display_one_col_template(); |
@ -0,0 +1,13 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_admin_script(); |
||||
|
||||
$returnURL = 'admin.php'; |
||||
|
||||
// the section (for the tabs) |
||||
$this_section = SECTION_PLATFORM_ADMIN; |
||||
|
||||
include "meeting.php"; |
@ -0,0 +1,13 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_course_script(true); |
||||
|
||||
$returnURL = 'start.php?cId='.api_get_course_id().'&sessionId='.api_get_session_id(); |
||||
|
||||
// the section (for the tabs) |
||||
$this_section = SECTION_COURSES; |
||||
|
||||
include "meeting.php"; |
@ -0,0 +1,4 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
$plugin_info = ZoomPlugin::create()->get_info(); |
@ -0,0 +1,41 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Doctrine\Common\Collections\Criteria; |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_course_script(true); |
||||
|
||||
// the section (for the tabs) |
||||
$this_section = SECTION_COURSES; |
||||
|
||||
$logInfo = [ |
||||
'tool' => 'Videoconference Zoom', |
||||
]; |
||||
|
||||
Event::registerLog($logInfo); |
||||
|
||||
$tool_name = get_lang('ZoomVideoconferences'); |
||||
$tpl = new Template($tool_name); |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
|
||||
if ($plugin->userIsConferenceManager()) { |
||||
// user can create a new meeting |
||||
$tpl->assign('createInstantMeetingForm', $plugin->getCreateInstantMeetingForm()->returnForm()); |
||||
$tpl->assign('scheduleMeetingForm', $plugin->getScheduleMeetingForm()->returnForm()); |
||||
} |
||||
|
||||
try { |
||||
$tpl->assign('scheduledMeetings', $plugin->getScheduledMeetings()); |
||||
} catch (Exception $exception) { |
||||
Display::addFlash( |
||||
Display::return_message('Could not retrieve scheduled meeting list: '.$exception->getMessage(), 'error') |
||||
); |
||||
} |
||||
|
||||
$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,55 @@ |
||||
{{ search_form }} |
||||
<table class="table table-hover table-striped"> |
||||
<caption>{{ 'MeetingsFound'|get_lang }}</caption> |
||||
<thead> |
||||
<tr> |
||||
<th>{{ 'StartTime'|get_lang }}</th> |
||||
<th>{{ 'Course'|get_lang }}</th> |
||||
<th>{{ 'Session'|get_lang }}</th> |
||||
<th>{{ 'Topic'|get_lang }}</th> |
||||
{% if recordings %} |
||||
<th>{{ 'Recordings'|get_lang }}</th> |
||||
{% endif %} |
||||
<th></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{% for meeting in meetings %} |
||||
<tr> |
||||
<td>{{ meeting.formattedStartTime }}</td> |
||||
<td>{{ meeting.course ? meeting.course.title : '-' }}</td> |
||||
<td>{{ meeting.session ? meeting.session.name : '-' }}</td> |
||||
<td>{{ meeting.topic }}</td> |
||||
{% if recordings %} |
||||
<td> |
||||
{% for recording in recordings %} |
||||
{% if recording.id == meeting.id %} |
||||
<dl> |
||||
<dt> |
||||
{{ recording.formattedStartTime }} |
||||
({{ recording.formattedDuration }}) |
||||
</dt> |
||||
<dd> |
||||
<ul> |
||||
{% for file in recording.recording_files %} |
||||
<li> |
||||
{{ file.recording_type }}.{{ file.file_type }} |
||||
({{ file.formattedFileSize }}) |
||||
</li> |
||||
{% endfor %} |
||||
</ul> |
||||
</dd> |
||||
</dl> |
||||
{% endif %} |
||||
{% endfor %} |
||||
</td> |
||||
{% endif %} |
||||
<td> |
||||
<a class="btn" href="meeting_from_admin.php?meetingId={{ meeting.id }}"> |
||||
{{ 'Details'|get_lang }} |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
</table> |
@ -0,0 +1,78 @@ |
||||
<p>{{ meeting.typeName }} {{ meeting.id }} ({{ meeting.statusName }})</p> |
||||
|
||||
{% if isConferenceManager and meeting.status == 'waiting' %} |
||||
<p> |
||||
<a href="{{ meeting.start_url }}" target="_blank"> |
||||
{{ 'StartMeeting'|get_lang }} |
||||
</a> |
||||
</p> |
||||
{% endif %} |
||||
|
||||
{% if currentUserJoinURL %} |
||||
<p> |
||||
<a href="{{ currentUserJoinURL }}" target="_blank"> |
||||
{{ 'JoinMeetingAsMyself'|get_lang }} |
||||
</a> |
||||
</p> |
||||
{% endif %} |
||||
|
||||
{% if meeting.settings.approval_type == 2 %} |
||||
<p> |
||||
<label> |
||||
{{ 'JoinURLToSendToParticipants'|get_lang }} |
||||
<input readonly value="{{ meeting.join_url }}"> |
||||
</label> |
||||
</p> |
||||
{% endif %} |
||||
|
||||
|
||||
{% if isConferenceManager %} |
||||
|
||||
{{ editMeetingForm }} |
||||
{{ deleteMeetingForm }} |
||||
{{ registerParticipantForm }} |
||||
{{ fileForm }} |
||||
{% if registrants and meeting.settings.approval_type != 2 %} |
||||
<script> |
||||
function copyJoinURL(event, url) { |
||||
event.target.textContent = '{{ 'CopyingJoinURL'|get_lang|escape }}'; |
||||
navigator.clipboard.writeText(url).then( |
||||
function() { |
||||
event.target.textContent = '{{ 'JoinURLCopied'|get_lang|escape }}'; |
||||
}, function() { |
||||
event.target.textContent = '{{ 'CouldNotCopyJoinURL'|get_lang|escape }}' + ' ' + url; |
||||
} |
||||
); |
||||
} |
||||
</script> |
||||
<ul> |
||||
{% for registrant in registrants %} |
||||
<li> |
||||
<a onclick="copyJoinURL(event, '{{ registrant.join_url }}')"> |
||||
{{ 'CopyJoinAsURL'|get_lang }} |
||||
</a> |
||||
{{ registrant.fullName }} |
||||
</li> |
||||
{% endfor %} |
||||
</ul> |
||||
{% endif %} |
||||
|
||||
{% else %} |
||||
|
||||
<h2>{{ meeting.topic }}</h2> |
||||
{% if meeting.agenda %} |
||||
<blockquote>{{ meeting.agenda| nl2br }}</blockquote> |
||||
{% endif %} |
||||
|
||||
{% if meeting.type == 2 or meeting.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,44 @@ |
||||
{% if createInstantMeetingForm %} |
||||
{{ createInstantMeetingForm }} |
||||
{% endif %} |
||||
{% if scheduledMeetings %} |
||||
<div class="page-header"> |
||||
<h2>{{ 'ScheduledMeetings'|get_lang }}</h2> |
||||
</div> |
||||
<table class="table"> |
||||
<tr> |
||||
<!-- th>{{ 'CreatedAt'|get_lang }}</th --> |
||||
<th>{{ 'StartTime'|get_lang }}</th> |
||||
<th>{{ 'Duration'|get_lang }}</th> |
||||
<!-- th>{{ 'Type'|get_lang }}</th --> |
||||
<th>{{ 'TopicAndAgenda'|get_lang }}</th> |
||||
<th></th> |
||||
</tr> |
||||
{% for meeting in scheduledMeetings %} |
||||
<tr> |
||||
<!-- td>{{ meeting.created_at }}</td --> |
||||
<td>{{ meeting.formattedStartTime }}</td> |
||||
<td>{{ meeting.formattedDuration }}</td> |
||||
<!-- td>{{ meeting.typeName }}</td --> |
||||
<td> |
||||
<strong>{{ meeting.topic }}</strong> |
||||
<p class="small">{{ meeting.agenda|nl2br }}</p> |
||||
</td> |
||||
<td> |
||||
<a class="btn" href="meeting_from_start.php?meetingId={{ meeting.id }}"> |
||||
{{ 'Details'|get_lang }} |
||||
</a> |
||||
<a class="btn" href="{{ meeting.join_url }}"> |
||||
{{ 'Join'|get_lang }} |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</table> |
||||
{% else %} |
||||
<!-- p>No scheduled meeting currently</p --> |
||||
{% endif %} |
||||
{% if scheduleMeetingForm %} |
||||
<h3>{{ 'ScheduleAMeeting'|get_lang }}</h3> |
||||
{{ scheduleMeetingForm }} |
||||
{% endif %} |
Loading…
Reference in new issue