Completed
Push — 1.10.x ( b603d2...d2bf4a )
by
unknown
89:29 queued 39:58
created

bbb::publishMeeting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 10
Ratio 83.33 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 1
dl 10
loc 12
rs 9.4285
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Class bbb
6
 * This script initiates a video conference session, calling the BigBlueButton
7
 * API
8
 * @package chamilo.plugin.bigbluebutton
9
 *
10
 * BigBlueButton-Chamilo connector class
11
 */
12
//namespace Chamilo\Plugin\BBB;
13
14
/**
15
 * Class bbb
16
 * @package Chamilo\Plugin\BBB
17
 */
18
class bbb
19
{
20
    public $url;
21
    public $salt;
22
    public $api;
23
    public $user_complete_name = null;
24
    public $protocol = 'http://';
25
    public $debug = false;
26
    public $logout_url = null;
27
    public $plugin_enabled = false;
28
29
    /**
30
     *
31
     * Constructor (generates a connection to the API and the Chamilo settings
32
     * required for the connection to the video conference server)
33
     * @param string $host
34
     * @param string $salt
35
     */
36
    public function __construct($host = null, $salt = null)
37
    {
38
        // Initialize video server settings from global settings
39
        $plugin = BBBPlugin::create();
40
41
        $bbb_plugin = $plugin->get('tool_enable');
42
43
        if (empty($host)) {
44
            $bbb_host = $plugin->get('host');
45
        } else {
46
            $bbb_host = $host;
47
        }
48
        if (empty($salt)) {
49
            $bbb_salt = $plugin->get('salt');
50
        } else {
51
            $bbb_salt = $salt;
52
        }
53
54
        $this->logout_url = $this->getListingUrl();
55
        $this->table = Database::get_main_table('plugin_bbb_meeting');
56
57
        if ($bbb_plugin == true) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $bbb_plugin of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
58
            $userInfo = api_get_user_info();
59
            $this->user_complete_name = $userInfo['complete_name'];
60
            $this->salt = $bbb_salt;
61
            $info = parse_url($bbb_host);
62
            $this->url = $bbb_host.'/bigbluebutton/';
63
            if (isset($info['scheme'])) {
64
                $this->protocol = $info['scheme'].'://';
65
                $this->url = str_replace($this->protocol, '', $this->url);
66
            }
67
68
            // Setting BBB api
69
            define('CONFIG_SECURITY_SALT', $this->salt);
70
            define('CONFIG_SERVER_BASE_URL', $this->url);
71
72
            $this->api = new BigBlueButtonBN();
73
            $this->plugin_enabled = true;
74
        }
75
    }
76
77
    /**
78
     * Checks whether a user is teacher in the current course
79
     * @return bool True if the user can be considered a teacher in this course, false otherwise
80
     */
81
    public function isTeacher()
82
    {
83
        return api_is_course_admin() || api_is_coach() || api_is_platform_admin();
84
    }
85
86
    /**
87
     * See this file in you BBB to set up default values
88
     * @param   array $params Array of parameters that will be completed if not containing all expected variables
89
90
       /var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties
91
     *
92
       More record information:
93
       http://code.google.com/p/bigbluebutton/wiki/RecordPlaybackSpecification
94
95
       # Default maximum number of users a meeting can have.
96
        # Doesn't get enforced yet but is the default value when the create
97
        # API doesn't pass a value.
98
        defaultMaxUsers=20
99
100
        # Default duration of the meeting in minutes.
101
        # Current default is 0 (meeting doesn't end).
102
        defaultMeetingDuration=0
103
104
        # Remove the meeting from memory when the end API is called.
105
        # This allows 3rd-party apps to recycle the meeting right-away
106
        # instead of waiting for the meeting to expire (see below).
107
        removeMeetingWhenEnded=false
108
109
        # The number of minutes before the system removes the meeting from memory.
110
        defaultMeetingExpireDuration=1
111
112
        # The number of minutes the system waits when a meeting is created and when
113
        # a user joins. If after this period, a user hasn't joined, the meeting is
114
        # removed from memory.
115
        defaultMeetingCreateJoinDuration=5
116
     *
117
     */
118
    public function createMeeting($params)
