This commit is contained in:
Xes
2025-08-14 22:39:38 +02:00
parent 3641e93527
commit 5403f346e3
3370 changed files with 327179 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
This plugin will create a link in existing and new courses for the teachers to
start a videoconference room with OpenMeetings, as well as the administration
settings to configure this tool.
More info on OpenMeetings: http://openmeetings.apache.org/
More info on Chamilo: http://www.chamilo.org
The tasks related to the development of this plugin:
* https://support.chamilo.org/issues/5491
* (private system access) https://task.beeznest.com/issues/7046
* https://issues.apache.org/jira/browse/OPENMEETINGS-802
People involved:
* Financed by the Commission Scolaire des Hautes-Rivières, Québec, Canada (and coordinated/executed by the TICFP team)
* First draft developed by Francis Gonzales Tello - Independent (at the time)
* First stable version published by Yannick Warnier - BeezNest/Chamilo team
* Maxim Solodovnik - OpenMeetings team - many thanks to him!
* Julio Montoya - Corrections and adding features.

View File

@@ -0,0 +1,11 @@
<?php
/* For licensing terms, see /license.txt */
/* Openmeetings parameters that will be registered in the course settings */
require_once __DIR__.'/../../main/inc/global.inc.php';
require_once 'lib/openmeetings.class.php';
require_once 'lib/openmeetings_plugin.class.php';
require_once 'lib/openmeetings_gateway.php';
require_once 'lib/openmeetings_rest_service.php';

View File

@@ -0,0 +1,11 @@
<?php
/**
* This script is included by the course_home.php script (indirectly) and is
* used to show the link to the plugin from inside the course's tools list.
*
* @package chamilo.plugin.bigbluebutton
*/
/**
* Display course tool title.
*/
echo "Videoconference";

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1,12 @@
<?php
/**
* This script is included by main/admin/settings.lib.php and generally
* includes things to execute in the main database (settings_current table).
*
* @package chamilo.plugin.bigbluebutton
*/
/**
* Initialization.
*/
require_once __DIR__.'/config.php';
openmeetingsPlugin::create()->install();

View File

@@ -0,0 +1,55 @@
<?php
/**
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
//Needed in order to show the plugin title
$strings['plugin_title'] = "OpenMeetings";
$strings['plugin_comment'] = "[Deprecated] Add a videoconference room in a Chamilo course using OpenMeetings";
$strings['Videoconference'] = "Videoconference";
$strings['MeetingOpened'] = "Meeting opened";
$strings['MeetingClosed'] = "Meeting closed";
$strings['MeetingClosedComment'] = "If you have asked for your sessions to be recorded, the recording will be available in the list below when it has been completely generated.";
$strings['CloseMeeting'] = "Close meeting";
$strings['MeetingDeleted'] = "Delete meeting";
$strings['MeetingDeletedComment'] = "";
$strings['VideoConferenceXCourseX'] = "Videoconference #%s course %s";
$strings['VideoConferenceAddedToTheCalendar'] = "Videoconference added to the calendar";
$strings['VideoConferenceAddedToTheLinkTool'] = "Videoconference added to the link tool";
$strings['GoToTheVideoConference'] = "Go to the videoconference";
$strings['Records'] = "Recording";
$strings['Meeting'] = "Meeting";
$strings['ViewRecord'] = "View recording";
$strings['CopyToLinkTool'] = "Copy to link tool";
$strings['EnterConference'] = "Enter the videoconference";
$strings['RecordList'] = "Recording list";
$strings['ServerIsNotRunning'] = "Videoconference server is not running";
$strings['ServerIsNotConfigured'] = "Videoconference server is not configured";
$strings['XUsersOnLine'] = "%s user(s) online";
$strings['host'] = 'OpenMeetings host';
$strings['host_help'] = 'This is the full address of your OpenMeeetings server interface. Might be http://localhost:5080/openmeetings, an IP address (e.g. http://192.168.13.54:5080/openmeetings) or a domain name (e.g. http://my.video.com:5080/openmeetings).';
$strings['salt'] = 'OpenMeetings salt';
$strings['salt_help'] = 'This is the security key of your OpenMeetings server, which will allow your server to authentify the Chamilo installation. Refer to the OpenMeetings documentation to locate it.';
$strings['tool_enable'] = 'OpenMeetings videoconference tool enabled';
$strings['tool_enable_help'] = 'Choose whether you want to enable the OpenMeetings videoconference tool. Once enabled, it will show as an additional course tool in all courses homepage, and teachers will be able to launch a conference at any time. Students will not be able to launch a conference, only join one. If you don\'t have an OpenMeetings server, please <a target="_blank" href="http://openmeetings.apache.org/">set one up</a> or ask the Chamilo official providers for a quote. OpenMeetings is a free (as in freedom *and* beer), but its installation requires a set of technical skills that might not be immediately available to all. You can install it on your own or seek professional help to assist you or do it for you. This help, however, will generate a certain cost. In the pure logic of the free software, we offer you the tools to make your work easier and recommend professionals (the Chamilo Official Providers) that will be able to help you if this were too difficult.<br />';
$strings['openmeetings_welcome_message'] = 'Welcome message';
$strings['openmeetings_record_and_store'] = 'Record and store sessions';
$strings['plugin_tool_openmeetings'] = 'Video';
$strings['ThereAreNotRecordingsForTheMeetings'] = 'There are not recording for the meeting sessions';
$strings['NoRecording'] = 'No recording';

View File

@@ -0,0 +1,50 @@
<?php
/* License: see /license.txt */
//Needed in order to show the plugin title
$strings['plugin_title'] = "OpenMeetings";
$strings['plugin_comment'] = "[Non maintenu] Ajoutez un espace de vidéoconférences aux cours de Chamilo avec OpenMeetings";
$strings['Videoconference'] = "Vidéoconférence";
$strings['MeetingOpened'] = "Session ouverte";
$strings['MeetingClosed'] = "Session fermée";
$strings['MeetingClosedComment'] = "Si vous avez demandé l'enregistrement des sessions de conférence, cet enregistrement apparaîtra dans la liste ci-dessous dans quelques instants.";
$strings['CloseMeeting'] = "Fermer la session";
$strings['MeetingDeleted'] = "Supprimer la session";
$strings['MeetingDeletedComment'] = "";
$strings['VideoConferenceXCourseX'] = "Vidéoconférence #%s, cours %s";
$strings['VideoConferenceAddedToTheCalendar'] = "Vidéoconférence ajoutée au calendrier";
$strings['VideoConferenceAddedToTheLinkTool'] = "Vidéoconférence ajoutée comme lien. Vous pouvez éditer et publier le lien sur la page principale du cours depuis l'outil liens.";
$strings['GoToTheVideoConference'] = "Entrer dans la salle de conférence";
$strings['Records'] = "Enregistrement";
$strings['Meeting'] = "Salle de conférence";
$strings['ViewRecord'] = "Voir l'enregistrement";
$strings['CopyToLinkTool'] = "Ajouter comme lien du cours";
$strings['EnterConference'] = "Entrer dans la salle de conférence";
$strings['RecordList'] = "Liste des enregistrements";
$strings['ServerIsNotRunning'] = "Le serveur de vidéoconférence ne fonctionne pas";
$strings['ServerIsNotConfigured'] = "Le serveur de vidéoconférence n'est pas configuré correctement";
$strings['XUsersOnLine'] = "%s utilisateurs dans la salle";
$strings['host'] = 'Hôte de OpenMeetings';
$strings['host_help'] = "C'est le nom du serveur où le serveur de vidéoconférence a été habilité. Cela peut être http://localhost:5080/openmeetings, une adresse IP (du genre http://192.168.13.54:5080/openmeetings) ou un nom de domaine (du genre http://ma.videoconf.com:5080/openmeetings).";
$strings['salt'] = 'Clef OpenMeetings';
$strings['salt_help'] = "C'est la clef de sécurité de votre serveur OpenMeetings (appelée 'salt' en anglais) qui permet à votre serveur de vérifier l'identité de votre installation de Chamilo et ainsi l'autoriser à se connecter. Veuillez vous référer à la documentation de OpenMeetings pour la localiser.";
$strings['tool_enable'] = 'Outil de vidéoconférence OpenMeetings activé';
$strings['tool_enable_help'] = "Choisissez si vous souhaitez activer l'outil de vidéoconférence OpenMeetings. Une fois activé, il apparaîtra comme un outil additionnel sur toutes les pages principales de cours, et les enseignants pourront démarrer une conférence à n'importe quel moment. Les étudiants ne pourront pas lancer de nouvelle session de conférence, seulement se joindre à une session existante. Si vous ne disposez pas d'un serveur de vidéoconférence OpenMeetings, veuillez <a target=\"_blank\" href=\"http://openmeetings.apache.org/\">en installer un</a> avant de poursuivre, ou demander un devis à l'un des fournisseurs officiels de Chamilo. OpenMeetings est un outil de logiciel libre (et gratuit), mais son installation pourrait présenter une certaine complexité et demander des compétences qui ne sont peut-être pas à la portée de tous. Vous pouvez l'installer vous-même à partir de la documentation (disponible publiquement) de OpenMeetings, ou recherchez un soutien professionnel. Ce soutien pourrait générer certains coûts (au moins le temps de la personne qui vous assiste dans l'opération). Dans le plus pur esprit du logiciel libre, nous vous fournissons les outils pour simplifier votre travail dans la mesure de nos possibilités, et nous vous recommandons des professionnels (les fournisseurs officiels de Chamilo) pour vous venir en aide au cas où ceux-ci seraient insuffisants.<br />";
$strings['openmeetings_welcome_message'] = 'Message de bienvenue de OpenMeetings';
$strings['openmeetings_record_and_store'] = 'Enregistrer les sessions de vidéoconférence';
$strings['plugin_tool_openmeetings'] = 'Vidéo';
$strings['ThereAreNotRecordingsForTheMeetings'] = 'Aucun enregistrement disponible';
$strings['NoRecording'] = "Pas d'enregistrement";

