@ -143,8 +143,8 @@ class bbb
public function forceCIdReq($courseCode, $sessionId = 0, $groupId = 0)
{
$this->courseCode = $courseCode;
$this->sessionId = intval($sessionId) ;
$this->groupId = intval($groupId) ;
$this->sessionId = (int) $sessionId ;
$this->groupId = (int) $groupId ;
}
/**
@ -265,39 +265,40 @@ class bbb
if ($max < 0 ) {
$max = 0;
}
$this->maxUsersLimit = intval($max) ;
$this->maxUsersLimit = (int) $max ;
}
/**
* See this file in you BBB to set up default values
* @param array $params Array of parameters that will be completed if not containing all expected variables
/var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties
*
More record information:
http://code.google.com/p/bigbluebutton/wiki/RecordPlaybackSpecification
# Default maximum number of users a meeting can have.
# Doesn't get enforced yet but is the default value when the create
# API doesn't pass a value.
defaultMaxUsers=20
# Default duration of the meeting in minutes.
# Current default is 0 (meeting doesn't end).
defaultMeetingDuration=0
# Remove the meeting from memory when the end API is called.
# This allows 3rd-party apps to recycle the meeting right-away
# instead of waiting for the meeting to expire (see below).
removeMeetingWhenEnded=false
# The number of minutes before the system removes the meeting from memory.
defaultMeetingExpireDuration=1
# The number of minutes the system waits when a meeting is created and when
# a user joins. If after this period, a user hasn't joined, the meeting is
# removed from memory.
defaultMeetingCreateJoinDuration=5
* @param array $params Array of parameters that will be completed if not containing all expected variables
*
* /var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties
*
* More record information:
* http://code.google.com/p/bigbluebutton/wiki/RecordPlaybackSpecification
*
* Default maximum number of users a meeting can have.
* Doesn't get enforced yet but is the default value when the create
* API doesn't pass a value.
* defaultMaxUsers=20
*
* Default duration of the meeting in minutes.
* Current default is 0 (meeting doesn't end).
* defaultMeetingDuration=0
*
* Remove the meeting from memory when the end API is called.
* This allows 3rd-party apps to recycle the meeting right-away
* instead of waiting for the meeting to expire (see below).
* removeMeetingWhenEnded=false
*
* The number of minutes before the system removes the meeting from memory.
* defaultMeetingExpireDuration=1
*
* The number of minutes the system waits when a meeting is created and when
* a user joins. If after this period, a user hasn't joined, the meeting is
* removed from memory.
* defaultMeetingCreateJoinDuration=5
*
* @return mixed
*/
@ -331,11 +332,6 @@ class bbb
// Each simultaneous conference room needs to have a different
// voice_bridge composed of a 5 digits number, so generating a random one
$params['voice_bridge'] = rand(10000, 99999);
if ($this->debug) {
error_log("enter create_meeting ".print_r($params, 1));
}
$params['created_at'] = api_get_utc_datetime();
$params['access_url'] = $this->accessUrl;
@ -350,14 +346,10 @@ class bbb
$id = Database::insert($this->table, $params);
if ($id) {
if ($this->debug) {
error_log("create_meeting: $id ");
}
$meetingName = isset($params['meeting_name']) ? $params['meeting_name'] : $this->getCurrentVideoConferenceName();
$welcomeMessage = isset($params['welcome_msg']) ? $params['welcome_msg'] : null;
$record = isset($params['record']) & & $params['record'] ? 'true' : 'false';
$duration = isset($params['duration']) ? intval($params['duration']) : 0;
//$duration = isset($params['duration']) ? intval($params['duration']) : 0;
// This setting currently limits the maximum conference duration,
// to avoid lingering sessions on the video-conference server #6261
$duration = 300;
@ -370,38 +362,31 @@ class bbb
'dialNumber' => '', // The main number to call into. Optional.
'voiceBridge' => $params['voice_bridge'], // PIN to join voice. Required.
'webVoice' => '', // Alphanumeric to join voice. Optional.
'logoutUrl' => $this->logoutUrl,
'logoutUrl' => $this->logoutUrl.'& action=logout& remote_id='.$params['remote_id'] ,
'maxParticipants' => $max, // Optional. -1 = unlimitted. Not supported in BBB. [number]
'record' => $record, // New. 'true' will tell BBB to record the meeting.
'duration' => $duration, // Default = 0 which means no set duration in minutes. [number]
//'meta_category' => '', // Use to pass additional info to BBB server. See API docs.
//'meta_category' => '', // Use to pass additional info to BBB server. See API docs.
);
if ($this->debug) {
error_log("create_meeting params: ".print_r($bbbParams, 1));
}
$status = false;
$meeting = null;
while ($status === false) {
$result = $this->api->createMeetingWithXmlResponseArray(
$bbbParams
);
$result = $this->api->createMeetingWithXmlResponseArray($bbbParams);
if (isset($result) & & strval($result['returncode']) == 'SUCCESS') {
if ($this->debug) {
error_log(
"create_meeting result: ".print_r($result, 1)
);
if ($this->plugin->get('allow_regenerate_recording') === 'true') {
$internalId = Database::escape_string($result['internalMeetingID']);
$sql = "UPDATE $this->table SET internal_meeting_id = '".$internalId."'
WHERE id = $id";
Database::query($sql);
}
$meeting = $this->joinMeeting($meetingName, true);
return $meeting;
}
}
return false;
}
return false;
}
@ -579,7 +564,7 @@ class bbb
}
}
if (strval($meetingIsRunningInfo['returncode']) == 'SUCCESS' & &
if (strval($meetingIsRunningInfo['returncode']) === 'SUCCESS' & &
isset($meetingIsRunningInfo['meetingName']) & &
!empty($meetingIsRunningInfo['meetingName'])
) {
@ -628,9 +613,8 @@ class bbb
if ($this->debug) {
error_log("Failed to get any response. Maybe we can't contact the BBB server.");
}
} else {
return $result;
}
return $result;
} catch (Exception $e) {
if ($this->debug) {
error_log('Caught exception: ', $e->getMessage(), "\n");
@ -734,7 +718,7 @@ class bbb
);
}
$conditions['order'] = "created_at ASC" ;
$conditions['order'] = 'created_at ASC' ;
$meetingList = Database::select(
'*',
@ -766,7 +750,7 @@ class bbb
);
if ($meetingBBB === false) {
//c hecking with the remote_id didn't work, so just in case and
// C hecking with the remote_id didn't work, so just in case and
// to provide backwards support, check with the id
$params = array(
'meetingId' => $meetingDB['id'],
@ -783,7 +767,7 @@ class bbb
$meetingBBB['end_url'] = $this->endUrl($meetingDB);
if (isset($meetingBBB['returncode']) & & (string) $meetingBBB['returncode'] == 'FAILED') {
if (isset($meetingBBB['returncode']) & & (string) $meetingBBB['returncode'] === 'FAILED') {
if ($meetingDB['status'] == 1 & & $this->isConferenceManager()) {
$this->endMeeting($meetingDB['id'], $courseCode);
}
@ -804,35 +788,35 @@ class bbb
}
$record = [];
if (empty($meetingDB['video_url'])) {
$recordingParams = ['meetingId' => $mId];
$records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
if (!empty($records)) {
if (!isset($records['messageKey']) || $records['messageKey'] != 'noRecordings') {
$record = end($records);
if (!is_array($record) || !isset($record['recordId'])) {
continue;
}
$recordingParams = ['meetingId' => $mId];
$records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
if (!empty($records)) {
if (!isset($records['messageKey']) || $records['messageKey'] !== 'noRecordings') {
$record = end($records);
if (!is_array($record) || !isset($record['recordId'])) {
continue;
}
if (!empty($record['playbackFormatUrl'])) {
$this->updateMeetingVideoUrl($meetingDB['id'], $record['playbackFormatUrl']);
}
if (!$this->isConferenceManager()) {
$record = [];
}
if (!$this->isConferenceManager()) {
$record = [];
}
}
} else {
$record['playbackFormatUrl'] = $meetingDB['video_url'];
}
$recordLink = isset($record['playbackFormatUrl']) & & !empty($record['playbackFormatUrl'])
? Display::url(
if ( isset($record['playbackFormatUrl']) & & !empty($record['playbackFormatUrl'])) {
$recordLink = Display::url(
$this->plugin->get_lang('ViewRecord'),
$record['playbackFormatUrl'],
['target' => '_blank']
)
: $this->plugin->get_lang('NoRecording');
['target' => '_blank', 'class' => 'btn btn-default']
);
} else {
$recordLink = $this->plugin->get_lang('NoRecording');
}
if ($isAdminReport) {
$this->forceCIdReq(
@ -1115,6 +1099,61 @@ class bbb
return 0;
}
/**
* @param int $id
* @param string $recordId
*
* @return bool
*/
public function regenerateRecording($id, $recordId = '')
{
if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
return false;
}
if (empty($id)) {
return false;
}
$meetingData = Database::select(
'*',
$this->table,
array('where' => array('id = ?' => array($id))),
'first'
);
// Check if there are recordings for this meeting
$recordings = $this->api->getRecordings(['meetingId' => $meetingData['remote_id']]);
if (!empty($recordings) & & isset($recordings['messageKey']) & & $recordings['messageKey'] === 'noRecordings') {
// Regenerate the meeting id
if (!empty($meetingData['internal_meeting_id'])) {
return $this->api->generateRecording(['recordId' => $meetingData['internal_meeting_id']]);
}
/*$pass = $this->getModMeetingPassword();
$info = $this->getMeetingInfo(['meetingId' => $meetingData['remote_id'], 'password' => $pass]);
if (!empty($info) & & isset($info['internalMeetingID'])) {
return $this->api->generateRecording(['recordId' => $meetingData['internal_meeting_id']]);
}*/
return false;
} else {
if (!empty($recordings['records'])) {
$recordExists = false;
foreach ($recordings['records'] as $record) {
if ($recordId == $record['recordId']) {
$recordExists = true;
break;
}
}
if ($recordExists) {
return $this->api->generateRecording(['recordId' => $recordId]);
}
}
}
return false;
}
/**
* Deletes a recording of a meeting
*
@ -1389,6 +1428,49 @@ class bbb
return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=delete_record&id='.$meeting['id'];
}
/**
* @param array $meeting
* @param array $recordInfo
*
* @return string
*/
public function regenerateRecordUrl($meeting, $recordInfo)
{
if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
return '';
}
if (!isset($meeting['id'])) {
return '';
}
if (empty($recordInfo) || (!empty($recordInfo['recordId']) & & !isset($recordInfo['recordId']))) {
return '';
}
return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().
'&action=regenerate_record&id='.$meeting['id'].'&record_id='.$recordInfo['recordId'];
}
/**
* @param array $meeting
*
* @return string
*/
public function regenerateRecordUrlFromMeeting($meeting)
{
if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
return '';
}
if (!isset($meeting['id'])) {
return '';
}
return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().
'&action=regenerate_record&id='.$meeting['id'];
}
/**
* @param array $meeting
* @return string
@ -1399,7 +1481,8 @@ class bbb
return '';
}
return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=copy_record_to_link_tool&id='.$meeting['id'];
return api_get_path(WEB_PLUGIN_PATH).
'bbb/listing.php?'.$this->getUrlParams().'&action=copy_record_to_link_tool&id='.$meeting['id'];
}
/**
@ -1438,6 +1521,25 @@ class bbb
return $meetingData;
}
/**
* Get the meeting info.
*
* @param int $id
*
* @return array
*/
public function getMeetingByRemoteId($id)
{
$meetingData = Database::select(
'*',
'plugin_bbb_meeting',
array('where' => array('remote_id = ?' => $id)),
'first'
);
return $meetingData;
}
/**
* @param int $meetingId
* @return array
@ -1496,8 +1598,9 @@ class bbb
/**
* @param array $meetingInfo
* @param array $recordInfo
* @param bool $isGlobal
* @param bool $isAdminReport
* @param bool $isGlobal
* @param bool $isAdminReport
*
* @return array
*/
private function getActionLinks(
@ -1518,14 +1621,29 @@ class bbb
);
$links = [];
if ($this->plugin->get('allow_regenerate_recording') === 'true' & & $meetingInfo['record'] == 1) {
if (!empty($recordInfo)) {
$links[] = Display::url(
Display::return_icon('reload.png', get_lang('RegenerateRecord')),
$this->regenerateRecordUrl($meetingInfo, $recordInfo)
);
} else {
$links[] = Display::url(
Display::return_icon('reload.png', get_lang('RegenerateRecord')),
$this->regenerateRecordUrlFromMeeting($meetingInfo)
);
}
}
if (empty($recordInfo)) {
if (!$isAdminReport) {
$links[] = Display::url(
Display::return_icon('delete.png', get_lang('Delete')),
$this->deleteRecordUrl($meetingInfo)
);
$links[] = $linkVisibility;
if ($meetingInfo['status'] == 0) {
$links[] = Display::url(
Display::return_icon('delete.png', get_lang('Delete')),
$this->deleteRecordUrl($meetingInfo)
);
$links[] = $linkVisibility;
}
return $links;
} else {
@ -1552,25 +1670,26 @@ class bbb
$hide = $this->plugin->get('disable_download_conference_link') === 'true' ? true : false;
if ($hide == false) {
if ($meetingInfo['has_video_m4v']) {
$links[] = Display::url(
Display::return_icon('save.png', get_lang('DownloadFile')),
$recordInfo['playbackFormatUrl'].'/capture.m4v',
['target' => '_blank']
);
} else {
$links[] = Display::url(
Display::return_icon('save.png', get_lang('DownloadFile')),
'#',
[
'id' => "btn-check-meeting-video-{$meetingInfo['id']}",
'class' => 'check-meeting-video',
'data-id' => $meetingInfo['id']
]
);
if ($meetingInfo['has_video_m4v']) {
$links[] = Display::url(
Display::return_icon('save.png', get_lang('DownloadFile')),
$recordInfo['playbackFormatUrl'].'/capture.m4v',
['target' => '_blank']
);
} else {
$links[] = Display::url(
Display::return_icon('save.png', get_lang('DownloadFile')),
'#',
[
'id' => "btn-check-meeting-video-{$meetingInfo['id']}",
'class' => 'check-meeting-video',
'data-id' => $meetingInfo['id']
]
);
}
}
if (!$isAdminReport) {
$links[] = Display::url(
Display::return_icon('delete.png', get_lang('Delete')),
@ -1584,6 +1703,7 @@ class bbb
);
}
return $links;
}