119
    {
120
        $params['c_id'] = api_get_course_int_id();
121
        $courseCode = api_get_course_id();
122
        $params['session_id'] = api_get_session_id();
123
124
        $params['attendee_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : api_get_course_id();
125
        $attendeePassword =  $params['attendee_pw'];
126
        $params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $this->getModMeetingPassword();
127
        $moderatorPassword = $params['moderator_pw'];
128
129
        $params['record'] = api_get_course_setting('big_blue_button_record_and_store', $courseCode) == 1 ? true : false;
130
        $max = api_get_course_setting('big_blue_button_max_students_allowed', $courseCode);
131
        $max =  isset($max) ? $max : -1;
132
        $params['status'] = 1;
133
        // Generate a pseudo-global-unique-id to avoid clash of conferences on
134
        // the same BBB server with several Chamilo portals
135
        $params['remote_id'] = uniqid(true, true);
136
        // Each simultaneous conference room needs to have a different
137
        // voice_bridge composed of a 5 digits number, so generating a random one
138
        $params['voice_bridge'] = rand(10000,99999);
139
140
        if ($this->debug) {
141
            error_log("enter create_meeting ".print_r($params, 1));
142
        }
143
144
        $params['created_at'] = api_get_utc_datetime();
145
        $id = Database::insert($this->table, $params);
146
147
        if ($id) {
148
            if ($this->debug) {
149
                error_log("create_meeting: $id ");
150
            }
151
152
            $meetingName = isset($params['meeting_name']) ? $params['meeting_name'] : api_get_course_id().'-'.api_get_session_id();
153
            $welcomeMessage = isset($params['welcome_msg']) ? $params['welcome_msg'] : null;
154
            $record = isset($params['record']) && $params['record'] ? 'true' : 'false';
155
            $duration = isset($params['duration']) ? intval($params['duration']) : 0;
156
            // This setting currently limits the maximum conference duration,
157
            // to avoid lingering sessions on the video-conference server #6261
158
            $duration = 300;
159
160
            $bbbParams = array(
161
                'meetingId' => $params['remote_id'], 					// REQUIRED
162
                'meetingName' => $meetingName, 	// REQUIRED
163
                'attendeePw' => $attendeePassword, 					// Match this value in getJoinMeetingURL() to join as attendee.
164
                'moderatorPw' => $moderatorPassword, 					// Match this value in getJoinMeetingURL() to join as moderator.
165
                'welcomeMsg' => $welcomeMessage, 					// ''= use default. Change to customize.
166
                'dialNumber' => '', 					// The main number to call into. Optional.
167
                'voiceBridge' => $params['voice_bridge'], 					// PIN to join voice. Required.
168
                'webVoice' => '', 						// Alphanumeric to join voice. Optional.
169
                'logoutUrl' =>  $this->logout_url,
170
                'maxParticipants' => $max, 				// Optional. -1 = unlimitted. Not supported in BBB. [number]
171
                'record' => $record, 					// New. 'true' will tell BBB to record the meeting.
172
                'duration' => $duration, 				// Default = 0 which means no set duration in minutes. [number]
173
                //'meta_category' => '', 				// Use to pass additional info to BBB server. See API docs.
174
            );
175
176
            if ($this->debug) {
177
                error_log("create_meeting params: ".print_r($bbbParams,1));
178
            }
179
180
            $status = false;
181
            $meeting = null;
182
183
            while ($status == false) {
184
                $result = $this->api->createMeetingWithXmlResponseArray(
185
                    $bbbParams
186
                );
187
                if (isset($result) && strval($result['returncode']) == 'SUCCESS') {
188
                    if ($this->debug) {
189
                        error_log(
190
                            "create_meeting result: " . print_r($result, 1)
191
                        );
192
                    }
193
                    $meeting = $this->joinMeeting($meetingName, true);
194
195
                    return $meeting;
196
                }
197
            }
198
            return $this->logout;
199
        }
200
    }
201
202
    /**
203
     * Tells whether the given meeting exists and is running
204
     * (using course code as name)
205
     * @param string $meetingName Meeting name (usually the course code)
206
     *
207
     * @return bool True if meeting exists, false otherwise
208
     * @assert ('') === false
209
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
210
     */
211
    public function meetingExists($meetingName)
212
    {
213
        if (empty($meetingName)) {
214
            return false;
215
        }
216
        $courseId = api_get_course_int_id();
217
        $sessionId = api_get_session_id();
218
        $meetingData = Database::select(
219
            '*',
220
            $this->table,
221
            array(
222
                'where' => array(
223
                    'c_id = ? AND session_id = ? AND meeting_name = ? AND status = 1 ' =>
224
                        array($courseId, $sessionId, $meetingName)
225
                )
226
            ),
227
            'first'
228
        );
229
        if ($this->debug) {
230
            error_log("meeting_exists ".print_r($meetingData, 1));
231
        }
232
        if (empty($meetingData)) {
233
            return false;
234
        } else {
235
            return true;
236
        }
237
    }
238
239
    /**
240
     * Returns a meeting "join" URL
241
     * @param string The name of the meeting (usually the course code)
242
     * @return mixed The URL to join the meeting, or false on error
243
     * @todo implement moderator pass
244
     * @assert ('') === false
245
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
246
     */
247
    public function joinMeeting($meetingName, $loop = false)
248
    {
249
        if (empty($meetingName)) {
250
            return false;
251
        }
252
253
        $pass = $this->getUserMeetingPassword();
254
255
        $meetingData = Database::select(
256
            '*',
257
            $this->table,
258
            array('where' => array('meeting_name = ? AND status = 1 ' => $meetingName)),
259
            'first'
260
        );
261
262
        if (empty($meetingData) || !is_array($meetingData)) {
263
            if ($this->debug) {
264
                error_log("meeting does not exist: $meetingName");
265
            }
266
267
            return false;
268
        }
269
270
        $params = array(
271
            'meetingId' => $meetingData['remote_id'],
272
            //  -- REQUIRED - The unique id for the meeting
273
            'password' => $this->getModMeetingPassword()
274
            //  -- REQUIRED - The moderator password for the meeting
275
        );
276
277
        $status = false;
278
        $meetingInfoExists = false;
279
        while ($status == false) {
280
281
            $meetingIsRunningInfo = $this->getMeetingInfo($params);
282 View Code Duplication
            if ($meetingIsRunningInfo === false) {
283
                //checking with the remote_id didn't work, so just in case and
284
                // to provide backwards support, check with the id
285
                $params = array(
286
                    'meetingId' => $meetingData['id'],
287
                    //  -- REQUIRED - The unique id for the meeting
288
                    'password' => $this->getModMeetingPassword()
289
                    //  -- REQUIRED - The moderator password for the meeting
290
                );
291
                $meetingIsRunningInfo = $this->getMeetingInfo($params);
292
            }
293
294
            if ($this->debug) {
295
                error_log(print_r($meetingIsRunningInfo, 1));
296
            }
297
298
            if (strval($meetingIsRunningInfo['returncode']) == 'SUCCESS' &&
299
                isset($meetingIsRunningInfo['meetingName']) &&
300
                !empty($meetingIsRunningInfo['meetingName'])
301
                //strval($meetingIsRunningInfo['running']) == 'true'
302
            ) {
303
                $meetingInfoExists = true;
304
            }
305
306
            if ($this->debug) {
307
                error_log(
308
                    "meeting is running: " . intval($meetingInfoExists)
309
                );
310
            }
311
312
            if ($meetingInfoExists) {
313
                $status = true;
314
            }
315
316
            if ($loop) {
317
                continue;
318
            } else {
319
                break;
320
            }
321
        }
322
323
        if ($meetingInfoExists) {
324
            $joinParams = array(
325
                'meetingId' => $meetingData['remote_id'],	//	-- REQUIRED - A unique id for the meeting
326
                'username' => $this->user_complete_name,	//-- REQUIRED - The name that will display for the user in the meeting
327
                'password' => $pass,			//-- REQUIRED - The attendee or moderator password, depending on what's passed here
328
                //'createTime' => api_get_utc_datetime(),			//-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
329
                'userID' => api_get_user_id(),				//-- OPTIONAL - string
330
                'webVoiceConf' => ''	//	-- OPTIONAL - string
331
            );
332
            $url = $this->api->getJoinMeetingURL($joinParams);
333
            $url = $this->protocol.$url;
334
        } else {
335
            $url = $this->logout_url;
336
        }
337
        if ($this->debug) {
338
            error_log("return url :" . $url);
339
        }
340
        return $url;
341
    }
342
343
    /**
344
     * Get information about the given meeting
345
     * @param array ...?
346
     * @return mixed Array of information on success, false on error
347
     * @assert (array()) === false
348
     */
349
    public function getMeetingInfo($params)
350
    {
351
        try {
352
            $result = $this->api->getMeetingInfoWithXmlResponseArray($params);
353
            if ($result == null) {
354
                if ($this->debug) {
355
                    error_log("Failed to get any response. Maybe we can't contact the BBB server.");
356
                }
357
            } else {
358
                return $result;
359
            }
360
        } catch (Exception $e) {
361
            if ($this->debug) {
362
                error_log('Caught exception: ', $e->getMessage(), "\n");
363
            }
364
        }
365
        return false;
366
    }
367
368
    /**
369
     * Gets all the course meetings saved in the plugin_bbb_meeting table
370
     * @return array Array of current open meeting rooms
371
     */
372
    public function getCourseMeetings()
373
    {
374
        $pass = $this->getUserMeetingPassword();
375
        $meetingList = Database::select(
376
            '*',
377
            $this->table,
378
            array(
379
                'where' => array(
380
                    'c_id = ? AND session_id = ? ' => array(
381
                        api_get_course_int_id(),
382
                        api_get_session_id(),
383
                    ),
384
                ),
385
            )
386
        );
387
        $newMeetingList = array();
388
389
        $item = array();
390
391
        foreach ($meetingList as $meetingDB) {
392
            $meetingBBB = $this->getMeetingInfo(array('meetingId' => $meetingDB['remote_id'], 'password' => $pass));
393 View Code Duplication
            if ($meetingBBB === false) {
394
                //checking with the remote_id didn't work, so just in case and
395
                // to provide backwards support, check with the id
396
                $params = array(
397
                    'meetingId' => $meetingDB['id'],
398
                    //  -- REQUIRED - The unique id for the meeting
399
                    'password' => $pass
400
                    //  -- REQUIRED - The moderator password for the meeting
401
                );
402
                $meetingBBB = $this->getMeetingInfo($params);
403
            }
404
405
            if ($meetingDB['visibility'] == 0 and $this->isTeacher() == false) {
406
                continue;
407
            }
408
            $meetingBBB['end_url'] = $this->endUrl($meetingDB);
409
410
            if ((string)$meetingBBB['returncode'] == 'FAILED') {
411
                if ($meetingDB['status'] == 1 && $this->isTeacher()) {
412
                    $this->endMeeting($meetingDB['id']);
413
                }
414
            } else {
415
                $meetingBBB['add_to_calendar_url'] = $this->addToCalendarUrl($meetingDB);
416
            }
417
418
            $recordArray = array();
419
            $actionLinksArray = array();
420
421
            if ($meetingDB['record'] == 1) {
422
                // backwards compatibility (when there was no remote ID)
423
                $mId = $meetingDB['remote_id'];
424
                if (empty($mId)) {
425
                    $mId = $meetingDB['id'];
426
                }
427
                if (empty($mId)) {
428
                    // if the id is still empty (should *never* occur as 'id' is
429
                    // the table's primary key), skip this conference
430
                    continue;
431
                }
432
                $recordingParams = array(
433
                    'meetingId' => $mId, //-- OPTIONAL - comma separate if multiple ids
434
                );
435
436
                //To see the recording list in your BBB server do: bbb-record --list
437
                $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
438
                if (!empty($records)) {
439
                    $count = 1;
440
                    if (isset($records['message']) && !empty($records['message'])) {
441
                        if ($records['messageKey'] == 'noRecordings') {
442
                            $recordArray[] = get_lang('NoRecording');
443
                            if ($meetingDB['visibility'] == 0) {
444
                                $actionLinksArray[] = Display::url(
445
                                    Display::return_icon(
446
                                        'invisible.png',
447
                                        get_lang('MakeVisible'),
448
                                        array(),
449
                                        ICON_SIZE_MEDIUM
450
                                    ),
451
                                    $this->publishUrl($meetingDB)
452
                                );
453
                            } else {
454
                                $actionLinksArray[] = Display::url(
455
                                    Display::return_icon(
456
                                        'visible.png',
457
                                        get_lang('MakeInvisible'),
458
                                        array(),
459
                                        ICON_SIZE_MEDIUM
460
                                    ),
461
                                    $this->unPublishUrl($meetingDB)
462
                                );
463
                            }
464
                        } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
465
                            //$recordArray[] = $records['message'];
466
                        }
467
                    } else {
468
                        foreach ($records as $record) {
469
                            //if you get several recordings here and you used a
470
                            // previous version of Chamilo, you might want to
471
                            // only keep the last result for each chamilo conf
472
                            // (see show_links after the end of this loop)
473
                            if (is_array($record) && isset($record['recordId'])) {
474
                                $url = Display::url(
475
                                    get_lang('ViewRecord')." [~".$record['playbackFormatLength']."']",
476
                                    $record['playbackFormatUrl'],
477
                                    array('target' => '_blank')
478
                                );
479
                                $actionLinks = '';
480
                                if ($this->isTeacher()) {
481
                                    $actionLinks .= Display::url(
482
                                        Display::return_icon(
483
                                            'link.gif',
484
                                            get_lang('CopyToLinkTool')
485
                                        ),
486
                                        $this->copyToRecordToLinkTool($meetingDB)
487
                                    );
488
                                    $actionLinks .= Display::url(
489
                                        Display::return_icon(
490
                                            'agenda.png',
491
                                            get_lang('AddToCalendar')
492
                                        ),
493
                                        $this->addToCalendarUrl($meetingDB, $record)
494
                                    );
495
                                    $actionLinks .= Display::url(
496
                                        Display::return_icon(
497
                                            'delete.png',
498
                                            get_lang('Delete')
499
                                        ),
500
                                        $this->deleteRecordUrl($meetingDB)
501
                                    );
502 View Code Duplication
                                    if ($meetingDB['visibility'] == 0) {
503
                                        $actionLinks .= Display::url(
504
                                            Display::return_icon(
505
                                                'invisible.png',
506
                                                get_lang('MakeVisible'),
507
                                                array(),
508
                                                ICON_SIZE_MEDIUM
509
                                            ),
510
                                            $this->publishUrl($meetingDB)
511
                                        );
512
                                    } else {
513
                                        $actionLinks .= Display::url(
514
                                            Display::return_icon(
515
                                                'visible.png',
516
                                                get_lang('MakeInvisible'),
517
                                                array(),
518
                                                ICON_SIZE_MEDIUM
519
                                            ),
520
                                            $this->unPublishUrl($meetingDB)
521
                                        );
522
                                    }
523
                                }
524
                                //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
525
                                $count++;
526
                                $recordArray[] = $url;
527
                                $actionLinksArray[] = $actionLinks;
528
                            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
529
                                /*if (is_array($record) && isset($record['recordID']) && isset($record['playbacks'])) {
530
531
                                    //Fix the bbb timestamp
532
                                    //$record['startTime'] = substr($record['startTime'], 0, strlen($record['startTime']) -3);
533
                                    //$record['endTime']   = substr($record['endTime'], 0, strlen($record['endTime']) -3);
534
                                    //.' - '.api_convert_and_format_date($record['startTime']).' - '.api_convert_and_format_date($record['endTime'])
535
                                    foreach($record['playbacks'] as $item) {
536
                                        $url = Display::url(get_lang('ViewRecord'), $item['url'], array('target' => '_blank'));
537
                                        //$url .= Display::url(get_lang('DeleteRecord'), api_get_self().'?action=delete_record&'.$record['recordID']);
538
                                        if ($this->isTeacher()) {
539
                                            $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']);
540
                                            $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='.$item['url']);
541
                                            $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordID']);
542
                                        }
543
                                        //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
544
                                        $count++;
545
                                        $recordArray[] = $url;
546
                                    }
547
                                }*/
548
                            }
549
                        }
550
                    }
551
                } else {
552
                    $actionLinks = '';
553 View Code Duplication
                    if ($this->isTeacher()) {
554
                        if ($meetingDB['visibility'] == 0) {
555
                            $actionLinks .= Display::url(
556
                                Display::return_icon(
557
                                    'invisible.png',
558
                                    get_lang('MakeVisible'),
559
                                    array(),
560
                                    ICON_SIZE_MEDIUM
561
                                ),
562
                                $this->publishUrl($meetingDB)
563
                            );
564
                        } else {
565
                            $actionLinks .= Display::url(
566
                                Display::return_icon(
567
                                    'visible.png',
568
                                    get_lang('MakeInvisible'),
569
                                    array(),
570
                                    ICON_SIZE_MEDIUM
571
                                ),
572
                                $this->unPublishUrl($meetingDB)
573
                            );
574
                        }
575
                    }
576
                    $actionLinksArray[] = $actionLinks;
577
                    $item['action_links'] = implode('<br />', $actionLinksArray);
578
                }
579
                //var_dump($recordArray);
580
                $item['show_links']  = implode('<br />', $recordArray);
581
                $item['action_links'] = implode('<br />', $actionLinksArray);
582
            }
583
584
            $item['created_at'] = api_convert_and_format_date($meetingDB['created_at']);
585
            //created_at
586
            $meetingDB['created_at'] = $item['created_at']; //avoid overwrite in array_merge() below
587
588
            $item['publish_url'] = $this->publishUrl($meetingDB);
589
            $item['unpublish_url'] = $this->unPublishUrl($meetingBBB);
0 ignored issues
show
Security Bug introduced by
It seems like $meetingBBB can also be of type false; however, bbb::unPublishUrl() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
590
591
            if ($meetingDB['status'] == 1) {
592
                $joinParams = array(
593
                    'meetingId' => $meetingDB['remote_id'],		//-- REQUIRED - A unique id for the meeting
594
                    'username' => $this->user_complete_name,	//-- REQUIRED - The name that will display for the user in the meeting
595
                    'password' => $pass,			//-- REQUIRED - The attendee or moderator password, depending on what's passed here
596
                    'createTime' => '',			//-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
597
                    'userID' => '',			//	-- OPTIONAL - string
598
                    'webVoiceConf' => ''	//	-- OPTIONAL - string
599
                );
600
                $item['go_url'] = $this->protocol.$this->api->getJoinMeetingURL($joinParams);
601
            }
602
            $item = array_merge($item, $meetingDB, $meetingBBB);
603
            $newMeetingList[] = $item;
604
        }
605
606
        return $newMeetingList;
607
    }
