* Status / Videoconference: add support for BigBlueButton videoconferencing, it can be configured via Status app's site-configuration

This commit is contained in:
Hadi Nategh 2020-12-04 17:45:15 +01:00
parent ef95d2df6a
commit 8370e44fbe
7 changed files with 152 additions and 25 deletions

View File

@ -232,6 +232,25 @@ class calendar_boupdate extends calendar_bo
$messages[] = lang('Status of participants set to unknown because of missing category rights');
}
}
// generate a video-room-url, if we need one and not already have one
if ($event['videoconference'] && empty($event['##videoconference']) && class_exists('EGroupware\\Status\\Videoconference\\Call')
&& !EGroupware\Status\Hooks::isVideoconferenceDisabled())
{
$event['##videoconference'] = EGroupware\Status\Videoconference\Call::genUniqueRoomID();
}
elseif (isset($event['videoconference']) && !$event['videoconference'])
{
$event['##videoconference'] = '';
}
// update videoconference resource amounts based on number of participants
if ($event['videoconference'] && !empty($event['##videoconference']) && class_exists('EGroupware\\Status\\Videoconference\\Call')
&& !EGroupware\Status\Hooks::isVideoconferenceDisabled() && ($videoconferenceResId = \EGroupware\Status\Hooks::getVideoconferenceResourceId()))
{
$event['participant_types']['r'][$videoconferenceResId] =
$event['participants']['r'.$videoconferenceResId] = 'A'.(count($event['participant_types']['u']) + count($event['participant_types']['e']) + count($event['participant_types']['c']));
}
// check for conflicts only happens !$ignore_conflicts AND if start + end date are given
$checked_excluding = null;
if (!$ignore_conflicts && !$event['non_blocking'] && isset($event['start']) && isset($event['end']) &&
@ -247,16 +266,7 @@ class calendar_boupdate extends calendar_bo
return $conflicts;
}
// generate a video-room-url, if we need one and not already have one
if ($event['videoconference'] && empty($event['##videoconference']) && class_exists('EGroupware\\Status\\Videoconference\\Call')
&& !EGroupware\Status\Hooks::isVideoconferenceDisabled())
{
$event['##videoconference'] = EGroupware\Status\Videoconference\Call::genUniqueRoomID();
}
elseif (isset($event['videoconference']) && !$event['videoconference'])
{
$event['##videoconference'] = '';
}
//echo "saving $event[id]="; _debug_array($event);
$event2save = $event;
@ -1086,7 +1096,8 @@ class calendar_boupdate extends calendar_bo
'name' => $fullname,
'email' => is_numeric($userid) ? Api\Accounts::id2name($userid, 'account_email') : $userid,
'avatar' => (string)$avatar,
'account_id' => $userid
'account_id' => $userid,
'cal_id' => $details['id']
], [], $startdate, $enddate);
$event_arr['videoconference'] = [
'field' => lang('Video Conference'),
@ -1105,7 +1116,7 @@ class calendar_boupdate extends calendar_bo
switch($msg_type == MSG_ALARM ? 'extended' : $part_prefs['calendar']['update_format'])
{
case 'ical':
if (is_null($ics) || $m_type != $msg_type) // need different ical for organizer notification
if (is_null($ics) || $m_type != $msg_type || $event['##videoconference']) // need different ical for organizer notification or videoconference join urls
{
$calendar_ical = new calendar_ical();
$calendar_ical->setSupportedFields('full'); // full iCal fields+event TZ

View File

@ -687,7 +687,8 @@ class calendar_groupdav extends Api\CalDAV\Handler
'name' => Api\Accounts::username($user),
'email' => Api\Accounts::id2name($user, 'account_email'),
'avatar' => (string)$avatar,
'account_id' => $user
'account_id' => $user,
'cal_id' => $event['id']
], [], $event['start_date'], $event['end_date']);
$event['description'] = lang('Videoconference').":\n$link\n\n".$event['description'];
}

View File