View File

@@ -0,0 +1,53 @@
<?php
/* License: see /license.txt */
//Needed in order to show the plugin title
$strings['plugin_title'] = "OpenMeetings";
$strings['plugin_comment'] = "[No mantenido] Añade una sala de videoconferencia en los cursos de Chamilo con OpenMeetings (om)";
$strings['Videoconference'] = "VideoconferenciaOM";
$strings['MeetingOpened'] = "Sala abierta";
$strings['MeetingClosed'] = "Sala cerrada";
$strings['MeetingClosedComment'] = "Si ha pedido grabar la sesión de videoconferencia en los parámetros del curso, esta grabación aparecerá en la lista siguiente una vez generada.";
$strings['CloseMeeting'] = "Cerrar sala";
$strings['MeetingDeleted'] = "Eliminar sala";
$strings['MeetingDeletedComment'] = "";
$strings['VideoConferenceXCourseX'] = "Videoconferencia #%s, curso %s";
$strings['VideoConferenceAddedToTheCalendar'] = "Videoconferencia añadida al calendario";
$strings['VideoConferenceAddedToTheLinkTool'] = "Videoconferencia añadida como enlace. Puede editar y publicar el enlace en la página principal del curso desde la herramienta de enlace.";
$strings['GoToTheVideoConference'] = "Ir a la videoconferencia";
$strings['Records'] = "Grabación";
$strings['Meeting'] = "Sala de conferencia";
$strings['ViewRecord'] = "Ver grabación";
$strings['CopyToLinkTool'] = "Añadir como enlace del curso";
$strings['EnterConference'] = "Entrar a la videoconferencia";
$strings['RecordList'] = "Lista de grabaciones";
$strings['ServerIsNotRunning'] = "El servidor de videoconferencia no está funcionando";
$strings['ServerIsNotConfigured'] = "El servidor de videoconferencia no está configurado correctamente";
$strings['XUsersOnLine'] = "%s usuario(s) en la sala";
$strings['host'] = 'Host de OpenMeetings';
$strings['host_help'] = 'Este es el nombre del servidor donde su servidor OpenMeetings está corriendo. Puede ser http://localhost:5080/openmeetings, una dirección IP (ej: http://192.168.13.54:5080/openmeetings) o un nombre de dominio (ej: http://mi.video.com:5080/openmeetings).';
$strings['user'] = 'Usuario';
$strings['user_help'] = 'Ingrese el usuario con el cual de conectará al servidor OpenMeetings';
$strings['pass'] = 'Clave OpenMeetings';
$strings['pass_help'] = 'Esta es la llave de seguridad de su servidor OpenMeetings (llamada "salt" en inglés), que permitirá a su servidor de autentifica la instalación de Chamilo (como autorizada). Refiérese a la documentación de OpenMeetings para ubicarla.';
$strings['tool_enable'] = 'Herramienta de videoconferencia OpenMeetings activada';
$strings['tool_enable_help'] = 'Escoja si desea activar la herramienta de videoconferencia OpenMeetings. Una vez activada, se mostrará como una herramienta adicional en todas las páginas principales de cursos, y los profesores podrán iniciar una conferencia en cualquier momento. Los estudiantes no podrían lanzar una conferencia, solo juntarse a una existente. Si no tiene un servidor de videoconferencia OpenMeetings, por favor <a target=\"_blank\" href=\"http://openmeetings.apache.org/\">configure uno</a> antes de seguir, o pida una cotización a uno de los proveedores oficiales de Chamilo. OpenMeetings es una herramienta de software libre (y gratuita), pero su instalación requiere de competencias que quizás no sean inmediatamente disponibles para todos. Puede instalarla usted mismo o buscar ayuda profesional. Esta ayuda podría no obstante generar algunos costos (por lo menos el tiempo de la persona quien lo ayude). En el puro espíritu del software libre, le ofrecemos las herramientas para hacer su trabajo más simple, en la medida de nuestras posibilidades, y le recomendamos profesionales (los proveedores oficiales de Chamilo) para ayudarlo en caso esto fuera demasiado complicado.<br />';
$strings['openmeetings_welcome_message'] = 'Mensaje de bienvenida de ';
$strings['openmeetings_record_and_store'] = 'Grabar las sesiones de videoconferencia';
$strings['plugin_tool_openmeetings'] = 'Video';
$strings['ThereAreNotRecordingsForTheMeetings'] = 'No hay grabaciones de sesiones de videoconferencia';
$strings['NoRecording'] = 'No hay grabación';

View File