608
609
    /**
610
     * Function disabled
611
     */
612 View Code Duplication
    public function publishMeeting($id)
613
    {
614
        //return BigBlueButtonBN::setPublishRecordings($id, 'true', $this->url, $this->salt);
615
        if (empty($id)) {
616
617
            return false;
618
        }
619
        $id = intval($id);
620
        Database::update($this->table, array('visibility' => 1), array('id = ? ' => $id));
621
622
        return true;
623
    }
624
625
    /**
626
     * Function disabled
627
     */
628 View Code Duplication
    public function unpublishMeeting($id)
629
    {
630
        //return BigBlueButtonBN::setPublishRecordings($id, 'false', $this->url, $this->salt);
631
        if (empty($id)) {
632
            return false;
633
        }
634
        $id = intval($id);
635
        Database::update($this->table, array('visibility' => 0), array('id = ? ' => $id));
636
637
        return true;
638
    }
639
640
    /**
641
     * Closes a meeting (usually when the user click on the close button from
642
     * the conferences listing.
643
     * @param string The internal ID of the meeting (id field for this meeting)
644
     * @return void
645
     * @assert (0) === false
646
     */
647
    public function endMeeting($id)
648
    {
649
        if (empty($id)) {
650
            return false;
651
        }
652
        $meetingData = Database::select('*', $this->table, array('where' => array('id = ?' => array($id))), 'first');
653
        $pass = $this->getUserMeetingPassword();
654
655
        $endParams = array(
656
            'meetingId' => $meetingData['remote_id'],   // REQUIRED - We have to know which meeting to end.
657
            'password' => $pass,        // REQUIRED - Must match moderator pass for meeting.
658
        );
659
        $this->api->endMeetingWithXmlResponseArray($endParams);
660
        Database::update(
661
            $this->table,
662
            array('status' => 0, 'closed_at' => api_get_utc_datetime()),
663
            array('id = ? ' => $id)
664
        );
665
    }