@ -3551,7 +3551,7 @@ var CalendarApp = /** @class */ (function (_super) {
*/
CalendarApp.prototype.joinVideoConferenceAction = function (_action, _sender) {
var data = egw.dataGetUIDdata(_sender[0].id)['data'];
return this.joinVideoConference(data['##videoconference']);
return this.joinVideoConference(data['##videoconference'], data);
};
/**
* Join a videoconference
@ -3560,14 +3560,20 @@ var CalendarApp = /** @class */ (function (_super) {
*
* @param {string} videoconference
*/
CalendarApp.prototype.joinVideoConference = function (videoconference) {
CalendarApp.prototype.joinVideoConference = function (videoconference, _data) {
return egw.json("EGroupware\\Status\\Videoconference\\Call::ajax_genMeetingUrl", [videoconference,
{
name: egw.user('account_fullname'),
account_id: egw.user('account_id'),
email: egw.user('account_email')
}], function (_url) {
app.status.openCall(_url);
email: egw.user('account_email'),
cal_id: _data.id
}, _data.start, _data.end], function (_value) {
if (_value) {
if (_value.err)
egw.message(_value.err, 'error');
if (_value.url)
app.status.openCall(_value.url);
}
}).sendRequest();
};
/**

View File

@ -4408,7 +4408,7 @@ class CalendarApp extends EgwApp
{
let data = egw.dataGetUIDdata(_sender[0].id)['data'];
return this.joinVideoConference(data['##videoconference']);
return this.joinVideoConference(data['##videoconference'], data);
}
/**
@ -4418,7 +4418,7 @@ class CalendarApp extends EgwApp
*
* @param {string} videoconference
*/
public joinVideoConference(videoconference)
public joinVideoConference(videoconference, _data)
{
return egw.json(
"EGroupware\\Status\\Videoconference\\Call::ajax_genMeetingUrl",
@ -4426,9 +4426,14 @@ class CalendarApp extends EgwApp
{
name:egw.user('account_fullname'),
account_id:egw.user('account_id'),
email:egw.user('account_email')
}], function(_url){
app.status.openCall(_url);
email:egw.user('account_email'),
cal_id:_data.id
}, _data.start, _data.end], function(_value){
if (_value)
{
if (_value.err) egw.message(_value.err, 'error');
if(_value.url) app.status.openCall(_value.url);
}
}).sendRequest();
}
}

View File

@ -64,6 +64,7 @@
"ext-xml": "*",
"ext-xsl": "*",
"adldap2/adldap2": "=4.0.4",
"bigbluebutton/bigbluebutton-api-php": "^2.0",
"bower-asset/cropper": "2.3.*",
"bower-asset/diff2html": "^2.7",
"bower-asset/fastclick": "1.0.*",

56
composer.lock generated
View File

@ -102,6 +102,62 @@
"homepage": "https://github.com/Bacon/BaconQrCode",
"time": "2017-10-17T09:59:25+00:00"
},
{
"name": "bigbluebutton/bigbluebutton-api-php",
"version": "2.0.9",
"source": {
"type": "git",
"url": "https://github.com/bigbluebutton/bigbluebutton-api-php.git",
"reference": "3256e88c0870ee201816ac80e193ba41eaccfd45"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bigbluebutton/bigbluebutton-api-php/zipball/3256e88c0870ee201816ac80e193ba41eaccfd45",
"reference": "3256e88c0870ee201816ac80e193ba41eaccfd45",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"php": ">=5.4"
},
"require-dev": {
"composer/composer": "1.7.*@dev",
"ext-mbstring": "*",
"friendsofphp/php-cs-fixer": "2.*",
"fzaninotto/faker": "~1.8.0",
"php": ">=7.0",
"php-coveralls/php-coveralls": "2.1.*",
"phpunit/phpunit": "6.*",
"squizlabs/php_codesniffer": "3.*"
},
"type": "library",
"autoload": {
"psr-4": {
"BigBlueButton\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-3.0"
],
"authors": [
{
"name": "Ghazi Triki",
"email": "ghazi.nocturne@gmail.com",
"role": "Developer"
}
],
"description": "BigBlueButton PHP API Library for PHP",
"homepage": "http://bigbluebutton.org/",
"keywords": [
"api",
"bbb",
"bigbluebutton"
],
"time": "2020-08-20T13:19:38+00:00"
},
{
"name": "bnf/slim3-psr15",
"version": "1.1.0",

View File

@ -838,6 +838,53 @@ class resources_bo
return $list;
}
/**
*
* @param $_res_id
* @param $_starttime
* @param $_endtime
* @return array|null returns array of resource data with calculated useable quantity
*/
function checkUseable($_res_id, $_starttime, $_endtime)
{
$resource = $this->read($_res_id);
if ($resource && $resource['bookable'])
{
//get a calendar objet for reservations
if ( (!isset($this->bocal)) || !(is_object($this->bocal)))
{
$this->bocal = new calendar_bo();
}
$overlapping_events =& $this->bocal->search(array(
'start' => $_starttime,
'end' => $_endtime,
'users' => ['r'.$_res_id],
'ignore_acl' => true, // otherwise we get only events readable by the user
'enum_groups' => false, // otherwise group-events would not block time
));
foreach($overlapping_events as $event)
{
if ($event['non_blocking']) continue; // ignore non_blocking events
// now we are interested only on resources booked by theses events
if (isset($event['participants']) && is_array($event['participants'])){
foreach($event['participants'] as $part_key => $part_detail){
if ($part_key{0}=='r')
{
$resource_id=substr($part_key,1);
if ($resource_id != $_res_id) continue;
$quantity = 1;
$this->bocal->so->split_status($part_detail,$quantity);
$resource['useable']-=$quantity;
}
}
}
}
}
return $resource;
}
/**
* get title for an infolog entry identified by $res_id
*