upgrade
This commit is contained in:
116
plugin/bbb/lib/VM.php
Normal file
116
plugin/bbb/lib/VM.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class VM
|
||||
*/
|
||||
class VM
|
||||
{
|
||||
protected $config;
|
||||
public $virtualMachine;
|
||||
|
||||
/**
|
||||
* VM constructor.
|
||||
* @param $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $checkEnabled Check if, additionnally to being installed, the plugin is enabled
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled(bool $checkEnabled = false): bool
|
||||
{
|
||||
$config = $this->getConfig();
|
||||
|
||||
if (!isset($config)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_array($config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($config['enabled']) && $config['enabled']) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return VirtualMachineInterface
|
||||
*/
|
||||
public function getVirtualMachine()
|
||||
{
|
||||
return $this->virtualMachine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param VirtualMachineInterface $virtualMachine
|
||||
*/
|
||||
public function setVirtualMachine(VirtualMachineInterface $virtualMachine)
|
||||
{
|
||||
$this->virtualMachine = $virtualMachine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return VirtualMachineInterface
|
||||
*/
|
||||
public function getVirtualMachineFromConfig()
|
||||
{
|
||||
$vmList = $this->config['vms'];
|
||||
|
||||
foreach ($vmList as $vm) {
|
||||
if (isset($vm['enabled']) && $vm['enabled'] == true) {
|
||||
$className = $vm['name'].'VM';
|
||||
|
||||
return new $className($vm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the VM to the max size
|
||||
*/
|
||||
public function resizeToMaxLimit()
|
||||
{
|
||||
$virtualMachine = $this->getVirtualMachineFromConfig();
|
||||
$this->setVirtualMachine($virtualMachine);
|
||||
$virtualMachine->resizeToMaxLimit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the VM to the min size
|
||||
*/
|
||||
public function resizeToMinLimit()
|
||||
{
|
||||
$virtualMachine = $this->getVirtualMachineFromConfig();
|
||||
$this->setVirtualMachine($virtualMachine);
|
||||
$virtualMachine->resizeToMinLimit();
|
||||
}
|
||||
|
||||
public function runCron()
|
||||
{
|
||||
$virtualMachine = $this->getVirtualMachineFromConfig();
|
||||
$this->setVirtualMachine($virtualMachine);
|
||||
|
||||
$virtualMachine->runCron();
|
||||
}
|
||||
}
|
||||
2232
plugin/bbb/lib/bbb.lib.php
Normal file
2232
plugin/bbb/lib/bbb.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
697
plugin/bbb/lib/bbb_api.php
Normal file
697
plugin/bbb/lib/bbb_api.php
Normal file
@@ -0,0 +1,697 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2010 Blindside Networks
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Versions:
|
||||
1.0 -- Initial version written by DJP
|
||||
(email: djp [a t ] architectes DOT .org)
|
||||
1.1 -- Updated by Omar Shammas and Sebastian Schneider
|
||||
(email : omar DOT shammas [a t ] g m ail DOT com)
|
||||
(email : seb DOT sschneider [ a t ] g m ail DOT com)
|
||||
1.2 -- Updated by Omar Shammas
|
||||
(email : omar DOT shammas [a t ] g m ail DOT com)
|
||||
1.3 -- Refactored by Peter Mentzer
|
||||
(email : peter@petermentzerdesign.com)
|
||||
- This update will BREAK your external existing code if
|
||||
you've used the previous versions <= 1.2 already so:
|
||||
-- update your external code to use new method names if needed
|
||||
-- update your external code to pass new parameters to methods
|
||||
- Working example of joinIfRunning.php now included
|
||||
- Added support for BBB 0.8b recordings
|
||||
- Now using Zend coding, naming and style conventions
|
||||
- Refactored methods to accept standardized parameters & match BBB API structure
|
||||
-- See included samples for usage examples
|
||||
*/
|
||||
|
||||
class BigBlueButtonBN
|
||||
{
|
||||
private $_securitySalt;
|
||||
private $_bbbServerBaseUrl;
|
||||
private $_bbbServerProtocol;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
/*
|
||||
Establish just our basic elements in the constructor:
|
||||
*/
|
||||
// BASE CONFIGS - set these for your BBB server in config.php and they will
|
||||
// simply flow in here via the constants:
|
||||
$this->_securitySalt = CONFIG_SECURITY_SALT;
|
||||
$this->_bbbServerBaseUrl = CONFIG_SERVER_BASE_URL;
|
||||
$this->_bbbServerProtocol = CONFIG_SERVER_PROTOCOL;
|
||||
}
|
||||
|
||||
private function _processXmlResponse($url)
|
||||
{
|
||||
/*
|
||||
A private utility method used by other public methods to process XML responses.
|
||||
*/
|
||||
if (extension_loaded('curl')) {
|
||||
$ch = curl_init() or die ( curl_error($ch) );
|
||||
$timeout = 10;
|
||||
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt( $ch, CURLOPT_URL, $this->_bbbServerProtocol.$url );
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
|
||||
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout);
|
||||
// Following redirect required to use Scalelite, BBB's Load Balancer
|
||||
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
$data = curl_exec( $ch );
|
||||
curl_close( $ch );
|
||||
|
||||
if ($data) {
|
||||
return (new SimpleXMLElement($data));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (simplexml_load_file($url));
|
||||
}
|
||||
|
||||
private function _requiredParam($param) {
|
||||
/* Process required params and throw errors if we don't get values */
|
||||
if ((isset($param)) && ($param != '')) {
|
||||
return $param;
|
||||
}
|
||||
elseif (!isset($param)) {
|
||||
throw new Exception('Missing parameter.');
|
||||
}
|
||||
else {
|
||||
throw new Exception(''.$param.' is required.');
|
||||
}
|
||||
}
|
||||
|
||||
private function _optionalParam($param) {
|
||||
/* Pass most optional params through as set value, or set to '' */
|
||||
/* Don't know if we'll use this one, but let's build it in case. */
|
||||
if ((isset($param)) && ($param != '')) {
|
||||
return $param;
|
||||
}
|
||||
else {
|
||||
$param = '';
|
||||
return $param;
|
||||
}
|
||||
}
|
||||
|
||||
/* __________________ BBB ADMINISTRATION METHODS _________________ */
|
||||
/* The methods in the following section support the following categories of the BBB API:
|
||||
-- create
|
||||
-- join
|
||||
-- end
|
||||
*/
|
||||
|
||||
public function getCreateMeetingUrl($creationParams) {
|
||||
/*
|
||||
USAGE:
|
||||
(see $creationParams array in createMeetingArray method.)
|
||||
*/
|
||||
$this->_meetingId = $this->_requiredParam($creationParams['meetingId']);
|
||||
$this->_meetingName = $this->_requiredParam($creationParams['meetingName']);
|
||||
// Set up the basic creation URL:
|
||||
$creationUrl = $this->_bbbServerBaseUrl."api/create?";
|
||||
// Add params:
|
||||
$params =
|
||||
'name='.urlencode($this->_meetingName).
|
||||
'&meetingID='.urlencode($this->_meetingId).
|
||||
'&attendeePW='.urlencode($creationParams['attendeePw']).
|
||||
'&moderatorPW='.urlencode($creationParams['moderatorPw']).
|
||||
'&dialNumber='.urlencode($creationParams['dialNumber']).
|
||||
'&voiceBridge='.urlencode($creationParams['voiceBridge']).
|
||||
'&webVoice='.urlencode($creationParams['webVoice']).
|
||||
'&logoutURL='.urlencode($creationParams['logoutUrl']).
|
||||
'&maxParticipants='.urlencode($creationParams['maxParticipants']).
|
||||
'&record='.urlencode($creationParams['record']).
|
||||
'&duration='.urlencode($creationParams['duration']).
|
||||
'&meta_OriginURL'.urlencode($creationParams['meta_OriginURL'])
|
||||
;
|
||||
|
||||
//'&meta_category='.urlencode($creationParams['meta_category']);
|
||||
$welcomeMessage = $creationParams['welcomeMsg'];
|
||||
if (trim($welcomeMessage)) {
|
||||
$params .= '&welcome='.urlencode($welcomeMessage);
|
||||
}
|
||||
|
||||
// Return the complete URL:
|
||||
return ($creationUrl.$params.'&checksum='.sha1("create".$params.$this->_securitySalt));
|
||||
}
|
||||
|
||||
public function createMeetingWithXmlResponseArray($creationParams)
|
||||
{
|
||||
/*
|
||||
USAGE:
|
||||
$creationParams = array(
|
||||
'name' => 'Meeting Name', -- A name for the meeting (or username)
|
||||
'meetingId' => '1234', -- A unique id for the meeting
|
||||
'attendeePw' => 'ap', -- Set to 'ap' and use 'ap' to join = no user pass required.
|
||||
'moderatorPw' => 'mp', -- Set to 'mp' and use 'mp' to join = no user pass required.
|
||||
'welcomeMsg' => '', -- ''= use default. Change to customize.
|
||||
'dialNumber' => '', -- The main number to call into. Optional.
|
||||
'voiceBridge' => '', -- 5 digits PIN to join voice. Required.
|
||||
'webVoice' => '', -- Alphanumeric to join voice. Optional.
|
||||
'logoutUrl' => '', -- Default in bigbluebutton.properties. Optional.
|
||||
'maxParticipants' => '-1', -- Optional. -1 = unlimitted. Not supported in BBB. [number]
|
||||
'record' => 'false', -- New. 'true' will tell BBB to record the meeting.
|
||||
'duration' => '0', -- Default = 0 which means no set duration in minutes. [number]
|
||||
'meta_category' => '', -- Use to pass additional info to BBB server. See API docs to enable.
|
||||
);
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getCreateMeetingURL($creationParams));
|
||||
|
||||
if ($xml) {
|
||||
if ($xml->meetingID) {
|
||||
return [
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'message' => $xml->message->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'meetingId' => $xml->meetingID->__toString(),
|
||||
'attendeePw' => $xml->attendeePW->__toString(),
|
||||
'moderatorPw' => $xml->moderatorPW->__toString(),
|
||||
'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded->__toString(),
|
||||
'createTime' => $xml->createTime->__toString(),
|
||||
'internalMeetingID' => $xml->internalMeetingID->__toString(),
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'message' => $xml->message->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
];
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getJoinMeetingURL($joinParams)
|
||||
{
|
||||
/*
|
||||
NOTE: At this point, we don't use a corresponding joinMeetingWithXmlResponse here because the API
|
||||
doesn't respond on success, but you can still code that method if you need it. Or, you can take the URL
|
||||
that's returned from this method and simply send your users off to that URL in your code.
|
||||
USAGE:
|
||||
$joinParams = array(
|
||||
'meetingId' => '1234', -- REQUIRED - A unique id for the meeting
|
||||
'username' => 'Jane Doe', -- REQUIRED - The name that will display for the user in the meeting
|
||||
'password' => 'ap', -- 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
|
||||
);
|
||||
*/
|
||||
$this->_meetingId = $this->_requiredParam($joinParams['meetingId']);
|
||||
$this->_username = $this->_requiredParam($joinParams['username']);
|
||||
$this->_password = $this->_requiredParam($joinParams['password']);
|
||||
|
||||
// Establish the basic join URL:
|
||||
$joinUrl = $this->_bbbServerBaseUrl."api/join?";
|
||||
|
||||
// Add parameters to the URL:
|
||||
$params =
|
||||
'meetingID='.urlencode($this->_meetingId).
|
||||
'&fullName='.urlencode($this->_username).
|
||||
'&password='.urlencode($this->_password).
|
||||
'&userID='.urlencode($joinParams['userID']).
|
||||
'&webVoiceConf='.urlencode($joinParams['webVoiceConf'])
|
||||
;
|
||||
|
||||
// Only use createTime if we really want to use it. If it's '', then don't pass it:
|
||||
if ((isset($joinParams['createTime']) && $joinParams['createTime'] != '')) {
|
||||
$params .= '&createTime='.urlencode($joinParams['createTime']);
|
||||
}
|
||||
|
||||
/*if (isset($joinParams['interface']) && (int) $joinParams['interface'] === BBBPlugin::INTERFACE_HTML5) {
|
||||
$bbbHost = api_remove_trailing_slash(CONFIG_SERVER_URL_WITH_PROTOCOL);
|
||||
if (preg_match('#/bigbluebutton$#', $bbbHost)) {
|
||||
$bbbHost = preg_replace('#/bigbluebutton$#', '', $bbbHost);
|
||||
}
|
||||
$params .= '&redirectClient=true&clientURL='.$bbbHost.'/html5client/join';
|
||||
}*/
|
||||
|
||||
// Return the URL:
|
||||
return $joinUrl.$params.'&checksum='.sha1('join'.$params.$this->_securitySalt);
|
||||
}
|
||||
|
||||
public function getEndMeetingURL($endParams)
|
||||
{
|
||||
/* USAGE:
|
||||
$endParams = array (
|
||||
'meetingId' => '1234', -- REQUIRED - The unique id for the meeting
|
||||
'password' => 'mp' -- REQUIRED - The moderator password for the meeting
|
||||
);
|
||||
*/
|
||||
$this->_meetingId = $this->_requiredParam($endParams['meetingId']);
|
||||
$this->_password = $this->_requiredParam($endParams['password']);
|
||||
$endUrl = $this->_bbbServerBaseUrl."api/end?";
|
||||
$params =
|
||||
'meetingID='.urlencode($this->_meetingId).
|
||||
'&password='.urlencode($this->_password)
|
||||
;
|
||||
|
||||
return ($endUrl.$params.'&checksum='.sha1("end".$params.$this->_securitySalt));
|
||||
}
|
||||
|
||||
public function endMeetingWithXmlResponseArray($endParams) {
|
||||
/* USAGE:
|
||||
$endParams = array (
|
||||
'meetingId' => '1234', -- REQUIRED - The unique id for the meeting
|
||||
'password' => 'mp' -- REQUIRED - The moderator password for the meeting
|
||||
);
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getEndMeetingURL($endParams));
|
||||
if ($xml) {
|
||||
return array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'message' => $xml->message->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString()
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* __________________ BBB MONITORING METHODS _________________ */
|
||||
/* The methods in the following section support the following categories of the BBB API:
|
||||
-- isMeetingRunning
|
||||
-- getMeetings
|
||||
-- getMeetingInfo
|
||||
*/
|
||||
public function getIsMeetingRunningUrl($meetingId) {
|
||||
/* USAGE:
|
||||
$meetingId = '1234' -- REQUIRED - The unique id for the meeting
|
||||
*/
|
||||
$this->_meetingId = $this->_requiredParam($meetingId);
|
||||
$runningUrl = $this->_bbbServerBaseUrl."api/isMeetingRunning?";
|
||||
$params =
|
||||
'meetingID='.urlencode($this->_meetingId);
|
||||
return ($runningUrl.$params.'&checksum='.sha1("isMeetingRunning".$params.$this->_securitySalt));
|
||||
}
|
||||
|
||||
public function isMeetingRunningWithXmlResponseArray($meetingId) {
|
||||
/* USAGE:
|
||||
$meetingId = '1234' -- REQUIRED - The unique id for the meeting
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getIsMeetingRunningUrl($meetingId));
|
||||
if($xml) {
|
||||
return array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'running' => $xml->running->__toString() // -- Returns true/false.
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getGetMeetingsUrl() {
|
||||
/* Simply formulate the getMeetings URL
|
||||
We do this in a separate function so we have the option to just get this
|
||||
URL and print it if we want for some reason.
|
||||
*/
|
||||
$getMeetingsUrl = $this->_bbbServerBaseUrl."api/getMeetings?checksum=".sha1("getMeetings".$this->_securitySalt);
|
||||
return $getMeetingsUrl;
|
||||
}
|
||||
|
||||
public function getMeetingsWithXmlResponseArray()
|
||||
{
|
||||
/* USAGE:
|
||||
We don't need to pass any parameters with this one, so we just send the query URL off to BBB
|
||||
and then handle the results that we get in the XML response.
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getGetMeetingsUrl());
|
||||
if($xml) {
|
||||
// If we don't get a success code, stop processing and return just the returncode:
|
||||
if ($xml->returncode != 'SUCCESS') {
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString()
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
elseif ($xml->messageKey == 'noMeetings') {
|
||||
/* No meetings on server, so return just this info: */
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
else {
|
||||
// In this case, we have success and meetings. First return general response:
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
// Then interate through meeting results and return them as part of the array:
|
||||
foreach ($xml->meetings->meeting as $m) {
|
||||
$result[] = array(
|
||||
'meetingId' => $m->meetingID->__toString(),
|
||||
'meetingName' => $m->meetingName->__toString(),
|
||||
'createTime' => $m->createTime->__toString(),
|
||||
'attendeePw' => $m->attendeePW->__toString(),
|
||||
'moderatorPw' => $m->moderatorPW->__toString(),
|
||||
'hasBeenForciblyEnded' => $m->hasBeenForciblyEnded->__toString(),
|
||||
'running' => $m->running->__toString()
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function getMeetingInfoUrl($infoParams) {
|
||||
/* USAGE:
|
||||
$infoParams = array(
|
||||
'meetingId' => '1234', -- REQUIRED - The unique id for the meeting
|
||||
'password' => 'mp' -- REQUIRED - The moderator password for the meeting
|
||||
);
|
||||
*/
|
||||
$this->_meetingId = $this->_requiredParam($infoParams['meetingId']);
|
||||
$this->_password = $this->_requiredParam($infoParams['password']);
|
||||
$infoUrl = $this->_bbbServerBaseUrl."api/getMeetingInfo?";
|
||||
$params =
|
||||
'meetingID='.urlencode($this->_meetingId).
|
||||
'&password='.urlencode($this->_password);
|
||||
return ($infoUrl.$params.'&checksum='.sha1("getMeetingInfo".$params.$this->_securitySalt));
|
||||
}
|
||||
|
||||
public function getMeetingInfoWithXmlResponseArray($infoParams) {
|
||||
/* USAGE:
|
||||
$infoParams = array(
|
||||
'meetingId' => '1234', -- REQUIRED - The unique id for the meeting
|
||||
'password' => 'mp' -- REQUIRED - The moderator password for the meeting
|
||||
);
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getMeetingInfoUrl($infoParams));
|
||||
if($xml) {
|
||||
// If we don't get a success code or messageKey, find out why:
|
||||
if (($xml->returncode != 'SUCCESS') || ($xml->messageKey == null)) {
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
return $result;
|
||||
} else {
|
||||
// In this case, we have success and meeting info:
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'meetingName' => $xml->meetingName->__toString(),
|
||||
'meetingId' => $xml->meetingID->__toString(),
|
||||
'createTime' => $xml->createTime->__toString(),
|
||||
'voiceBridge' => $xml->voiceBridge->__toString(),
|
||||
'attendeePw' => $xml->attendeePW->__toString(),
|
||||
'moderatorPw' => $xml->moderatorPW->__toString(),
|
||||
'running' => $xml->running->__toString(),
|
||||
'recording' => $xml->recording->__toString(),
|
||||
'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded->__toString(),
|
||||
'startTime' => $xml->startTime->__toString(),
|
||||
'endTime' => $xml->endTime->__toString(),
|
||||
'participantCount' => $xml->participantCount->__toString(),
|
||||
'maxUsers' => $xml->maxUsers->__toString(),
|
||||
'moderatorCount' => $xml->moderatorCount->__toString(),
|
||||
'internalMeetingID' => $xml->internalMeetingID->__toString()
|
||||
);
|
||||
|
||||
// Then interate through attendee results and return them as part of the array:
|
||||
foreach ($xml->attendees->attendee as $a) {
|
||||
$result[] = array(
|
||||
'userId' => $a->userID->__toString(),
|
||||
'fullName' => $a->fullName->__toString(),
|
||||
'role' => $a->role->__toString()
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* __________________ BBB RECORDING METHODS _________________ */
|
||||
/* The methods in the following section support the following categories of the BBB API:
|
||||
-- getRecordings
|
||||
-- publishRecordings
|
||||
-- deleteRecordings
|
||||
*/
|
||||
|
||||
public function getRecordingsUrl($recordingParams) {
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'meetingId' => '1234', -- OPTIONAL - comma separate if multiple ids
|
||||
);
|
||||
*/
|
||||
$recordingsUrl = $this->_bbbServerBaseUrl."api/getRecordings?";
|
||||
$params = 'meetingID='.urlencode($recordingParams['meetingId']);
|
||||
return ($recordingsUrl.$params.'&checksum='.sha1("getRecordings".$params.$this->_securitySalt));
|
||||
|
||||
}
|
||||
|
||||
public function getRecordingsWithXmlResponseArray($recordingParams) {
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'meetingId' => '1234', -- OPTIONAL - comma separate if multiple ids
|
||||
);
|
||||
NOTE: 'duration' DOES work when creating a meeting, so if you set duration
|
||||
when creating a meeting, it will kick users out after the duration. Should
|
||||
probably be required in user code when 'recording' is set to true.
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getRecordingsUrl($recordingParams));
|
||||
if($xml) {
|
||||
// If we don't get a success code or messageKey, find out why:
|
||||
if (($xml->returncode != 'SUCCESS') || ($xml->messageKey == null)) {
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
else {
|
||||
// In this case, we have success and recording info:
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
$formats = [];
|
||||
|
||||
foreach ($xml->recordings->recording as $r) {
|
||||
foreach ($r->playback->format as $format) {
|
||||
$formats[] = $format;
|
||||
}
|
||||
|
||||
$result[] = array(
|
||||
'recordId' => $r->recordID->__toString(),
|
||||
'meetingId' => $r->meetingID->__toString(),
|
||||
'name' => $r->name->__toString(),
|
||||
'published' => $r->published->__toString(),
|
||||
'startTime' => $r->startTime->__toString(),
|
||||
'endTime' => $r->endTime->__toString(),
|
||||
'playbackFormat' => $formats,
|
||||
'playbackFormatType' => $r->playback->format->type->__toString(),
|
||||
'playbackFormatUrl' => $r->playback->format->url->__toString(),
|
||||
'playbackFormatLength' => $r->playback->format->length->__toString(),
|
||||
'metadataTitle' => $r->metadata->title->__toString(),
|
||||
'metadataSubject' => $r->metadata->subject->__toString(),
|
||||
'metadataDescription' => $r->metadata->description->__toString(),
|
||||
'metadataCreator' => $r->metadata->creator->__toString(),
|
||||
'metadataContributor' => $r->metadata->contributor->__toString(),
|
||||
'metadataLanguage' => $r->metadata->language->__toString(),
|
||||
// Add more here as needed for your app depending on your
|
||||
// use of metadata when creating recordings.
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $array recordingParams
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getRecordings($recordingParams)
|
||||
{
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'meetingId' => '1234', -- OPTIONAL - comma separate if multiple ids
|
||||
);
|
||||
NOTE: 'duration' DOES work when creating a meeting, so if you set duration
|
||||
when creating a meeting, it will kick users out after the duration. Should
|
||||
probably be required in user code when 'recording' is set to true.
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getRecordingsUrl($recordingParams));
|
||||
if($xml) {
|
||||
// If we don't get a success code or messageKey, find out why:
|
||||
if (($xml->returncode != 'SUCCESS') || ($xml->messageKey == null)) {
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
else {
|
||||
// In this case, we have success and recording info:
|
||||
$result = array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'messageKey' => $xml->messageKey->__toString(),
|
||||
'message' => $xml->message->__toString()
|
||||
);
|
||||
$result['records'] = [];
|
||||
if (!empty($xml->recordings->recording)) {
|
||||
$formats = [];
|
||||
|
||||
foreach ($xml->recordings->recording as $r) {
|
||||
foreach ($r->playback->format as $format) {
|
||||
$formats[] = $format;
|
||||
}
|
||||
$result['records'][] = array(
|
||||
'recordId' => $r->recordID->__toString(),
|
||||
'meetingId' => $r->meetingID->__toString(),
|
||||
'name' => $r->name->__toString(),
|
||||
'published' => $r->published->__toString(),
|
||||
'startTime' => $r->startTime->__toString(),
|
||||
'endTime' => $r->endTime->__toString(),
|
||||
'playbackFormat' => $formats,
|
||||
'playbackFormatType' => $r->playback->format->type->__toString(),
|
||||
'playbackFormatUrl' => $r->playback->format->url->__toString(),
|
||||
'playbackFormatLength' => $r->playback->format->length->__toString(),
|
||||
'metadataTitle' => $r->metadata->title->__toString(),
|
||||
'metadataSubject' => $r->metadata->subject->__toString(),
|
||||
'metadataDescription' => $r->metadata->description->__toString(),
|
||||
'metadataCreator' => $r->metadata->creator->__toString(),
|
||||
'metadataContributor' => $r->metadata->contributor->__toString(),
|
||||
'metadataLanguage' => $r->metadata->language->__toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPublishRecordingsUrl($recordingParams) {
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'recordId' => '1234', -- REQUIRED - comma separate if multiple ids
|
||||
'publish' => 'true', -- REQUIRED - boolean: true/false
|
||||
);
|
||||
*/
|
||||
$recordingsUrl = $this->_bbbServerBaseUrl."api/publishRecordings?";
|
||||
$params =
|
||||
'recordID='.urlencode($recordingParams['recordId']).
|
||||
'&publish='.urlencode($recordingParams['publish']);
|
||||
return ($recordingsUrl.$params.'&checksum='.sha1("publishRecordings".$params.$this->_securitySalt));
|
||||
|
||||
}
|
||||
|
||||
public function publishRecordingsWithXmlResponseArray($recordingParams) {
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'recordId' => '1234', -- REQUIRED - comma separate if multiple ids
|
||||
'publish' => 'true', -- REQUIRED - boolean: true/false
|
||||
);
|
||||
*/
|
||||
$xml = $this->_processXmlResponse($this->getPublishRecordingsUrl($recordingParams));
|
||||
if($xml) {
|
||||
return array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'published' => $xml->published->__toString() // -- Returns true/false.
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function getDeleteRecordingsUrl($recordingParams) {
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'recordId' => '1234', -- REQUIRED - comma separate if multiple ids
|
||||
);
|
||||
*/
|
||||
$recordingsUrl = $this->_bbbServerBaseUrl."api/deleteRecordings?";
|
||||
$params =
|
||||
'recordID='.urlencode($recordingParams['recordId']);
|
||||
return ($recordingsUrl.$params.'&checksum='.sha1("deleteRecordings".$params.$this->_securitySalt));
|
||||
}
|
||||
|
||||
public function deleteRecordingsWithXmlResponseArray($recordingParams) {
|
||||
/* USAGE:
|
||||
$recordingParams = array(
|
||||
'recordId' => '1234', -- REQUIRED - comma separate if multiple ids
|
||||
);
|
||||
*/
|
||||
|
||||
$xml = $this->_processXmlResponse($this->getDeleteRecordingsUrl($recordingParams));
|
||||
if($xml) {
|
||||
return array(
|
||||
'returncode' => $xml->returncode->__toString(),
|
||||
'deleted' => $xml->deleted->__toString() // -- Returns true/false.
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** USAGE:
|
||||
* $recordingParams = array(
|
||||
* 'recordId' => '1234', -- REQUIRED - comma separate if multiple ids
|
||||
* );
|
||||
*/
|
||||
public function generateRecording($recordingParams)
|
||||
{
|
||||
if (empty($recordingParams)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$recordingsUrl = $this->_bbbServerBaseUrl.'../demo/regenerateRecord.jsp?';
|
||||
$params = 'recordID='.urlencode($recordingParams['recordId']);
|
||||
$url = $recordingsUrl.$params.'&checksum='.sha1('regenerateRecord'.$params.$this->_securitySalt);
|
||||
|
||||
$ch = curl_init() or die ( curl_error($ch) );
|
||||
$timeout = 10;
|
||||
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt( $ch, CURLOPT_URL, $url );
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
|
||||
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout);
|
||||
$data = curl_exec( $ch );
|
||||
curl_close( $ch );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
407
plugin/bbb/lib/bbb_plugin.class.php
Normal file
407
plugin/bbb/lib/bbb_plugin.class.php
Normal file
@@ -0,0 +1,407 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/* To show the plugin course icons you need to add these icons:
|
||||
* main/img/icons/22/plugin_name.png
|
||||
* main/img/icons/64/plugin_name.png
|
||||
* main/img/icons/64/plugin_name_na.png
|
||||
*/
|
||||
|
||||
/**
|
||||
* Videoconference plugin with BBB
|
||||
*/
|
||||
class BBBPlugin extends Plugin
|
||||
{
|
||||
const ROOM_OPEN = 0;
|
||||
const ROOM_CLOSE = 1;
|
||||
const ROOM_CHECK = 2;
|
||||
|
||||
public $isCoursePlugin = true;
|
||||
|
||||
// When creating a new course this settings are added to the course
|
||||
public $course_settings = [
|
||||
[
|
||||
'name' => 'big_blue_button_record_and_store',
|
||||
'type' => 'checkbox',
|
||||
],
|
||||
[
|
||||
'name' => 'bbb_enable_conference_in_groups',
|
||||
'type' => 'checkbox',
|
||||
],
|
||||
[
|
||||
'name' => 'bbb_force_record_generation',
|
||||
'type' => 'checkbox',
|
||||
],
|
||||
[
|
||||
'name' => 'big_blue_button_students_start_conference_in_groups',
|
||||
'type' => 'checkbox',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* BBBPlugin constructor.
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
$settings = [
|
||||
'tool_enable' => 'boolean',
|
||||
'host' => 'text',
|
||||
'salt' => 'text',
|
||||
'enable_global_conference' => 'boolean',
|
||||
'enable_global_conference_per_user' => 'boolean',
|
||||
'enable_conference_in_course_groups' => 'boolean',
|
||||
'enable_global_conference_link' => 'boolean',
|
||||
'disable_download_conference_link' => 'boolean',
|
||||
'max_users_limit' => 'text',
|
||||
'global_conference_allow_roles' => [
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
PLATFORM_ADMIN => get_lang('Administrator'),
|
||||
COURSEMANAGER => get_lang('Teacher'),
|
||||
STUDENT => get_lang('Student'),
|
||||
STUDENT_BOSS => get_lang('StudentBoss'),
|
||||
],
|
||||
'attributes' => ['multiple' => 'multiple'],
|
||||
],
|
||||
'allow_regenerate_recording' => 'boolean',
|
||||
// Default course settings, must be the same as $course_settings
|
||||
'big_blue_button_record_and_store' => 'checkbox',
|
||||
'bbb_enable_conference_in_groups' => 'checkbox',
|
||||
'bbb_force_record_generation' => 'checkbox',
|
||||
'disable_course_settings' => 'boolean',
|
||||
'meeting_duration' => 'text',
|
||||
];
|
||||
|
||||
if (1 === (int) api_get_current_access_url_id()) {
|
||||
$settings['plugin_bbb_multiple_urls_cron_apply_to_all'] = 'checkbox';
|
||||
}
|
||||
|
||||
parent::__construct(
|
||||
'2.11',
|
||||
'Julio Montoya, Yannick Warnier, Angel Fernando Quiroz Campos, Jose Angel Ruiz, Ghazi Triki, Adnen Manssouri',
|
||||
$settings
|
||||
);
|
||||
|
||||
$this->isAdminPlugin = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BBBPlugin|null
|
||||
*/
|
||||
public static function create()
|
||||
{
|
||||
static $result = null;
|
||||
|
||||
return $result ? $result : $result = new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $variable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validateCourseSetting($variable)
|
||||
{
|
||||
if ($this->get('disable_course_settings') === 'true') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = true;
|
||||
switch ($variable) {
|
||||
case 'bbb_enable_conference_in_groups':
|
||||
$result = $this->get('enable_conference_in_course_groups') === 'true';
|
||||
break;
|
||||
case 'bbb_force_record_generation':
|
||||
$result = $this->get('allow_regenerate_recording') === 'true';
|
||||
break;
|
||||
case 'big_blue_button_record_and_store':
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCourseSettings()
|
||||
{
|
||||
$settings = [];
|
||||
if ($this->get('disable_course_settings') !== 'true') {
|
||||
$settings = parent::getCourseSettings();
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \Plugin
|
||||
*/
|
||||
public function performActionsAfterConfigure()
|
||||
{
|
||||
$result = $this->get('disable_course_settings') === 'true';
|
||||
if ($result) {
|
||||
$valueConference = $this->get('bbb_enable_conference_in_groups') === 'true' ? 1 : 0;
|
||||
self::update_course_field_in_all_courses('bbb_enable_conference_in_groups', $valueConference);
|
||||
|
||||
$valueForceRecordGeneration = $this->get('bbb_force_record_generation') === 'true' ? 1 : 0;
|
||||
self::update_course_field_in_all_courses('bbb_force_record_generation', $valueForceRecordGeneration);
|
||||
|
||||
$valueForceRecordStore = $this->get('big_blue_button_record_and_store') === 'true' ? 1 : 0;
|
||||
self::update_course_field_in_all_courses('big_blue_button_record_and_store', $valueForceRecordStore);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$sql = "CREATE TABLE IF NOT EXISTS plugin_bbb_meeting (
|
||||
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
|
||||
c_id INT unsigned NOT NULL DEFAULT 0,
|
||||
group_id INT unsigned NOT NULL DEFAULT 0,
|
||||
user_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 VARCHAR(255) NOT NULL,
|
||||
closed_at VARCHAR(255) NOT NULL,
|
||||
calendar_id INT DEFAULT 0,
|
||||
welcome_msg VARCHAR(255) NOT NULL DEFAULT '',
|
||||
session_id INT unsigned DEFAULT 0,
|
||||
remote_id CHAR(30),
|
||||
internal_meeting_id VARCHAR(255) DEFAULT NULL,
|
||||
visibility TINYINT NOT NULL DEFAULT 1,
|
||||
voice_bridge INT NOT NULL DEFAULT 1,
|
||||
access_url INT NOT NULL DEFAULT 1,
|
||||
video_url TEXT NULL,
|
||||
has_video_m4v TINYINT NOT NULL DEFAULT 0
|
||||
)";
|
||||
Database::query($sql);
|
||||
|
||||
Database::query(
|
||||
"CREATE TABLE IF NOT EXISTS plugin_bbb_room (
|
||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
meeting_id int NOT NULL,
|
||||
participant_id int(11) NOT NULL,
|
||||
in_at datetime,
|
||||
out_at datetime,
|
||||
close INT NOT NULL DEFAULT 0
|
||||
);"
|
||||
);
|
||||
$fieldLabel = 'plugin_bbb_course_users_limit';
|
||||
$fieldType = ExtraField::FIELD_TYPE_INTEGER;
|
||||
$fieldTitle = $this->get_lang('MaxUsersInConferenceRoom');
|
||||
$fieldDefault = '0';
|
||||
$extraField = new ExtraField('course');
|
||||
$fieldId = CourseManager::create_course_extra_field(
|
||||
$fieldLabel,
|
||||
$fieldType,
|
||||
$fieldTitle,
|
||||
$fieldDefault
|
||||
);
|
||||
$extraField->find($fieldId);
|
||||
$extraField->update(
|
||||
[
|
||||
'id' => $fieldId,
|
||||
'variable' => 'plugin_bbb_course_users_limit',
|
||||
'changeable' => 1,
|
||||
'visible_to_self' => 1,
|
||||
'visible_to_others' => 0,
|
||||
]
|
||||
);
|
||||
$fieldLabel = 'plugin_bbb_session_users_limit';
|
||||
$extraField = new ExtraField('session');
|
||||
$fieldId = SessionManager::create_session_extra_field(
|
||||
$fieldLabel,
|
||||
$fieldType,
|
||||
$fieldTitle,
|
||||
$fieldDefault
|
||||
);
|
||||
$extraField->find($fieldId);
|
||||
$extraField->update(
|
||||
[
|
||||
'id' => $fieldId,
|
||||
'variable' => 'plugin_bbb_session_users_limit',
|
||||
'changeable' => 1,
|
||||
'visible_to_self' => 1,
|
||||
'visible_to_others' => 0,
|
||||
]
|
||||
);
|
||||
|
||||
Database::query(
|
||||
"CREATE TABLE IF NOT EXISTS plugin_bbb_meeting_format (
|
||||
id int unsigned not null PRIMARY KEY AUTO_INCREMENT,
|
||||
meeting_id int unsigned not null,
|
||||
format_type varchar(255) not null,
|
||||
resource_url text not null
|
||||
);"
|
||||
);
|
||||
|
||||
// Copy icons into the main/img/icons folder
|
||||
$iconName = 'bigbluebutton';
|
||||
$iconsList = [
|
||||
'64/'.$iconName.'.png',
|
||||
'64/'.$iconName.'_na.png',
|
||||
'32/'.$iconName.'.png',
|
||||
'32/'.$iconName.'_na.png',
|
||||
'22/'.$iconName.'.png',
|
||||
'22/'.$iconName.'_na.png',
|
||||
];
|
||||
$sourceDir = api_get_path(SYS_PLUGIN_PATH).'bbb/resources/img/';
|
||||
$destinationDir = api_get_path(SYS_CODE_PATH).'img/icons/';
|
||||
foreach ($iconsList as $icon) {
|
||||
$src = $sourceDir.$icon;
|
||||
$dest = $destinationDir.$icon;
|
||||
copy($src, $dest);
|
||||
}
|
||||
// Installing course settings
|
||||
$this->install_course_fields_in_all_courses(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall
|
||||
*/
|
||||
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);
|
||||
|
||||
$variables = [
|
||||
'bbb_salt',
|
||||
'bbb_host',
|
||||
'bbb_tool_enable',
|
||||
'enable_global_conference',
|
||||
'enable_global_conference_per_user',
|
||||
'enable_global_conference_link',
|
||||
'disable_download_conference_link',
|
||||
'enable_conference_in_course_groups',
|
||||
'bbb_plugin',
|
||||
'bbb_plugin_host',
|
||||
'bbb_plugin_salt',
|
||||
'max_users_limit',
|
||||
'global_conference_allow_roles'
|
||||
];
|
||||
|
||||
$urlId = api_get_current_access_url_id();
|
||||
|
||||
foreach ($variables as $variable) {
|
||||
$sql = "DELETE FROM $t_settings WHERE variable = '$variable' AND access_url = $urlId";
|
||||
Database::query($sql);
|
||||
}
|
||||
|
||||
$em = Database::getManager();
|
||||
$sm = $em->getConnection()->getSchemaManager();
|
||||
if ($sm->tablesExist('plugin_bbb_meeting')) {
|
||||
Database::query("DELETE FROM plugin_bbb_meeting WHERE access_url = $urlId");
|
||||
}
|
||||
|
||||
// Only delete tables if it's uninstalled from main url.
|
||||
if (1 == $urlId) {
|
||||
$extraField = new ExtraField('course');
|
||||
$extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
|
||||
'plugin_bbb_course_users_limit'
|
||||
);
|
||||
if (!empty($extraFieldInfo)) {
|
||||
$extraField->delete($extraFieldInfo['id']);
|
||||
}
|
||||
$extraField = new ExtraField('session');
|
||||
$extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
|
||||
'plugin_bbb_session_users_limit'
|
||||
);
|
||||
if (!empty($extraFieldInfo)) {
|
||||
$extraField->delete($extraFieldInfo['id']);
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM $t_options WHERE variable = 'bbb_plugin'";
|
||||
Database::query($sql);
|
||||
|
||||
// hack to get rid of Database::query warning (please add c_id...)
|
||||
$sql = "DELETE FROM $t_tool WHERE name = 'bbb' AND c_id != 0";
|
||||
Database::query($sql);
|
||||
|
||||
if ($sm->tablesExist('plugin_bbb_meeting_format')) {
|
||||
Database::query('DROP TABLE IF EXISTS plugin_bbb_meeting_format');
|
||||
}
|
||||
if ($sm->tablesExist('plugin_bbb_room')) {
|
||||
Database::query('DROP TABLE IF EXISTS plugin_bbb_room');
|
||||
}
|
||||
if ($sm->tablesExist('plugin_bbb_meeting')) {
|
||||
Database::query('DROP TABLE IF EXISTS plugin_bbb_meeting');
|
||||
}
|
||||
|
||||
// Deleting course settings
|
||||
$this->uninstall_course_fields_in_all_courses($this->course_settings);
|
||||
|
||||
// Remove icons from the main/img/icons folder
|
||||
$iconName = 'bigbluebutton';
|
||||
$iconsList = [
|
||||
'64/'.$iconName.'.png',
|
||||
'64/'.$iconName.'_na.png',
|
||||
'32/'.$iconName.'.png',
|
||||
'32/'.$iconName.'_na.png',
|
||||
'22/'.$iconName.'.png',
|
||||
'22/'.$iconName.'_na.png',
|
||||
];
|
||||
$destinationDir = api_get_path(SYS_CODE_PATH).'img/icons/';
|
||||
foreach ($iconsList as $icon) {
|
||||
$dest = $destinationDir.$icon;
|
||||
if (is_file($dest)) {
|
||||
@unlink($dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$sql = "SHOW COLUMNS FROM plugin_bbb_room WHERE Field = 'close'";
|
||||
$res = Database::query($sql);
|
||||
|
||||
if (Database::num_rows($res) === 0) {
|
||||
$sql = "ALTER TABLE plugin_bbb_room ADD close int unsigned NULL";
|
||||
$res = Database::query($sql);
|
||||
if (!$res) {
|
||||
echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning');
|
||||
}
|
||||
|
||||
Database::update(
|
||||
'plugin_bbb_room',
|
||||
['close' => BBBPlugin::ROOM_CLOSE]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the course setting in all courses
|
||||
*
|
||||
* @param bool $variable Course setting to update
|
||||
* @param bool $value New values of the course setting
|
||||
*/
|
||||
public function update_course_field_in_all_courses($variable, $value)
|
||||
{
|
||||
// Update existing courses to add the new course setting value
|
||||
$table = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$sql = "SELECT id FROM $table ORDER BY id";
|
||||
$res = Database::query($sql);
|
||||
$courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
|
||||
while ($row = Database::fetch_assoc($res)) {
|
||||
Database::update(
|
||||
$courseSettingTable,
|
||||
['value' => $value],
|
||||
['variable = ? AND c_id = ?' => [$variable, $row['id']]]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
plugin/bbb/lib/vm/AbstractVM.php
Normal file
50
plugin/bbb/lib/vm/AbstractVM.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class AbstractVM
|
||||
*/
|
||||
abstract class AbstractVM
|
||||
{
|
||||
public $name;
|
||||
public $host;
|
||||
public $user;
|
||||
public $vmId;
|
||||
public $vmMinSize;
|
||||
public $vmMaxSize;
|
||||
public $apiKey;
|
||||
public $vmClientId;
|
||||
public $messages = array();
|
||||
protected $connector;
|
||||
|
||||
/**
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct($settings)
|
||||
{
|
||||
$this->name = $settings['name'];
|
||||
$this->host = $settings['host'];
|
||||
$this->user = $settings['user'];
|
||||
$this->apiKey = $settings['api_key'];
|
||||
$this->vmId = $settings['vm_id'];
|
||||
$this->vmMinSize = $settings['vm_min_size_id'];
|
||||
$this->vmMaxSize = $settings['vm_max_size_id'];
|
||||
$this->vmClientId = $settings['vm_client_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*/
|
||||
public function addMessage($message)
|
||||
{
|
||||
$this->messages[] = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessageToString()
|
||||
{
|
||||
return implode(PHP_EOL, $this->messages);
|
||||
}
|
||||
}
|
||||
44
plugin/bbb/lib/vm/AmazonVM.php
Normal file
44
plugin/bbb/lib/vm/AmazonVM.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use DigitalOcean\DigitalOcean;
|
||||
use DigitalOcean\Credentials;
|
||||
|
||||
/**
|
||||
* Class AmazonVM
|
||||
*/
|
||||
class AmazonVM extends AbstractVM implements VirtualMachineInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function runCron()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function resizeToMaxLimit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function resizeToMinLimit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
180
plugin/bbb/lib/vm/DigitalOceanVM.php
Normal file
180
plugin/bbb/lib/vm/DigitalOceanVM.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use DigitalOcean\DigitalOcean;
|
||||
use DigitalOcean\Credentials;
|
||||
|
||||
/**
|
||||
* Class DigitalOceanVM
|
||||
*/
|
||||
class DigitalOceanVM extends AbstractVM implements VirtualMachineInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct($settings)
|
||||
{
|
||||
parent::__construct($settings);
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
// Set up your credentials.
|
||||
$credentials = new Credentials($this->vmClientId, $this->apiKey);
|
||||
// Use the default adapter, CurlHttpAdapter.
|
||||
$this->connector = new DigitalOcean($credentials);
|
||||
|
||||
// Or use BuzzHttpAdapter.
|
||||
//$this->connector = new DigitalOcean($credentials, new BuzzHttpAdapter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DigitalOcean
|
||||
*/
|
||||
public function getConnector()
|
||||
{
|
||||
return $this->connector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type min or max
|
||||
*/
|
||||
public function resizeTo($type = 'min')
|
||||
{
|
||||
try {
|
||||
$droplets = $this->getConnector()->droplets();
|
||||
$sizes = $this->getConnector()->sizes();
|
||||
$availableSizes = $sizes->getAll();
|
||||
|
||||
if (isset($availableSizes->status) && $availableSizes->status == 'OK') {
|
||||
|
||||
$minSizeIdExists = false;
|
||||
$maxSizeIdExists = false;
|
||||
|
||||
foreach ($availableSizes->sizes as $size) {
|
||||
if ($size->id == $this->vmMaxSize) {
|
||||
$maxSizeIdExists = true;
|
||||
}
|
||||
if ($size->id == $this->vmMinSizeSize) {
|
||||
$minSizeIdExists = true;
|
||||
}
|
||||
}
|
||||
if ($maxSizeIdExists && $minSizeIdExists) {
|
||||
throw new \Exception('Sizes are not well configured');
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('Sizes not available');
|
||||
}
|
||||
|
||||
// Returns all active droplets that are currently running in your account.
|
||||
//$allActive = $droplets->showAllActive();
|
||||
|
||||
$dropletInfo = $droplets->show($this->vmId);
|
||||
|
||||
if ($dropletInfo->status == 'OK') {
|
||||
switch ($type) {
|
||||
case 'min':
|
||||
if ($dropletInfo->droplet->size_id == $this->vmMinSize) {
|
||||
// No resize
|
||||
$this->addMessage(
|
||||
'Nothing to execute. The size was already reduced.'
|
||||
);
|
||||
} else {
|
||||
$this->resize($this->vmMinSize);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'max':
|
||||
if ($dropletInfo->droplet->size_id == $this->vmMaxSize) {
|
||||
// No resize
|
||||
$this->addMessage(
|
||||
'Nothing to execute. The size was already boost.'
|
||||
);
|
||||
} else {
|
||||
$this->resize($this->vmMaxSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
throw new \Exception(" Id ".$this->vmId." doesn't exists.");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off / resize / turns on
|
||||
* @param int $sizeId
|
||||
*/
|
||||
public function resize($sizeId)
|
||||
{
|
||||
$droplets = $this->getConnector()->droplets();
|
||||
$dropletInfo = $droplets->show($this->vmId);
|
||||
|
||||
$powerOff = $droplets->powerOff($this->vmId);
|
||||
|
||||
$this->addMessage('Power off droplet #'.$this->vmId);
|
||||
|
||||
$this->waitForEvent($powerOff->event_id);
|
||||
|
||||
$this->addMessage('Current status: '.$dropletInfo->droplet->status);
|
||||
|
||||
$resizeDroplet = $droplets->resize(
|
||||
$this->vmId,
|
||||
array('size_id' => intval($sizeId))
|
||||
);
|
||||
$this->addMessage('Resize droplet to size id: '.$sizeId);
|
||||
$this->waitForEvent($resizeDroplet->event_id);
|
||||
|
||||
$powerOn = $droplets->powerOn($this->vmId);
|
||||
$this->waitForEvent($powerOn->event_id);
|
||||
$this->addMessage('Power on droplet #'.$this->vmId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops until an event answer 100 percentage
|
||||
* @param int $eventId
|
||||
*/
|
||||
public function waitForEvent($eventId)
|
||||
{
|
||||
$events = $this->getConnector()->events();
|
||||
$status = false;
|
||||
while ($status == false) {
|
||||
$infoStatus = $events->show($eventId);
|
||||
if ($infoStatus->status == 'OK' && $infoStatus->event->percentage == 100) {
|
||||
$status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function runCron()
|
||||
{
|
||||
$this->resizeToMinLimit();
|
||||
echo $this->getMessageToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function resizeToMaxLimit()
|
||||
{
|
||||
$this->resizeTo('max');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function resizeToMinLimit()
|
||||
{
|
||||
$this->resizeTo('min');
|
||||
}
|
||||
}
|
||||
29
plugin/bbb/lib/vm/VMInterface.php
Normal file
29
plugin/bbb/lib/vm/VMInterface.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Interface VirtualMachineInterface
|
||||
*/
|
||||
interface VirtualMachineInterface
|
||||
{
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function connect();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function runCron();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function resizeToMaxLimit();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function resizeToMinLimit();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user