666
667
    /**
668
     * Gets the password for a specific meeting for the current user
669
     * @return string A moderator password if user is teacher, or the course code otherwise
670
     */
671
    public function getUserMeetingPassword()
672
    {
673
        if ($this->isTeacher()) {
674
            return $this->getModMeetingPassword();
675
        } else {
676
            return api_get_course_id();
677
        }
678
    }
679
680
    /**
681
     * Generated a moderator password for the meeting
682
     * @return string A password for the moderation of the videoconference
683
     */
684
    public function getModMeetingPassword()
685
    {
686
        return api_get_course_id().'mod';
687
    }
688
689
    /**
690
     * Get users online in the current course room
691
     * @return int The number of users currently connected to the videoconference
692
     * @assert () > -1
693
     */
694
    public function getUsersOnlineInCurrentRoom()
695
    {
696
        $courseId = api_get_course_int_id();
697
        $sessionId = api_get_session_id();
698
        $meetingData = Database::select(
699
            '*',
700
            $this->table,
701
            array('where' => array('c_id = ? AND session_id = ? AND status = 1 ' => array($courseId, $sessionId))),
702
            'first'
703
        );
704
        if (empty($meetingData)) {
705
            return 0;
706
        }
707
        $pass = $this->getModMeetingPassword();
708
        $info = $this->getMeetingInfo(array('meetingId' => $meetingData['remote_id'], 'password' => $pass));
709 View Code Duplication
        if ($info === false) {
710
            //checking with the remote_id didn't work, so just in case and
711
            // to provide backwards support, check with the id
712
            $params = array(
713
                'meetingId' => $meetingData['id'],
714
                //  -- REQUIRED - The unique id for the meeting
715
                'password' => $pass
716
                //  -- REQUIRED - The moderator password for the meeting
717
            );
718
            $info = $this->getMeetingInfo($params);
719
        }
720
721
        if (!empty($info) && isset($info['participantCount'])) {
722
            return $info['participantCount'];
723
724
        }
725
        return 0;
726
    }