@@ -0,0 +1,581 @@
<?php
/**
* Chamilo-OpenMeetings integration plugin library, defining methods to connect
* to OpenMeetings from Chamilo by calling its web services.
*
* @package chamilo.plugin.openmeetings
*/
namespace Chamilo\Plugin\OpenMeetings;
include_once __DIR__.'/session.class.php';
include_once __DIR__.'/room.class.php';
include_once __DIR__.'/user.class.php';
/**
* Open Meetings-Chamilo connector class.
*/
class OpenMeetings
{
public $url;
public $user;
public $pass;
public $api;
public $user_complete_name = null;
public $protocol = 'http://';
public $debug = false;
public $logout_url = null;
public $plugin_enabled = false;
public $sessionId = "";
public $roomName = '';
public $chamiloCourseId;
public $chamiloSessionId;
public $externalType;
/**
* Constructor (generates a connection to the API and the Chamilo settings
* required for the connection to the video conference server).
*/
public function __construct()
{
global $_configuration;
// initialize video server settings from global settings
$plugin = \OpenMeetingsPlugin::create();
$om_plugin = (bool) $plugin->get('tool_enable');
$om_host = $plugin->get('host');
$om_user = $plugin->get('user');
$om_pass = $plugin->get('pass');
$accessUrl = api_get_access_url($_configuration['access_url']);
$this->externalType = substr($accessUrl['url'], strpos($accessUrl['url'], '://') + 3, -1);
if (strcmp($this->externalType, 'localhost') == 0) {
$this->externalType = substr(api_get_path(WEB_PATH), strpos(api_get_path(WEB_PATH), '://') + 3, -1);
}
$this->externalType = 'chamilolms.'.$this->externalType;
$this->table = \Database::get_main_table('plugin_openmeetings');
if ($om_plugin) {
$user_info = api_get_user_info();
$this->user_complete_name = $user_info['complete_name'];
$this->user = $om_user;
$this->pass = $om_pass;
$this->url = $om_host;
// Setting OM api
define('CONFIG_OPENMEETINGS_USER', $this->user);
define('CONFIG_OPENMEETINGS_PASS', $this->pass);
define('CONFIG_OPENMEETINGS_SERVER_URL', $this->url);
$this->gateway = new \OpenMeetingsGateway($this->url, $this->user, $this->pass);
$this->plugin_enabled = $om_plugin;
// The room has a name composed of C + course ID + '-' + session ID
$this->chamiloCourseId = api_get_course_int_id();
$this->chamiloSessionId = api_get_session_id();
$this->roomName = 'C'.$this->chamiloCourseId.'-'.$this->chamiloSessionId;
$return = $this->gateway->loginUser();
if ($return == 0) {
$msg = 'Could not initiate session with server through OpenMeetingsGateway::loginUser()';
error_log(__FILE__.'+'.__LINE__.': '.$msg);
exit($msg);
}
$this->sessionId = $this->gateway->sessionId;
}
}
/**
* Checks whether a user is teacher in the current course.
*
* @return bool True if the user can be considered a teacher in this course, false otherwise
*/
public function isTeacher()
{
return api_is_course_admin() || api_is_coach() || api_is_platform_admin();
}
/*
* Creating a Room for the meeting
* @return bool True if the user is correct and false when is incorrect
*/
public function createMeeting($params)
{
global $_configuration;
// First, try to see if there is an active room for this course and session.
$roomId = null;
$meetingData = \Database::select(
'*',
$this->table,
[
'where' => [
'c_id = ?' => $this->chamiloCourseId,
' AND session_id = ? ' => $this->chamiloSessionId,
' AND status <> ? ' => 2,
],
],
'first'
);
if ($meetingData != false && count($meetingData) > 0) {
// There has been a room in the past for this course. It should
// still be on the server, so update (instead of creating a new one)
// This fills the following attributes: status, name, comment, chamiloCourseId, chamiloSessionId
$room = new Room();
$room->loadRoomId($meetingData['room_id']);
$roomArray = (array) $room;
$roomArray['SID'] = $this->sessionId;
$roomId = $this->gateway->updateRoomWithModeration($room);
if ($roomId != $meetingData['room_id']) {
$msg = 'Something went wrong: the updated room ID ('.$roomId.') is not the same as the one we had ('.$meetingData['room_id'].')';
exit($msg);
}
} else {
$room = new Room();
$room->SID = $this->sessionId;
$room->name = $this->roomName;
//$room->roomtypes_id = $room->roomtypes_id;
$room->comment = urlencode(get_lang('Course').': '.$params['meeting_name'].' - '.$_configuration['software_name']);
//$room->numberOfPartizipants = $room->numberOfPartizipants;
$room->ispublic = boolval($room->getString('isPublic', 'false'));
//$room->appointment = $room->getString('appointment');
//$room->isDemoRoom = $room->getString('isDemoRoom');
//$room->demoTime = $room->demoTime;
//$room->isModeratedRoom = $room->getString('isModeratedRoom');
$roomId = $this->gateway->createRoomWithModAndType($room);
}
if (!empty($roomId)) {
/*
// Find the biggest room_id so far, and create a new one
if (empty($roomId)) {
$roomData = \Database::select('MAX(room_id) as room_id', $this->table, array(), 'first');
$roomId = $roomData['room_id'] + 1;
}*/
$params['status'] = '1';
$params['meeting_name'] = $room->name;
$params['created_at'] = api_get_utc_datetime();
$params['room_id'] = $roomId;
$params['c_id'] = api_get_course_int_id();
$params['session_id'] = api_get_session_id();
$params['record'] = ($room->allowRecording ? 1 : 0);
$id = \Database::insert($this->table, $params);
$this->joinMeeting($id);
} else {
return -1;
}
}
/**
* Returns a meeting "join" URL.
*
* @param string The name of the meeting (usually the course code)
*
* @return mixed The URL to join the meeting, or false on error
*
* @todo implement moderator pass
* @assert ('') === false
* @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
*/
public function joinMeeting($meetingId)
{
if (empty($meetingId)) {
return false;
}
$meetingData = \Database::select(
'*',
$this->table,
['where' => ['id = ? AND status = 1 ' => $meetingId]],
'first'
);
if (empty($meetingData)) {
if ($this->debug) {
error_log("meeting does not exist: $meetingId ");
}
return false;
}
$params = ['room_id' => $meetingData['room_id']];
$returnVal = $this->setUserObjectAndGenerateRoomHashByURLAndRecFlag($params);
$iframe = $this->url."/?"."secureHash=".$returnVal;
printf("<iframe src='%s' width='%s' height = '%s' />", $iframe, "100%", 640);
}
/**
* Checks if the videoconference server is running.
* Function currently disabled (always returns 1).
*
* @return bool True if server is running, false otherwise
* @assert () === false
*/
public function isServerRunning()
{
// Always return true for now as this requires the openmeetings object
// to have been instanciated and this includes a loginUser() which
// connects to the server
return true;
}
/**
* Gets the password for a specific meeting for the current user.
*
* @return string A moderator password if user is teacher, or the course code otherwise
*/
public function getMeetingUserPassword()
{
if ($this->isTeacher()) {
return $this->getMeetingModerationPassword();
} else {
return api_get_course_id();
}
}
/**
* Generated a moderator password for the meeting.
*
* @return string A password for the moderation of the video conference
*/
public function getMeetingModerationPassword()
{
return api_get_course_id().'mod';
}
/**
* Get information about the given meeting.
*
* @param array ...?
*
* @return mixed Array of information on success, false on error
* @assert (array()) === false
*/
public function getMeetingInfo($params)
{
try {
$result = $this->api->getMeetingInfoArray($params);
if ($result == null) {
if ($this->debug) {
error_log(__FILE__.'+'.__LINE__." Failed to get any response. Maybe we can't contact the OpenMeetings server.");
}
} else {
return $result;
}
} catch (Exception $e) {
if ($this->debug) {
error_log(__FILE__.'+'.__LINE__.' Caught exception: ', $e->getMessage(), "\n");
}
}
return false;
}
/**
* @param array $params Array of parameters
*
* @return mixed
*/
public function setUserObjectAndGenerateRecordingHashByURL($params)
{
$username = $_SESSION['_user']['username'];
$firstname = $_SESSION['_user']['firstname'];
$lastname = $_SESSION['_user']['lastname'];
$userId = $_SESSION['_user']['user_id'];
$systemType = 'chamilo';
$room_id = $params['room_id'];
$urlWsdl = $this->url."/services/UserService?wsdl";
$omServices = new \SoapClient($urlWsdl);
$objRec = new User();
$objRec->SID = $this->sessionId;
$objRec->username = $username;
$objRec->firstname = $firstname;
$objRec->lastname = $lastname;
$objRec->externalUserId = $userId;
$objRec->externalUserType = $systemType;
$objRec->recording_id = $recording_id;
$orFn = $omServices->setUserObjectAndGenerateRecordingHashByURL($objRec);
return $orFn->return;
}
/**
* @param array $params Array of parameters
*
* @return mixed
*/
public function setUserObjectAndGenerateRoomHashByURLAndRecFlag($params)
{
$username = $_SESSION['_user']['username'];
$firstname = $_SESSION['_user']['firstname'];
$lastname = $_SESSION['_user']['lastname'];
$profilePictureUrl = $_SESSION['_user']['avatar'];
$email = $_SESSION['_user']['mail'];
$userId = $_SESSION['_user']['user_id'];
$systemType = 'Chamilo';
$room_id = $params['room_id'];
$becomeModerator = ($this->isTeacher() ? 1 : 0);
$allowRecording = 1; //Provisional
$urlWsdl = $this->url."/services/UserService?wsdl";
$omServices = new \SoapClient($urlWsdl);
$objRec = new User();
$objRec->SID = $this->sessionId;
$objRec->username = $username;
$objRec->firstname = $firstname;
$objRec->lastname = $lastname;
$objRec->profilePictureUrl = $profilePictureUrl;
$objRec->email = $email;
$objRec->externalUserId = $userId;
$objRec->externalUserType = $systemType;
$objRec->room_id = $room_id;
$objRec->becomeModeratorAsInt = $becomeModerator;
$objRec->showAudioVideoTestAsInt = 1;
$objRec->allowRecording = $allowRecording;
$rcFn = $omServices->setUserObjectAndGenerateRoomHashByURLAndRecFlag($objRec);
return $rcFn->return;
}
/**
* Gets all the course meetings saved in the plugin_openmeetings table.
*
* @return array Array of current open meeting rooms
*/
public function getCourseMeetings()
{
$newMeetingsList = [];
$item = [];
$meetingsList = \Database::select(
'*',
$this->table,
['where' => [
'c_id = ? ' => api_get_course_int_id(),
' AND session_id = ? ' => api_get_session_id(),
' AND status <> ? ' => 2, // status deleted
],
]
);
$room = new Room();
$room->SID = $this->sessionId;
if (!empty($meetingsList)) {
foreach ($meetingsList as $meetingDb) {
//$room->rooms_id = $meetingDb['room_id'];
error_log(__FILE__.'+'.__LINE__.' Meetings found: '.print_r($meetingDb, 1));
$remoteMeeting = [];
$meetingDb['created_at'] = api_get_local_time($meetingDb['created_at']);
$meetingDb['closed_at'] = (!empty($meetingDb['closed_at']) ? api_get_local_time($meetingDb['closed_at']) : '');
// Fixed value for now
$meetingDb['participantCount'] = 40;
$rec = $this->gateway->getFlvRecordingByRoomId($meetingDb['room_id']);
$links = [];
// Links to videos look like these:
// http://video2.openmeetings.com:5080/openmeetings/DownloadHandler?fileName=flvRecording_4.avi&moduleName=lzRecorderApp&parentPath=&room_id=&sid=dfc0cac396d384f59242aa66e5a9bbdd
$link = $this->url.'/DownloadHandler?fileName=%s&moduleName=lzRecorderApp&parentPath=&room_id=%s&sid=%s';
if (!empty($rec)) {
$link1 = sprintf($link, $rec['fileHash'], $meetingDb['room_id'], $this->sessionId);
$link2 = sprintf($link, $rec['alternateDownload'], $meetingDb['room_id'], $this->sessionId);
$links[] = $rec['fileName'].' '.
\Display::url('[.flv]', $link1, ['target' => '_blank']).' '.
\Display::url('[.avi]', $link2, ['target' => '_blank']);
}
$item['show_links'] = implode('<br />', $links);
// The following code is currently commented because the web service
// says this is not allowed by the SOAP user.
/*
try {
// Get the conference room object from OpenMeetings server - requires SID and rooms_id to be defined
$objRoomId = $this->gateway->getRoomById($meetingDb['room_id']);
if (empty($objRoomId->return)) {
error_log(__FILE__.'+'.__LINE__.' Emptyyyyy ');
//\Database::delete($this->table, "id = {$meetingDb['id']}");
// Don't delete expired rooms, just mark as closed
\Database::update($this->table, array('status' => 0, 'closed_at' => api_get_utc_datetime()), array('id = ? ' => $meetingDb['id']));
continue;
}
//$objCurUs = $omServices->getRoomWithCurrentUsersById($objCurrentUsers);
} catch (SoapFault $e) {
error_log(__FILE__.'+'.__LINE__.' '.$e->faultstring);
exit;
}
//if( empty($objCurUs->returnMeetingID) ) continue;
$current_room = array(
'roomtype' => $objRoomId->return->roomtype->roomtypes_id,
'meetingName' => $objRoomId->return->name,
'meetingId' => $objRoomId->return->meetingID,
'createTime' => $objRoomId->return->rooms_id,
'showMicrophoneStatus' => $objRoomId->return->showMicrophoneStatus,
'attendeePw' => $objRoomId->return->attendeePW,
'moderatorPw' => $objRoomId->return->moderators,
'isClosed' => $objRoomId->return->isClosed,
'allowRecording' => $objRoomId->return->allowRecording,
'startTime' => $objRoomId->return->startTime,
'endTime' => $objRoomId->return->updatetime,
'participantCount' => count($objRoomId->return->currentusers),
'maxUsers' => $objRoomId->return->numberOfPartizipants,
'moderatorCount' => count($objRoomId->return->moderators)
);
// Then interate through attendee results and return them as part of the array:
if (!empty($objRoomId->return->currentusers)) {
foreach ($objRoomId->return->currentusers as $a)
$current_room[] = array(
'userId' => $a->username,
'fullName' => $a->firstname . " " . $a->lastname,
'isMod' => $a->isMod
);
}
$remoteMeeting = $current_room;
*/
if (empty($remoteMeeting)) {
/*
error_log(__FILE__.'+'.__LINE__.' Empty remote Meeting for now');
if ($meetingDb['status'] == 1 && $this->isTeacher()) {
$this->endMeeting($meetingDb['id']);
}
*/
} else {
$remoteMeeting['add_to_calendar_url'] = api_get_self().'?action=add_to_calendar&id='.$meetingDb['id'].'&start='.api_strtotime($meetingDb['startTime']);
}
$remoteMeeting['end_url'] = api_get_self().'?action=end&id='.$meetingDb['id'];
$remoteMeeting['delete_url'] = api_get_self().'?action=delete&id='.$meetingDb['id'];
//$record_array = array();
// if ($meetingDb['record'] == 1) {
// $recordingParams = array(
// 'meetingId' => $meetingDb['id'], //-- OPTIONAL - comma separate if multiple ids
// );
//
// $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
// if (!empty($records)) {
// $count = 1;
// if (isset($records['message']) && !empty($records['message'])) {
// if ($records['messageKey'] == 'noRecordings') {
// $record_array[] = get_lang('NoRecording');
// } else {
// //$record_array[] = $records['message'];
// }
// } else {
// foreach ($records as $record) {
// if (is_array($record) && isset($record['recordId'])) {
// $url = Display::url(get_lang('ViewRecord'), $record['playbackFormatUrl'], array('target' => '_blank'));
// if ($this->is_teacher()) {
// $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meetingDb['id'].'&record_id='.$record['recordId']);
// $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meetingDb['id'].'&start='.api_strtotime($meetingDb['created_at']).'&url='.$record['playbackFormatUrl']);
// $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordId']);
// }
// //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
// $count++;
// $record_array[] = $url;
// } else {
//
// }
// }
// }
// }
// //var_dump($record_array);
// $item['show_links'] = implode('<br />', $record_array);
//
// }
//
//$item['created_at'] = api_convert_and_format_date($meetingDb['created_at']);
// //created_at
//
// $item['publish_url'] = api_get_self().'?action=publish&id='.$meetingDb['id'];
// $item['unpublish_url'] = api_get_self().'?action=unpublish&id='.$meetingDb['id'];
//
//if ($meetingDb['status'] == 1) {
// $joinParams = array(
// 'meetingId' => $meetingDb['id'], //-- REQUIRED - A unique id for the meeting
// 'username' => $this->user_complete_name, //-- REQUIRED - The name that will display for the user in the meeting
// 'password' => $pass, //-- REQUIRED - The attendee or moderator password, depending on what's passed here
// 'createTime' => '', //-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
// 'userID' => '', // -- OPTIONAL - string
// 'webVoiceConf' => '' // -- OPTIONAL - string
// );
// $returnVal = $this->setUserObjectAndGenerateRoomHashByURLAndRecFlag( array('room_id' => $meetingDb['id']) );
// $joinUrl = CONFIG_OPENMEETINGS_SERVER_URL . "?" .
// "secureHash=" . $returnVal;
//
// $item['go_url'] = $joinUrl;
//}
$item = array_merge($item, $meetingDb, $remoteMeeting);
//error_log(__FILE__.'+'.__LINE__.' Item: '.print_r($item,1));
$newMeetingsList[] = $item;
} //end foreach $meetingsList
}
return $newMeetingsList;
}
/**
* Send a command to the OpenMeetings server to close the meeting.
*
* @param int $meetingId
*
* @return int
*/
public function endMeeting($meetingId)
{
try {
$room = new Room($meetingId);
$room->SID = $this->sessionId;
$room->room_id = intval($meetingId);
$room->status = false;
$urlWsdl = $this->url."/services/RoomService?wsdl";
$ws = new \SoapClient($urlWsdl);
$roomClosed = $ws->closeRoom($room);
if ($roomClosed > 0) {
\Database::update(
$this->table,
[
'status' => 0,
'closed_at' => api_get_utc_datetime(),
],
['id = ? ' => $meetingId]
);
}
} catch (SoapFault $e) {
error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems: Fault: '.$e->faultstring);
exit;
return -1;
}
}
/**
* @param int $id
*
* @return int
*/
public function deleteMeeting($id)
{
try {
$room = new Room();
$room->loadRoomId($id);
$this->gateway->deleteRoom($room);
\Database::update(
$this->table,
[
'status' => 2,
],
['id = ? ' => $id]
);
return $id;
} catch (SoapFault $e) {
error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems: Fault: '.$e->faultstring);
exit;
return -1;
}
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* OpenMeetings API.
*
* @package chamilo.plugin.openmeetings
*/
/**
* Class OpenMeetingsAPI.
*/
class OpenMeetingsAPI
{
private $_user;
private $_pass;
private $_serverBaseUrl;
/**
* Constructor.
*/
public function __construct()
{
$this->_user = CONFIG_OPENMEETINGS_USER;
$this->_pass = CONFIG_OPENMEETINGS_PASS;
$this->_serverBaseUrl = CONFIG_OPENMEETINGS_SERVER_URL;
}
}

View File

@@ -0,0 +1,491 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License") + you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @package chamilo.plugin.openmeetings
*/
/**
* Init.
*/
require_once 'openmeetings_rest_service.php';
/**
* Class OpenMeetingsGateway.
*/
class OpenMeetingsGateway
{
public $sessionId = "";
public $config;
private $rest;
private $_user;
private $_pass;
private $_url;
public function __construct($host, $user, $pass)
{
$this->_user = urlencode($user);
$this->_pass = urlencode($pass);
$this->_url = $host;
if (substr($this->_url, -1, 1) == '/') {
$this->_url = substr($this->_url, 0, -1);
}
$this->rest = new OpenMeetingsRestService();
$err = $this->rest->getError();
if ($err) {
error_log('Constructor error: '.$err);
error_log('Debug: '.$this->rest->getDebug());
exit();
}
}
/**
* @param string $name
*
* @return string
*/
public function getRestUrl($name)
{
return $this->getUrl()."/services/".$name."/";
}
/**
* @return string
*/
public function getUrl()
{
return $this->_url;
}
/**
* @param bool $in
*
* @return string
*/
public function var_to_str($in)
{
if (is_bool($in)) {
return $in ? "true" : "false";
} else {
return $in;
}
}
/**
* TODO: Get Error Service and show detailed Error Message.
*/
public function loginUser()
{
$returnValue = 0;
$response = $this->rest->call($this->getRestUrl("UserService")."getSession", "session_id");
if ($this->rest->getError()) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($response, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
$this->sessionId = $response;
$url = $this->getRestUrl("UserService")
."loginUser?"
."SID=".$this->sessionId
."&username=".$this->_user
."&userpass=".$this->_pass;
$result = $this->rest->call($url);
if ($this->rest->getError()) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error '.$err);
} else {
$returnValue = $result;
}
}
}
}
if ($returnValue > 0) {
return true;
} else {
return false;
}
}
/**
* @param Room $room
*
* @return array|bool|int|null
*/
public function updateRoomWithModeration($room)
{
$err = $this->rest->getError();
if ($err) {
error_log('Constructor error: '.$err);
error_log('Debug: '.$this->rest->getDebug());
exit();
}
$isModeratedRoom = false;
if ($room->isModeratedRoom == 1) {
$isModeratedRoom = true;
}
$url = $this->getRestUrl($this->getRestUrl("RoomService")
."updateRoomWithModeration?SID=".$this->sessionId
."&room_id=".$room->room_id
."&name=".urlencode($room->name)
."&roomtypes_id=".$room->roomtypes_id
."&comment=".$room->comment
."&numberOfPartizipants=".$room->numberOfPartizipants
."&ispublic=false"
."&appointment=false"
."&isDemoRoom=false"
."&demoTime=0"
."&isModeratedRoom=".$this->var_to_str($isModeratedRoom));
$result = $this->rest->call($url);
if ($result->fault) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
return $result;
}
}
return -1;
}
/**
* @param $username
* @param $firstname
* @param $lastname
* @param $userId
* @param $systemType
* @param $recording_id
*
* @return array|bool|int|null
*/
public function setUserObjectAndGenerateRecordingHashByURL($username, $firstname, $lastname, $userId, $systemType, $recording_id)
{
$result = $this->rest->call($this->getRestUrl("UserService")
.'setUserObjectAndGenerateRecordingHashByURL?'
.'SID='.$this->sessionId
.'&username='.urlencode($username)
.'&firstname='.urlencode($firstname)
.'&lastname='.urlencode($lastname)
.'&externalUserId='.$userId
.'&externalUserType='.urlencode($systemType)
.'&recording_id='.$recording_id, 'return');
if ($result->fault) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
return $result;
}
}
return -1;
}
/**
* @param $username
* @param $firstname
* @param $lastname
* @param $profilePictureUrl
* @param $email
* @param $userId
* @param $systemType
* @param $room_id
* @param $becomeModerator
* @param $allowRecording
*
* @return array|bool|int|null
*/
public function setUserObjectAndGenerateRoomHashByURLAndRecFlag($username, $firstname, $lastname, $profilePictureUrl, $email, $userId, $systemType, $room_id, $becomeModerator, $allowRecording)
{
$err = $this->rest->getError();
if ($err) {
error_log('Constructor error: '.$err);
error_log('Debug: '.$this->rest->getDebug());
exit();
}
$result = $this->rest->call($this->getRestUrl("UserService")
."setUserObjectAndGenerateRoomHashByURLAndRecFlag?"
."SID=".$this->sessionId
."&username=".urlencode($username)
."&firstname=".urlencode($firstname)
."&lastname=".urlencode($lastname)
."&profilePictureUrl=".urlencode($profilePictureUrl)
."&email=".urlencode($email)
."&externalUserId=".urlencode($userId)
."&externalUserType=".urlencode($systemType)
."&room_id=".urlencode($room_id)
."&becomeModeratorAsInt=".$becomeModerator
."&showAudioVideoTestAsInt=1"
."&allowRecording=".$this->var_to_str($allowRecording));
if ($result->fault) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
// echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
return $result;
}
}
return -1;
}
/**
* @param Room $openmeetings
*
* @return array|bool|int|null
*/
public function deleteRoom($openmeetings)
{
$err = $this->rest->getError();
if ($err) {
error_log('Constructor error: '.$err);
error_log('Debug: '.$this->rest->getDebug());
exit();
}
$url = $this->getRestUrl("RoomService")."deleteRoom?SID=".$this->sessionId."&rooms_id=".$openmeetings->room_id;
$result = $this->rest->call($url);
if ($result->fault) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
// echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
// return $result["return"];
return $result;
}
}
return -1;
}
/**
* Generate a new room hash for entering a conference room.
*/
public function setUserObjectAndGenerateRoomHash($username, $firstname, $lastname, $profilePictureUrl, $email, $externalUserId, $externalUserType, $room_id, $becomeModeratorAsInt, $showAudioVideoTestAsInt)
{
$result = $this->rest->call($this->getRestUrl("UserService")
."setUserObjectAndGenerateRoomHash?"
."SID=".$this->sessionId
."&username=".urlencode($username)
."&firstname=".urlencode($firstname)
."&lastname=".urlencode($lastname)
."&profilePictureUrl=".urlencode($profilePictureUrl)
."&email=".urlencode($email)
."&externalUserId=".urlencode($externalUserId)
."&externalUserType=".urlencode($externalUserType)
."&room_id=".$room_id
."&becomeModeratorAsInt=".$becomeModeratorAsInt
."&showAudioVideoTestAsInt=".$showAudioVideoTestAsInt);
if ($result->getError()) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
// echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
return $result;
}
}
return -1;
}
/**
* Create a new conference room.
*
* @param Room The room object
*
* @return The REST call's result
*/
public function createRoomWithModAndType($room)
{
$service = 'addRoomWithModerationAndExternalType';
if ($room->allowRecording) {
$service = 'addRoomWithModerationAndRecordingFlags';
} elseif ($room->isAudioOnly) {
$service = 'addRoomWithModerationExternalTypeAndAudioType';
}
$url = $this->getRestUrl("RoomService")
.$service.'?'
.'SID='.$room->SID
.'&name='.$room->name
.'&roomtypes_id='.$room->roomtypes_id
.'&comment='.$room->comment
.'&numberOfPartizipants='.$room->numberOfPartizipants
.'&ispublic='.$this->var_to_str($room->ispublic)
.'&appointment='.$this->var_to_str($room->appointment)
.'&isDemoRoom='.$this->var_to_str($room->isDemoRoom)
.'&demoTime='.$room->demoTime
.'&isModeratedRoom='.$this->var_to_str($room->isModeratedRoom)
.'&externalRoomType='.$room->externalRoomType;
if ($room->allowRecording) {
$url .= '&allowUserQuestions='.$this->var_to_str($room->allowUserQuestions)
.'&isAudioOnly='.$this->var_to_str($room->isAudioOnly)
.'&waitForRecording='.$this->var_to_str($room->waitForRecording)
.'&allowRecording='.$this->var_to_str($room->allowRecording);
} elseif ($room->isAudioOnly) {
$url .= '&isAudioOnly='.$this->var_to_str($room->isAudioOnly);
}
$result = $this->rest->call($url);
if ($this->rest->fault) {
error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
} else {
$err = $this->rest->getError();
if ($err) {
error_log('Error: '.$err);
} else {
return $result;
}
}
return -1;
}
/**
* Gets the list of open rooms of type "Chamilo".
*
* @param string $type The type of external system connecting to OpenMeetings
*
* @return bool
*/
public function getRoomsWithCurrentUsersByType($type = 'chamilolms')
{
//$this->loginUser();
if (empty($this->sessionId)) {
return false;
}
$url = $this->getRestUrl("RoomService")."getRoomsWithCurrentUsersByListAndType?SID=".$this->sessionId
."&start=1&max=1000&orderby=name&asc=true&externalRoomType=chamilolms";
//$url = $this->getRestUrl("RoomService")
// . "getRoomTypes?"
// . "SID=" . $this->sessionId;
//$url = $this->getRestUrl('JabberService') . 'getAvailableRooms?SID=' . $this->sessionId;
$result = $this->rest->call($url, "return");
$rooms = [];
foreach ($result as $room) {
if ($room['externalRoomType'] == $type && count($room['currentusers']) > 0) {
$rooms[] = $room;
}
}
return $result;
}
/**
* Gets details of a remote room by room ID.
*
* @param int $roomId The ID of the room, as of plugin_openmeetings.room_id
*
* @return mixed Room object
*/
public function getRoomById($roomId = 0)
{
//$this->loginUser();
if (empty($this->sessionId) or empty($roomId)) {
return false;
}
$roomId = intval($roomId);
$url = $this->getRestUrl("RoomService")
."getRoomById?"
."SID=".$this->sessionId
."&rooms_id=".$roomId;
$result = $this->rest->call($url, "return");
return $result;
}
/**
* Get list of available recordings made by this instance.
*/
public function getRecordingsByExternalRooms()
{
$url = $this->getRestUrl("RoomService")
."getFlvRecordingByExternalRoomType?"
."SID=".$this->sessionId
."&externalRoomType=".urlencode($this->config["moduleKey"]);
$result = $this->rest->call($url, "return");
return $result;
}
/**
* Get the recording from the room.
*
* @param int $id Room ID
*
* @return array
*/
public function getFlvRecordingByRoomId($id)
{
$url = $this->getRestUrl("RoomService")
."getFlvRecordingByRoomId?"
."SID=".$this->sessionId
."&roomId=".urlencode($id);
$result = $this->rest->call($url, "return");
return $result;
}
/**
* Get list of available recordings made by user.
*/
public function getRecordingsByExternalUser($id)
{
$url = $this->getRestUrl("RoomService")
."getFlvRecordingByExternalUserId?"
."SID=".$this->sessionId
."&externalUserId=".$id;
$result = $this->rest->call($url, "return");
return $result;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/* See license terms in /license.txt */
/**
* Class OpenMeetingsPlugin.
*/
class OpenMeetingsPlugin extends Plugin
{
public $isCoursePlugin = true;
//When creating a new course this settings are added to the course
public $course_settings = [[
'name' => 'openmeetings_record_and_store',
'type' => 'checkbox',
]];
protected function __construct()
{
parent::__construct('2.0', 'Francis Gonzales', ['tool_enable' => 'boolean', 'host' => 'text', 'user' => 'text', 'pass' => 'text']);
}
public static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
public function install()
{
$table = Database::get_main_table('plugin_openmeetings');
// id is the internal unique ID (keeps track of historical sessions
// status is 0 for closed, 1 for open (available)
// room_id is a reference to the meeting ID on the OpenMeetings server.
// Any c_id + session_id occurence gets a unique new meeting ID to avoid issues with the number of rooms, as indicated in https://issues.apache.org/jira/browse/OPENMEETINGS-802#comment-13860340
$sql = "CREATE TABLE IF NOT EXISTS $table (
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
c_id INT unsigned NOT NULL DEFAULT 0,
session_id INT unsigned NOT NULL DEFAULT 0,
room_id INT unsigned NOT NULL DEFAULT 0,
meeting_name VARCHAR(255) NOT NULL DEFAULT '',
attendee_pw VARCHAR(255) NOT NULL DEFAULT '',
moderator_pw VARCHAR(255) NOT NULL DEFAULT '',
record INT NOT NULL DEFAULT 0,
status INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL,
closed_at DATETIME,
calendar_id INT DEFAULT 0,
welcome_msg TEXT NOT NULL DEFAULT '')";
Database::query($sql);
//Installing course settings
$this->install_course_fields_in_all_courses();
}
public function uninstall()
{
$t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
$t_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
$t_tool = Database::get_course_table(TABLE_TOOL_LIST);
//New settings
$sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_tool_enable'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_pass'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_user'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_host'";
Database::query($sql);
//Old settings deleting just in case
$sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_plugin'";
Database::query($sql);
$sql = "DELETE FROM $t_options WHERE variable = 'openmeetings_plugin'";
Database::query($sql);
// $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_plugin_host'";
// Database::query($sql);
// $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_plugin_salt'";
// Database::query($sql);
//hack to get rid of Database::query warning (please add c_id...)
$sql = "DELETE FROM $t_tool WHERE name = 'openmeetings' AND c_id = c_id";
Database::query($sql);
$t = Database::get_main_table('plugin_openmeetings');
$sql = "DROP TABLE IF EXISTS $t";
Database::query($sql);
//Deleting course settings
$this->uninstall_course_fields_in_all_courses($this->course_settings);
}
/**
* @param int $course_id
* @param bool $add_tool_link
*/
public function course_install($course_id, $add_tool_link = true)
{
//force ignoring the tools table insertion for this plugin
$this->install_course_fields($course_id, $add_tool_link);
}
}