727
728
    /**
729
     * Deletes a previous recording of a meeting
730
     * @param int integral ID of the recording
731
     * @return array ?
732
     * @assert () === false
733
     * @todo Also delete links and agenda items created from this recording
734
     */
735
    public function deleteRecord($id)
736
    {
737
        if (empty($id)) {
738
            return false;
739
        }
740
741
        $meetingData = Database::select(
742
            '*',
743
            $this->table,
744
            array('where' => array('id = ?' => array($id))),
745
            'first'
746
        );
747
748
        $recordingParams = array(
749
            /*
750
             * NOTE: Set the recordId below to a valid id after you have
751
             * created a recorded meeting, and received a real recordID
752
             * back from your BBB server using the
753
             * getRecordingsWithXmlResponseArray method.
754
             */
755
756
            // REQUIRED - We have to know which recording:
757
            'recordId' => $meetingData['remote_id'],
758
        );
759
760
        $result = $this->api->deleteRecordingsWithXmlResponseArray($recordingParams);
761
762
        if (!empty($result) && isset($result['deleted']) && $result['deleted'] == 'true') {
763
            Database::delete(
764
                $this->table,
765
                array('id = ?' => array($id))
766
            );
767
        }
768
769
        return $result;
770
    }
771
772
    /**
773
     * Creates a link in the links tool from the given videoconference recording
774
     * @param int ID of the item in the plugin_bbb_meeting table
775
     * @param string Hash identifying the recording, as provided by the API
776
     * @return mixed ID of the newly created link, or false on error
777
     * @assert (null, null) === false
778
     * @assert (1, null) === false
779
     * @assert (null, 'abcdefabcdefabcdefabcdef') === false
780
     */
781
    public function copyRecordToLinkTool($id)
782
    {
783
        if (empty($id)) {
784
            return false;
785
        }
786
        //$records =  BigBlueButtonBN::getRecordingsUrl($id);
787
        $meetingData = Database::select('*', $this->table, array('where' => array('id = ?' => array($id))), 'first');
788
789
        $records = $this->api->getRecordingsWithXmlResponseArray(array('meetingId' => $meetingData['remote_id']));
790
791
        if (!empty($records)) {
792
            if (isset($records['message']) && !empty($records['message'])) {
793
                if ($records['messageKey'] == 'noRecordings') {
794
                    $recordArray[] = get_lang('NoRecording');
795
                } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
796
                    //$recordArray[] = $records['message'];
797
                }
798
                return false;
799
            } else {
800
                $record = $records[0];
801
                if (is_array($record) && isset($record['recordId'])) {
802
                    $url = $record['playbackFormatUrl'];
803
                    $link = new Link();
0 ignored issues
show
Bug introduced by
The call to Link::__construct() misses some required arguments starting with $id.
Loading history...
804
                    $params['url'] = $url;
805
                    $params['title'] = $meetingData['meeting_name'];
806
                    $id = $link->save($params);
807
                    return $id;
808
                }
809
            }
810
        }
811
812
        return false;