View File

@@ -0,0 +1,186 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License") + you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Created on 03.01.2012 by eugen.schwert@gmail.com.
*
* @package chamilo.plugin.openmeetings
* @requires CURL
*/
/**
* Class OpenMeetingsRestService.
*/
class OpenMeetingsRestService
{
public function call($request, $returnAttribute = "return")
{
// This will allow you to view errors in the browser
// Note: set "display_errors" to 0 in production
// ini_set('display_errors',1);
// Report all PHP errors (notices, errors, warnings, etc.)
// error_reporting(E_ALL);
// URI used for making REST call. Each Web Service uses a unique URL.
// $request
// Initialize the session by passing the request as a parameter
$session = curl_init($request);
// Set curl options by passing session and flags
// CURLOPT_HEADER allows us to receive the HTTP header
curl_setopt($session, CURLOPT_HEADER, true);
// CURLOPT_RETURNTRANSFER will return the response
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
// Make the request
$response = curl_exec($session);
// Close the curl session
curl_close($session);
// Confirm that the request was transmitted to the OpenMeetings! Image Search Service
if (!$response) {
exit("Request OpenMeetings! OpenMeetings Service failed and no response was returned in ".__CLASS__.'::'.__FUNCTION__.'()');
}
// Create an array to store the HTTP response codes
$status_code = [];
// Use regular expressions to extract the code from the header
preg_match('/\d\d\d/', $response, $status_code);
$bt = debug_backtrace();
$caller = array_shift($bt);
$extra = ' (from '.$caller['file'].' at line '.$caller['line'].') ';
// Check the HTTP Response code and display message if status code is not 200 (OK)
switch ($status_code[0]) {
case 200:
// Success
break;
case 503:
error_log('Your call to OpenMeetings Web Services '.$extra.' failed and returned an HTTP status of 503.
That means: Service unavailable. An internal problem prevented us from returning data to you.');
return false;
break;
case 403:
error_log('Your call to OpenMeetings Web Services '.$extra.' failed and returned an HTTP status of 403.
That means: Forbidden. You do not have permission to access this resource, or are over your rate limit.');
return false;
break;
case 400:
// You may want to fall through here and read the specific XML error
error_log('Your call to OpenMeetings Web Services '.$extra.' failed and returned an HTTP status of 400.
That means: Bad request. The parameters passed to the service did not match as expected.
The exact error is returned in the XML response.');
return false;
break;
default:
error_log('Your call to OpenMeetings Web Services '.$extra.' returned an unexpected HTTP status of: '.$status_code[0]." Request ".$request);
return false;
}
// Get the XML from the response, bypassing the header
if (!($xml = strstr($response, '<ns'))) {
$xml = null;
}
$dom = new DOMDocument();
$dom->loadXML($xml);
if ($returnAttribute == "") {
//echo "XML".$xml."<br/>";
return $this->getArray($dom);
} else {
$returnNodeList = $dom->getElementsByTagName($returnAttribute);
$ret = [];
foreach ($returnNodeList as $returnNode) {
if ($returnNodeList->length == 1) {
return $this->getArray($returnNode);
} else {
$ret[] = $this->getArray($returnNode);
}
}
return $ret;
}
}
public function getArray($node)
{
if (is_null($node) || !is_object($node)) {
return $node;
}
$array = false;
/*
echo("!!!!!!!! NODE " . XML_TEXT_NODE
. " :: name = " . $node->nodeName
. " :: local = " . $node->localName
. " :: childs ? " . $node->hasChildNodes()
. " :: count = " . ($node->hasChildNodes() ? $node->childNodes->length : -1)
. " :: type = " . $node->nodeType
. " :: val = " . $node->nodeValue
. "\n");
/*
if ($node->hasAttributes()) {
foreach ($node->attributes as $attr) {
$array[$attr->nodeName] = $attr->nodeValue;
}
}
*/
if ($node->hasChildNodes()) {
foreach ($node->childNodes as $childNode) {
if ($childNode->nodeType != XML_TEXT_NODE) {
if ($node->hasAttributes()) {
foreach ($node->attributes as $attr) {
if ($attr->localName == "nil") {
return null;
}
}
}
if ($childNode->childNodes->length == 1) {
$array[$childNode->localName] = $this->getArray($childNode);
} else {
$array[$childNode->localName][] = $this->getArray($childNode);
}
} else {
return $childNode->nodeValue;
//echo("!!!!!!!! TEXT " . $childNode->nodeValue . "\n");
//$array[$childNode->localName]
}
}
}
return $array;
}
public function getError()
{
return false;
}
public function fault()
{
return false;
}
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* Definition for the room class.
*
* @package chamilo.plugin.videoconference
*/
namespace Chamilo\Plugin\OpenMeetings;
/**
* Class room.
*/
class Room
{
public $SID;
/**
* Defining plural and non-plural because of inconsistency in OpenMeetings.
*/
public $rooms_id;
public $room_id;
/**
* Status is false for closed, true for open.
*/
public $status = false;
public $name;
/**
* Room types are described here http://openmeetings.apache.org/RoomService.html#addRoomWithModerationAndExternalType
* 1 = Conference, 2 = Audience, 3 = Restricted, 4 = Interview
* $roomTypeId = ( $this->isTeacher() ) ? 1 : 2 ;.
*/
public $roomtypes_id = 1;
public $comment;
public $numberOfPartizipants = 40;
public $ispublic = false;
public $appointment = false;
public $isDemoRoom = false;
public $demoTime = 0;
public $isModeratedRoom = true;
public $externalRoomType = 'chamilolms';
public $allowUserQuestions = false;
public $isAudioOnly = false;
public $waitForRecording = true;
public $allowRecording = true;
public $chamiloCourseId;
public $chamiloSessionId;
private $table;
public function __construct()
{
$this->table = \Database::get_main_table('plugin_openmeetings');
global $_configuration;
$this->name = 'C'.api_get_course_int_id().'-'.api_get_session_id();
$accessUrl = api_get_access_url($_configuration['access_url']);
$this->externalRoomType = substr($accessUrl['url'], strpos($accessUrl['url'], '://') + 3, -1);
if (strcmp($this->externalRoomType, 'localhost') == 0) {
$this->externalRoomType = substr(api_get_path(WEB_PATH), strpos(api_get_path(WEB_PATH), '://') + 3, -1);
}
$this->externalRoomType = 'chamilolms.'.$this->externalRoomType;
}
/**
* Get Room by id.
*
* @param int $id
*/
public function getRoom($id)
{
if (!empty($id)) {
$roomData = \Database::select('*', $this->table, ['where' => ['id = ?' => $id]], 'first');
if (!empty($roomData)) {
$this->rooms_id = $this->room_id = $roomData['room_id'];
$this->status = $roomData['status'];
$this->name = $roomData['meeting_name'];
$this->comment = $roomData['welcome_msg'];
$this->allowRecording = $roomData['record'];
$this->chamiloCourseId = $roomData['c_id'];
$this->chamiloSessionId = $roomData['session_id'];
}
}
}
/**
* Sets the room ID and loads as much info as possible from the local table.
*
* @param int $id The room ID (from table.room_id)
*/
public function loadRoomId($id)
{
if (!empty($id)) {
$roomData = \Database::select('*', $this->table, ['where' => ['room_id = ?' => $id]], 'last');
if (!empty($roomData)) {
$this->rooms_id = $this->room_id = $roomData['room_id'];
$this->status = $roomData['status'];
$this->name = $roomData['meeting_name'];
$this->comment = $roomData['welcome_msg'];
$this->allowRecording = $roomData['record'];
$this->chamiloCourseId = $roomData['c_id'];
$this->chamiloSessionId = $roomData['session_id'];
}
}
}
/**
* Gets a string from a boolean attribute.
*
* @param string $attribute Name of the attribute
* @param mixed $voidReturn What to return if the value is not defined
*
* @return string The boolean value expressed as string ('true' or 'false')
*/
public function getString($attribute, $voidReturn = false)
{
if (empty($attribute)) {
return false;
}
if (!isset($this->$attribute)) {
return $voidReturn;
}
return $this->$attribute ? 'true' : 'false';
}
}

View File

@@ -0,0 +1,18 @@
<?php
/**
* Definition of OpenMeetings session class.
*
* @package chamilo.plugin.openmeetings
*/
namespace Chamilo\Plugin\OpenMeetings;
/**
* Class session.
*/
class Session
{
public function __construct()
{
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Definition of the OpenMeetings user class.
*
* @package chamilo.plugin.openmeetings
*/
namespace Chamilo\Plugin\OpenMeetings;
/**
* Class User.
*/
class User
{
public $SID;
public $username;
public $userpass;
public $firstname;
public $lastname;
public $profilePictureUrl;
public $email;
public $externalUserId;
public $externalUserType;
public $room_id;
public $becomeModeratorAsInt;
public $showAudioVideoTestAsInt;
public $allowRecording;
public $recording_id;
public function __construct()
{
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* This script initiates a videoconference session, calling the BigBlueButton API.
*
* @package chamilo.plugin.bigbluebutton
*/
/**
* Initialization.
*/
$course_plugin = 'openmeetings'; //needed in order to load the plugin lang variables
require_once __DIR__.'/config.php';
$plugin = \OpenMeetingsPlugin::create();
$tool_name = $plugin->get_lang('Videoconference');
$tpl = new Template($tool_name);
$om = new Chamilo\Plugin\OpenMeetings\OpenMeetings();
$action = isset($_GET['action']) ? $_GET['action'] : null;
$teacher = $om->isTeacher();
api_protect_course_script(true);
$message = null;
if ($teacher) {
switch ($action) {
case 'add_to_calendar':
$course_info = api_get_course_info();
$agenda = new Agenda('course');
$id = intval($_GET['id']);
$title = sprintf(get_lang('VideoConferenceXCourseX'), $id, $course_info['name']);
$content = Display::url(get_lang('GoToTheVideoConference'), $_GET['url']);
$event_id = $agenda->addEvent(
$_REQUEST['start'],
null,
'true',
$title,
$content,
['everyone']
);
if (!empty($event_id)) {
$message = Display::return_message(get_lang('VideoConferenceAddedToTheCalendar'), 'success');
} else {
$message = Display::return_message(get_lang('Error'), 'error');
}
break;
case 'copy_record_to_link_tool':
$result = $om->copy_record_to_link_tool($_GET['id'], $_GET['record_id']);
if ($result) {
$message = Display::return_message(get_lang('VideoConferenceAddedToTheLinkTool'), 'success');
} else {
$message = Display::return_message(get_lang('Error'), 'error');
}
break;
case 'delete_record':
/*$result = $om->delete_record($_GET['id']);
if ($result) {
$message = Display::return_message(get_lang('Deleted'), 'success');
} else {
$message = Display::return_message(get_lang('Error'), 'error');
}*/
break;
case 'delete':
$om->deleteMeeting($_GET['id']);
unset($om);
$message = Display::return_message(get_lang('MeetingDeleted').'<br />'.get_lang('MeetingDeletedComment'), 'success', false);
header('Location: '.api_get_self());
exit;
break;
case 'end':
$om->endMeeting($_GET['id']);
$message = Display::return_message(get_lang('MeetingClosed').'<br />'.get_lang('MeetingClosedComment'), 'success', false);
break;
case 'publish':
// Not implemented yet
//$result = $om->publish_meeting($_GET['id']);
break;
case 'unpublish':
// Not implemented yet
//$result = $om->unpublish_meeting($_GET['id']);
break;
default:
break;
}
}
$meetings = $om->getCourseMeetings();
$openMeeting = false;
$users_online = 0;
if (!empty($meetings)) {
$meetings = array_reverse($meetings);
foreach ($meetings as $meeting) {
if ($meeting['status'] == 1) {
$openMeeting = true;
}
}
$users_online = $meetings->participantCount;
}
$status = $om->isServerRunning();
$show_join_button = false;
if ($openMeeting || $teacher) {
$show_join_button = true;
}
$tpl->assign('allow_to_edit', $teacher);
$tpl->assign('meetings', $meetings);
$conference_url = api_get_path(WEB_PLUGIN_PATH).'openmeetings/start.php?launch=1&'.api_get_cidreq();
$tpl->assign('conference_url', $conference_url);
$tpl->assign('users_online', $users_online);
$tpl->assign('openmeetings_status', $status);
$tpl->assign('show_join_button', $show_join_button);
$tpl->assign('message', $message);
$listing_tpl = 'openmeetings/listing.tpl';
$content = $tpl->fetch($listing_tpl);
$tpl->assign('content', $content);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,66 @@
<div class ="row">
{% if openmeetings_status == true %}
{% if show_join_button == true %}
<div class ="span12" style="text-align:center">
<a href="{{ conference_url }}" target="_blank" class="btn btn-primary btn-large">
{{ 'EnterConference'|get_lang }}
</a>
<!--span id="users_online" class="label label-warning">{{ 'XUsersOnLine'| get_lang | format(users_online) }} </span-->
</div>
{% endif %}
<div class ="span12">
<div class="page-header">
<h2>{{ 'RecordList'|get_lang }}</h2>
</div>
<table class="table">
<tr>
<th>#</th>
<th>{{ 'CreatedAt'|get_lang }}</th>
<th>{{ 'Status'|get_lang }}</th>
<th>{{ 'Records'|get_lang }}</th>
{% if allow_to_edit %}
<th>{{ 'Actions'|get_lang }}</th>
{% endif %}
</tr>
{% for meeting in meetings %}
<tr>
<td>{{ meeting.id }}</td>
<td>{{ meeting.created_at }}</td>
<td>
{% if meeting.status == 1 %}
<span class="label label-success">{{ 'MeetingOpened'|get_lang }}</span>
{% else %}
<span class="label label-info">{{ 'MeetingClosed'|get_lang }}</span>
{% endif %}
</td>
<td>
{% if meeting.record == 1 %}
{# Record list #}
{{ meeting.show_links }}
{% endif %}
</td>
{% if allow_to_edit %}
<td>
{% if meeting.status == 1 %}
<a class="btn btn-default" href="{{ meeting.end_url }} "> {{ 'CloseMeeting' | get_lang }}</a>
{% endif %}
<a class="btn btn-danger" href="{{ meeting.delete_url }} "> {{ 'DeleteMeeting' | get_lang }}</a>
</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% else %}
<div class ="span12" style="text-align:center">
{{ 'ServerIsNotRunning' | return_message('warning') }}
</div>
{% endif %}
</div>

View File

@@ -0,0 +1,4 @@
<?php
require_once __DIR__.'/config.php';
$plugin_info = openmeetingsPlugin::create()->get_info();

View File

@@ -0,0 +1,68 @@
<?php
/**
* This script initiates a video conference session.
*/
/**
* Initialization.
*/
$course_plugin = 'openmeetings'; //needed in order to load the plugin lang variables
require_once __DIR__.'/config.php';
$tool_name = get_lang('Videoconference');
$tpl = new Template($tool_name);
$om = new \Chamilo\Plugin\OpenMeetings\OpenMeetings();
if ($om->isServerRunning()) {
if (isset($_GET['launch']) && $_GET['launch'] == 1) {
$meeting_params = [];
$meeting_params['meeting_name'] = 'C'.api_get_course_id().'-'.api_get_session_id();
$meetings = $om->getCourseMeetings();
$selectedMeeting = [];
/*
// Select the meeting with more participantCount.
if (!empty($meetings)) {
$max = 0;
foreach ($meetings as $meeting) {
if ($meeting['participantCount'] > $max) {
$selectedMeeting = $meeting;
$max = $meeting['participantCount'];
}
}
}
*/
// Check for the first meeting available with status = 1
// (there should be only one at a time, as createMeeting checks for that first
if (!empty($meetings)) {
foreach ($meetings as $meeting) {
if ($meeting['status'] == 1) {
$selectedMeeting = $meeting;
}
}
}
if (!empty($selectedMeeting)) {
$url = $om->joinMeeting($selectedMeeting['id']);
if ($url) {
header('location: '.$url);
exit;
}
} else {
if ($om->isTeacher()) {
$om->createMeeting($meeting_params);
exit;
} else {
$url = 'listing.php';
header('location: '.$url);
exit;
}
}
} else {
$url = 'listing.php';
header('location: '.$url);
exit;
}
} else {
$message = Display::return_message(get_lang('ServerIsNotRunning'), 'warning');
}
$tpl->assign('message', $message);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,14 @@
<?php
/**
* This script is included by main/admin/settings.lib.php when unselecting a plugin
* and is meant to remove things installed by the install.php script in both
* the global database and the courses tables.
*
* @package chamilo.plugin.bigbluebutton
*/
/**
* Queries.
*/
require_once __DIR__.'/config.php';
openmeetingsPlugin::create()->uninstall();