813
    }
814
815
    /**
816
     * Checks if the videoconference server is running.
817
     * Function currently disabled (always returns 1)
818
     * @return bool True if server is running, false otherwise
819
     * @assert () === false
820
     */
821
    public function isServerRunning()
822
    {
823
        return true;
824
        //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url);
825
    }
826
827
    /**
828
     * Get active session in the all platform
829
     */
830
    public function getActiveSessionsCount()
831
    {
832
        $meetingList = Database::select(
833
            'count(id) as count',
834
            $this->table,
835
            array('where' => array('status = ?' => array(1))),
836
            'first'
837
        );
838
839
        return $meetingList['count'];
840
    }
841
842
    /**
843
     * @param string $url
844
     */
845
    public function redirectToBBB($url)
846
    {
847
        if (file_exists(__DIR__ . '/../config.vm.php')) {
848
            // Using VM
849
            echo Display::url(get_lang('ClickToContinue'), $url);
850
            exit;
851
        } else {
852
            // Classic
853
            header("Location: $url");
854
            exit;
855
        }
856
857
        // js
858
        /*echo '<script>';
859
        echo 'window.location = "'.$url.'"';
860
        echo '</script>';
861
        exit;*/
862
    }
863
864
    /**
865
     * @return string
866
     */
867
    public function getConferenceUrl()
868
    {
869
        return api_get_path(WEB_PLUGIN_PATH).'bbb/start.php?launch=1&'.api_get_cidreq();
870
    }
871
872
    /**
873
     * @return string
874
     */
875
    public function getListingUrl()
876
    {
877
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq();
878
    }
879
880
    /**
881
     * @param array $meeting
882
     * @return string
883
     */
884
    public function endUrl($meeting)
885
    {
886
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq().'&action=end&id='.$meeting['id'];
887
    }
888
889
    /**
890
     * @param array $meeting
891
     * @param array $record
892
     * @return string
893
     */
894
    public function addToCalendarUrl($meeting, $record = [])
895
    {
896
        $url = isset($record['playbackFormatUrl']) ? $record['playbackFormatUrl'] : '';
897
898
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq().'&action=add_to_calendar&id='.$meeting['id'].'&start='.api_strtotime($meeting['created_at']).'&url='.$url;
899
    }
900
901
    /**
902
     * @param array $meeting
903
     * @return string
904
     */
905
    public function publishUrl($meeting)
906
    {
907
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq().'&action=publish&id='.$meeting['id'];
908
    }
909
910
    /**
911
     * @param array $meeting
912
     * @return string
913
     */
914
    public function unPublishUrl($meeting)
915
    {
916
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq().'&action=unpublish&id='.$meeting['id'];
917
    }
918
919
    /**
920
     * @param array $meeting
921
     * @return string
922
     */
923
    public function deleteRecordUrl($meeting)
924
    {
925
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq().'&action=delete_record&id='.$meeting['id'];
926
    }
927
928
    /**
929
     * @param array $meeting
930
     * @return string
931
     */
932
    public function copyToRecordToLinkTool($meeting)
933
    {
934
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.api_get_cidreq().'&action=copy_record_to_link_tool&id='.$meeting['id'];
935
    }
936
}
937