Completed
Push — 1.10.x ( a47b7a...621fef )
by
unknown
89:08 queued 37:34
created

bbb::isServerRunning()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 5
rs 9.4285
cc 1
eloc 2
nc 1
nop 0
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 = '';
24
    public $protocol = 'http://';
25
    public $debug = false;
26
    public $logoutUrl = '';
27
    public $pluginEnabled = false;
28
    public $enableGlobalConference = false;
29
    public $isGlobalConference = false;
30
    public $groupSupport = false;
31
32
    /**
33
     * Constructor (generates a connection to the API and the Chamilo settings
34
     * required for the connection to the video conference server)
35
     * @param string $host
36
     * @param string $salt
37
     */
38
    public function __construct($host = '', $salt = '', $isGlobalConference = false)
39
    {
40
        // Initialize video server settings from global settings
41
        $plugin = BBBPlugin::create();
42
43
        $bbbPlugin = $plugin->get('tool_enable');
44
45
        $bbb_host = !empty($host) ? $host : $plugin->get('host');
46
        $bbb_salt = !empty($salt) ? $salt : $plugin->get('salt');
47
48
        $this->logoutUrl = $this->getListingUrl();
49
        $this->table = Database::get_main_table('plugin_bbb_meeting');
50
        $this->enableGlobalConference = $plugin->get('enable_global_conference');
0 ignored issues
show
Documentation Bug introduced by
The property $enableGlobalConference was declared of type boolean, but $plugin->get('enable_global_conference') is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
51
        $this->isGlobalConference = (bool) $isGlobalConference;
52
53
        $columns = Database::listTableColumns($this->table);
54
        $this->groupSupport = isset($columns['group_id']) ? true : false;
55
56
        if ($bbbPlugin === true) {
57
            $userInfo = api_get_user_info();
58
            $this->user_complete_name = $userInfo['complete_name'];
59
            $this->salt = $bbb_salt;
60
            $info = parse_url($bbb_host);
61
            $this->url = $bbb_host.'/bigbluebutton/';
62
            if (isset($info['scheme'])) {
63
                $this->protocol = $info['scheme'].'://';
64
                $this->url = str_replace($this->protocol, '', $this->url);
65
            }
66
67
            // Setting BBB api
68
            define('CONFIG_SECURITY_SALT', $this->salt);
69
            define('CONFIG_SERVER_BASE_URL', $this->url);
70
71
            $this->api = new BigBlueButtonBN();
72
            $this->pluginEnabled = true;
73
        }
74
    }
75
76
    /**
77
     * @return bool
78
     */
79
    public function isGlobalConferenceEnabled()
80
    {
81
        return (bool) $this->enableGlobalConference;
82
    }
83
84
    /**
85
     * @return bool
86
     */
87
    public function isGlobalConference()
88
    {
89
        if ($this->isGlobalConferenceEnabled() === false) {
90
91
            return false;
92
        }
93
94
        return (bool) $this->isGlobalConference;
95
    }
96
97
    /**
98
     * @return bool
99
     */
100
    public function hasGroupSupport()
101
    {
102
        return $this->groupSupport;
103
    }
104
105
    /**
106
     * Checks whether a user is teacher in the current course
107
     * @return bool True if the user can be considered a teacher in this course, false otherwise
108
     */
109
    public function isConferenceManager()
110
    {
111
        return api_is_course_admin() || api_is_coach() || api_is_platform_admin();
112
    }
113
114
    /**
115
     * See this file in you BBB to set up default values
116
     * @param   array $params Array of parameters that will be completed if not containing all expected variables
117
118
       /var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties
119
     *
120
       More record information:
121
       http://code.google.com/p/bigbluebutton/wiki/RecordPlaybackSpecification
122
123
       # Default maximum number of users a meeting can have.
124
        # Doesn't get enforced yet but is the default value when the create
125
        # API doesn't pass a value.
126
        defaultMaxUsers=20
127
128
        # Default duration of the meeting in minutes.
129
        # Current default is 0 (meeting doesn't end).
130
        defaultMeetingDuration=0
131
132
        # Remove the meeting from memory when the end API is called.
133
        # This allows 3rd-party apps to recycle the meeting right-away
134
        # instead of waiting for the meeting to expire (see below).
135
        removeMeetingWhenEnded=false
136
137
        # The number of minutes before the system removes the meeting from memory.
138
        defaultMeetingExpireDuration=1
139
140
        # The number of minutes the system waits when a meeting is created and when
141
        # a user joins. If after this period, a user hasn't joined, the meeting is
142
        # removed from memory.
143
        defaultMeetingCreateJoinDuration=5
144
     *
145
     */
146
    public function createMeeting($params)
147
    {
148
        $courseCode = api_get_course_id();
149
        $params['c_id'] = api_get_course_int_id();
150
        $params['session_id'] = api_get_session_id();
151
152
        if ($this->hasGroupSupport()) {
153
            $params['group_id'] = api_get_group_id();
154
        }
155
156
        $params['attendee_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $courseCode;
157
        $attendeePassword =  $params['attendee_pw'];
158
        $params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $this->getModMeetingPassword();
159
        $moderatorPassword = $params['moderator_pw'];
160
161
        $params['record'] = api_get_course_setting('big_blue_button_record_and_store', $courseCode) == 1 ? true : false;
162
        $max = api_get_course_setting('big_blue_button_max_students_allowed', $courseCode);
163
        $max =  isset($max) ? $max : -1;
164
165
        $params['status'] = 1;
166
        // Generate a pseudo-global-unique-id to avoid clash of conferences on
167
        // the same BBB server with several Chamilo portals
168
        $params['remote_id'] = uniqid(true, true);
169
        // Each simultaneous conference room needs to have a different
170
        // voice_bridge composed of a 5 digits number, so generating a random one
171
        $params['voice_bridge'] = rand(10000, 99999);
172
173
        if ($this->debug) {
174
            error_log("enter create_meeting ".print_r($params, 1));
175
        }
176
177
        $params['created_at'] = api_get_utc_datetime();
178
        $id = Database::insert($this->table, $params);
179
180
        if ($id) {
181
            if ($this->debug) {
182
                error_log("create_meeting: $id ");
183
            }
184
185
            $meetingName = isset($params['meeting_name']) ? $params['meeting_name'] : $this->getCurrentVideoConferenceName();
186
            $welcomeMessage = isset($params['welcome_msg']) ? $params['welcome_msg'] : null;
187
            $record = isset($params['record']) && $params['record'] ? 'true' : 'false';
188
            $duration = isset($params['duration']) ? intval($params['duration']) : 0;
189
            // This setting currently limits the maximum conference duration,
190
            // to avoid lingering sessions on the video-conference server #6261
191
            $duration = 300;
192
193
            $bbbParams = array(
194
                'meetingId' => $params['remote_id'], 					// REQUIRED
195
                'meetingName' => $meetingName, 	// REQUIRED
196
                'attendeePw' => $attendeePassword, 					// Match this value in getJoinMeetingURL() to join as attendee.
197
                'moderatorPw' => $moderatorPassword, 					// Match this value in getJoinMeetingURL() to join as moderator.
198
                'welcomeMsg' => $welcomeMessage, 					// ''= use default. Change to customize.
199
                'dialNumber' => '', 					// The main number to call into. Optional.
200
                'voiceBridge' => $params['voice_bridge'], 					// PIN to join voice. Required.
201
                'webVoice' => '', 						// Alphanumeric to join voice. Optional.
202
                'logoutUrl' =>  $this->logoutUrl,
203
                'maxParticipants' => $max, 				// Optional. -1 = unlimitted. Not supported in BBB. [number]
204
                'record' => $record, 					// New. 'true' will tell BBB to record the meeting.
205
                'duration' => $duration, 				// Default = 0 which means no set duration in minutes. [number]
206
                //'meta_category' => '', 				// Use to pass additional info to BBB server. See API docs.
207
            );
208
209
            if ($this->debug) {
210
                error_log("create_meeting params: ".print_r($bbbParams,1));
211
            }
212
213
            $status = false;
214
            $meeting = null;
215
216
            while ($status === false) {
217
                $result = $this->api->createMeetingWithXmlResponseArray(
218
                    $bbbParams
219
                );
220
                if (isset($result) && strval($result['returncode']) == 'SUCCESS') {
221
                    if ($this->debug) {
222
                        error_log(
223
                            "create_meeting result: " . print_r($result, 1)
224
                        );
225
                    }
226
                    $meeting = $this->joinMeeting($meetingName, true);
227
228
                    return $meeting;
229
                }
230
            }
231
232
            return $this->logoutUrl;
233
        }
234
    }
235
236
    /**
237
     * Tells whether the given meeting exists and is running
238
     * (using course code as name)
239
     * @param string $meetingName Meeting name (usually the course code)
240
     *
241
     * @return bool True if meeting exists, false otherwise
242
     * @assert ('') === false
243
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
244
     */
245
    public function meetingExists($meetingName)
246
    {
247
        if (empty($meetingName)) {
248
249
            return false;
250
        }
251
252
        $courseId = api_get_course_int_id();
253
        $sessionId = api_get_session_id();
254
        $conditions =  array(
255
            'where' => array(
256
                'c_id = ? AND session_id = ? AND meeting_name = ? AND status = 1 ' =>
257
                    array($courseId, $sessionId, $meetingName)
258
            )
259
        );
260
261 View Code Duplication
        if ($this->hasGroupSupport()) {
262
            $groupId = api_get_group_id();
263
            $conditions =  array(
264
                'where' => array(
265
                    'c_id = ? AND session_id = ? AND meeting_name = ? AND group_id = ? AND status = 1 ' =>
266
                        array($courseId, $sessionId, $meetingName, $groupId)
267
                )
268
            );
269
        }
270
271
        $meetingData = Database::select(
272
            '*',
273
            $this->table,
274
            $conditions,
275
            'first'
276
        );
277
278
279
        if ($this->debug) {
280
            error_log("meeting_exists ".print_r($meetingData, 1));
281
        }
282
283
        if (empty($meetingData)) {
284
285
            return false;
286
        } else {
287
            return true;
288
        }
289
    }
290
291
    /**
292
     * Returns a meeting "join" URL
293
     * @param string The name of the meeting (usually the course code)
294
     * @return mixed The URL to join the meeting, or false on error
295
     * @todo implement moderator pass
296
     * @assert ('') === false
297
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
298
     */
299
    public function joinMeeting($meetingName, $loop = false)
300
    {
301
        if (empty($meetingName)) {
302
            return false;
303
        }
304
305
        $pass = $this->getUserMeetingPassword();
306
307
        $meetingData = Database::select(
308
            '*',
309
            $this->table,
310
            array('where' => array('meeting_name = ? AND status = 1 ' => $meetingName)),
311
            'first'
312
        );
313
314
        if (empty($meetingData) || !is_array($meetingData)) {
315
            if ($this->debug) {
316
                error_log("meeting does not exist: $meetingName");
317
            }
318
319
            return false;
320
        }
321
322
        $params = array(
323
            'meetingId' => $meetingData['remote_id'],
324
            //  -- REQUIRED - The unique id for the meeting
325
            'password' => $this->getModMeetingPassword()
326
            //  -- REQUIRED - The moderator password for the meeting
327
        );
328
329
        $status = false;
330
        $meetingInfoExists = false;
331
        while ($status === false) {
332
333
            $meetingIsRunningInfo = $this->getMeetingInfo($params);
334 View Code Duplication
            if ($meetingIsRunningInfo === false) {
335
                //checking with the remote_id didn't work, so just in case and
336
                // to provide backwards support, check with the id
337
                $params = array(
338
                    'meetingId' => $meetingData['id'],
339
                    //  -- REQUIRED - The unique id for the meeting
340
                    'password' => $this->getModMeetingPassword()
341
                    //  -- REQUIRED - The moderator password for the meeting
342
                );
343
                $meetingIsRunningInfo = $this->getMeetingInfo($params);
344
            }
345
346
            if ($this->debug) {
347
                error_log(print_r($meetingIsRunningInfo, 1));
348
            }
349
350
            if (strval($meetingIsRunningInfo['returncode']) == 'SUCCESS' &&
351
                isset($meetingIsRunningInfo['meetingName']) &&
352
                !empty($meetingIsRunningInfo['meetingName'])
353
                //strval($meetingIsRunningInfo['running']) == 'true'
354
            ) {
355
                $meetingInfoExists = true;
356
            }
357
358
            if ($this->debug) {
359
                error_log(
360
                    "meeting is running: " . intval($meetingInfoExists)
361
                );
362
            }
363
364
            if ($meetingInfoExists) {
365
                $status = true;
366
            }
367
368
            if ($loop) {
369
                continue;
370
            } else {
371
                break;
372
            }
373
        }
374
375
        if ($meetingInfoExists) {
376
            $joinParams = array(
377
                'meetingId' => $meetingData['remote_id'],	//	-- REQUIRED - A unique id for the meeting
378
                'username' => $this->user_complete_name,	//-- REQUIRED - The name that will display for the user in the meeting
379
                'password' => $pass,			//-- REQUIRED - The attendee or moderator password, depending on what's passed here
380
                //'createTime' => api_get_utc_datetime(),			//-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
381
                'userID' => api_get_user_id(),				//-- OPTIONAL - string
382
                'webVoiceConf' => ''	//	-- OPTIONAL - string
383
            );
384
            $url = $this->api->getJoinMeetingURL($joinParams);
385
            $url = $this->protocol.$url;
386
        } else {
387
            $url = $this->logoutUrl;
388
        }
389
        if ($this->debug) {
390
            error_log("return url :" . $url);
391
        }
392
393
        return $url;
394
    }
395
396
    /**
397
     * Get information about the given meeting
398
     * @param array ...?
399
     * @return mixed Array of information on success, false on error
400
     * @assert (array()) === false
401
     */
402
    public function getMeetingInfo($params)
403
    {
404
        try {
405
            $result = $this->api->getMeetingInfoWithXmlResponseArray($params);
406
            if ($result == null) {
407
                if ($this->debug) {
408
                    error_log("Failed to get any response. Maybe we can't contact the BBB server.");
409
                }
410
            } else {
411
                return $result;
412
            }
413
        } catch (Exception $e) {
414
            if ($this->debug) {
415
                error_log('Caught exception: ', $e->getMessage(), "\n");
416
            }
417
        }
418
419
        return false;
420
    }
421
422
    /**
423
     * Gets all the course meetings saved in the plugin_bbb_meeting table
424
     * @return array Array of current open meeting rooms
425
     */
426
    public function getMeetings()
427
    {
428
        $pass = $this->getUserMeetingPassword();
429
        $courseId = api_get_course_int_id();
430
        $sessionId  = api_get_session_id();
431
432
        $conditions =  array(
433
            'where' => array(
434
                'c_id = ? AND session_id = ? ' => array(
435
                    $courseId,
436
                    $sessionId,
437
                ),
438
            ),
439
        );
440
441 View Code Duplication
        if ($this->hasGroupSupport()) {
442
            $groupId = api_get_group_id();
443
            $conditions =  array(
444
                'where' => array(
445
                    'c_id = ? AND session_id = ? AND group_id = ? ' =>
446
                        array($courseId, $sessionId, $groupId)
447
                )
448
            );
449
        }
450
451
        $meetingList = Database::select(
452
            '*',
453
            $this->table,
454
            $conditions
455
        );
456
        $isGlobal = $this->isGlobalConference();
457
        $newMeetingList = array();
458
        $item = array();
459
        foreach ($meetingList as $meetingDB) {
460
            $meetingBBB = $this->getMeetingInfo(['meetingId' => $meetingDB['remote_id'], 'password' => $pass]);
461 View Code Duplication
            if ($meetingBBB === false) {
462
                //checking with the remote_id didn't work, so just in case and
463
                // to provide backwards support, check with the id
464
                $params = array(
465
                    'meetingId' => $meetingDB['id'],
466
                    //  -- REQUIRED - The unique id for the meeting
467
                    'password' => $pass
468
                    //  -- REQUIRED - The moderator password for the meeting
469
                );
470
                $meetingBBB = $this->getMeetingInfo($params);
471
            }
472
473
            if ($meetingDB['visibility'] == 0 && $this->isConferenceManager() === false) {
474
                continue;
475
            }
476
            $meetingBBB['end_url'] = $this->endUrl($meetingDB);
477
478
            if ((string)$meetingBBB['returncode'] == 'FAILED') {
479
                if ($meetingDB['status'] == 1 && $this->isConferenceManager()) {
480
                    $this->endMeeting($meetingDB['id']);
481
                }
482
            } else {
483
                $meetingBBB['add_to_calendar_url'] = $this->addToCalendarUrl($meetingDB);
484
            }
485
486
            $recordArray = array();
487
            $actionLinksArray = array();
488
489
            if ($meetingDB['record'] == 1) {
490
                // backwards compatibility (when there was no remote ID)
491
                $mId = $meetingDB['remote_id'];
492
                if (empty($mId)) {
493
                    $mId = $meetingDB['id'];
494
                }
495
                if (empty($mId)) {
496
                    // if the id is still empty (should *never* occur as 'id' is
497
                    // the table's primary key), skip this conference
498
                    continue;
499
                }
500
                $recordingParams = array(
501
                    'meetingId' => $mId, //-- OPTIONAL - comma separate if multiple ids
502
                );
503
504
                //To see the recording list in your BBB server do: bbb-record --list
505
                $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
506
                if (!empty($records)) {
507
                    $count = 1;
508
                    if (isset($records['message']) && !empty($records['message'])) {
509
                        if ($records['messageKey'] == 'noRecordings') {
510
                            $recordArray[] = get_lang('NoRecording');
511
                            if ($meetingDB['visibility'] == 0) {
512
                                $actionLinksArray[] = Display::url(
513
                                    Display::return_icon(
514
                                        'invisible.png',
515
                                        get_lang('MakeVisible'),
516
                                        array(),
517
                                        ICON_SIZE_MEDIUM
518
                                    ),
519
                                    $this->publishUrl($meetingDB)
520
                                );
521
                            } else {
522
                                $actionLinksArray[] = Display::url(
523
                                    Display::return_icon(
524
                                        'visible.png',
525
                                        get_lang('MakeInvisible'),
526
                                        array(),
527
                                        ICON_SIZE_MEDIUM
528
                                    ),
529
                                    $this->unPublishUrl($meetingDB)
530
                                );
531
                            }
532
                        }
533
                    } else {
534
                        foreach ($records as $record) {
535
                            //if you get several recordings here and you used a
536
                            // previous version of Chamilo, you might want to
537
                            // only keep the last result for each chamilo conf
538
                            // (see show_links after the end of this loop)
539
                            if (is_array($record) && isset($record['recordId'])) {
540
                                $url = Display::url(
541
                                    get_lang('ViewRecord')." [~".$record['playbackFormatLength']."']",
542
                                    $record['playbackFormatUrl'],
543
                                    array('target' => '_blank')
544
                                );
545
                                $actionLinks = '';
546
                                if ($this->isConferenceManager()) {
547
                                    if ($isGlobal === false) {
548
                                        $actionLinks .= Display::url(
549
                                            Display::return_icon(
550
                                                'link.gif',
551
                                                get_lang('CopyToLinkTool')
552
                                            ),
553
                                            $this->copyToRecordToLinkTool($meetingDB)
554
                                        );
555
                                        $actionLinks .= Display::url(
556
                                            Display::return_icon(
557
                                                'agenda.png',
558
                                                get_lang('AddToCalendar')
559
                                            ),
560
                                            $this->addToCalendarUrl($meetingDB, $record)
561
                                        );
562
                                    }
563
                                    $actionLinks .= Display::url(
564
                                        Display::return_icon(
565
                                            'delete.png',
566
                                            get_lang('Delete')
567
                                        ),
568
                                        $this->deleteRecordUrl($meetingDB)
569
                                    );
570
571 View Code Duplication
                                    if ($meetingDB['visibility'] == 0) {
572
                                        $actionLinks .= Display::url(
573
                                            Display::return_icon(
574
                                                'invisible.png',
575
                                                get_lang('MakeVisible'),
576
                                                array(),
577
                                                ICON_SIZE_MEDIUM
578
                                            ),
579
                                            $this->publishUrl($meetingDB)
580
                                        );
581
                                    } else {
582
                                        $actionLinks .= Display::url(
583
                                            Display::return_icon(
584
                                                'visible.png',
585
                                                get_lang('MakeInvisible'),
586
                                                array(),
587
                                                ICON_SIZE_MEDIUM
588
                                            ),
589
                                            $this->unPublishUrl($meetingDB)
590
                                        );
591
                                    }
592
                                }
593
                                $count++;
594
                                $recordArray[] = $url;
595
                                $actionLinksArray[] = $actionLinks;
596
                            } 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...
597
                                /*if (is_array($record) && isset($record['recordID']) && isset($record['playbacks'])) {
598
599
                                    //Fix the bbb timestamp
600
                                    //$record['startTime'] = substr($record['startTime'], 0, strlen($record['startTime']) -3);
601
                                    //$record['endTime']   = substr($record['endTime'], 0, strlen($record['endTime']) -3);
602
                                    //.' - '.api_convert_and_format_date($record['startTime']).' - '.api_convert_and_format_date($record['endTime'])
603
                                    foreach($record['playbacks'] as $item) {
604
                                        $url = Display::url(get_lang('ViewRecord'), $item['url'], array('target' => '_blank'));
605
                                        //$url .= Display::url(get_lang('DeleteRecord'), api_get_self().'?action=delete_record&'.$record['recordID']);
606
                                        if ($this->isConferenceManager()) {
607
                                            $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']);
608
                                            $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']);
609
                                            $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordID']);
610
                                        }
611
                                        //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
612
                                        $count++;
613
                                        $recordArray[] = $url;
614
                                    }
615
                                }*/
616
                            }
617
                        }
618
                    }
619
                } else {
620
                    $actionLinks = '';
621 View Code Duplication
                    if ($this->isConferenceManager()) {
622
                        if ($meetingDB['visibility'] == 0) {
623
                            $actionLinks .= Display::url(
624
                                Display::return_icon(
625
                                    'invisible.png',
626
                                    get_lang('MakeVisible'),
627
                                    array(),
628
                                    ICON_SIZE_MEDIUM
629
                                ),
630
                                $this->publishUrl($meetingDB)
631
                            );
632
                        } else {
633
                            $actionLinks .= Display::url(
634
                                Display::return_icon(
635
                                    'visible.png',
636
                                    get_lang('MakeInvisible'),
637
                                    array(),
638
                                    ICON_SIZE_MEDIUM
639
                                ),
640
                                $this->unPublishUrl($meetingDB)
641
                            );
642
                        }
643
                    }
644
                    $actionLinksArray[] = $actionLinks;
645
                    $item['action_links'] = implode('<br />', $actionLinksArray);
646
                }
647
                //var_dump($recordArray);
648
                $item['show_links']  = implode('<br />', $recordArray);
649
                $item['action_links'] = implode('<br />', $actionLinksArray);
650
            }
651
652
            $item['created_at'] = api_convert_and_format_date($meetingDB['created_at']);
653
            //created_at
654
            $meetingDB['created_at'] = $item['created_at']; //avoid overwrite in array_merge() below
655
656
            $item['publish_url'] = $this->publishUrl($meetingDB);
657
            $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...
658
659
            if ($meetingDB['status'] == 1) {
660
                $joinParams = array(
661
                    'meetingId' => $meetingDB['remote_id'],		//-- REQUIRED - A unique id for the meeting
662
                    'username' => $this->user_complete_name,	//-- REQUIRED - The name that will display for the user in the meeting
663
                    'password' => $pass,			//-- REQUIRED - The attendee or moderator password, depending on what's passed here
664
                    'createTime' => '',			//-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
665
                    'userID' => '',			//	-- OPTIONAL - string
666
                    'webVoiceConf' => ''	//	-- OPTIONAL - string
667
                );
668
                $item['go_url'] = $this->protocol.$this->api->getJoinMeetingURL($joinParams);
669
            }
670
            $item = array_merge($item, $meetingDB, $meetingBBB);
671
            $newMeetingList[] = $item;
672
        }
673
674
        return $newMeetingList;
675
    }
676
677
    /**
678
     * Function disabled
679
     */
680 View Code Duplication
    public function publishMeeting($id)
681
    {
682
        //return BigBlueButtonBN::setPublishRecordings($id, 'true', $this->url, $this->salt);
683
        if (empty($id)) {
684
685
            return false;
686
        }
687
        $id = intval($id);
688
        Database::update($this->table, array('visibility' => 1), array('id = ? ' => $id));
689
690
        return true;
691
    }
692
693
    /**
694
     * Function disabled
695
     */
696 View Code Duplication
    public function unpublishMeeting($id)
697
    {
698
        //return BigBlueButtonBN::setPublishRecordings($id, 'false', $this->url, $this->salt);
699
        if (empty($id)) {
700
701
            return false;
702
        }
703
        $id = intval($id);
704
        Database::update($this->table, array('visibility' => 0), array('id = ?' => $id));
705
706
        return true;
707
    }
708
709
    /**
710
     * Closes a meeting (usually when the user click on the close button from
711
     * the conferences listing.
712
     * @param string The internal ID of the meeting (id field for this meeting)
713
     * @return void
714
     * @assert (0) === false
715
     */
716
    public function endMeeting($id)
717
    {
718
        if (empty($id)) {
719
720
            return false;
721
        }
722
        $meetingData = Database::select('*', $this->table, array('where' => array('id = ?' => array($id))), 'first');
723
        $pass = $this->getUserMeetingPassword();
724
725
        $endParams = array(
726
            'meetingId' => $meetingData['remote_id'],   // REQUIRED - We have to know which meeting to end.
727
            'password' => $pass,        // REQUIRED - Must match moderator pass for meeting.
728
        );
729
        $this->api->endMeetingWithXmlResponseArray($endParams);
730
        Database::update(
731
            $this->table,
732
            array('status' => 0, 'closed_at' => api_get_utc_datetime()),
733
            array('id = ? ' => $id)
734
        );
735
    }
736
737
    /**
738
     * Gets the password for a specific meeting for the current user
739
     * @return string A moderator password if user is teacher, or the course code otherwise
740
     */
741
    public function getUserMeetingPassword()
742
    {
743
        if ($this->isConferenceManager()) {
744
745
            return $this->getModMeetingPassword();
746
        } else {
747
748
            if ($this->isGlobalConference()) {
749
750
                return 'url_'.api_get_current_access_url_id();
751
            }
752
753
            return api_get_course_id();
754
        }
755
    }
756
757
    /**
758
     * Generated a moderator password for the meeting
759
     * @return string A password for the moderation of the videoconference
760
     */
761
    public function getModMeetingPassword()
762
    {
763
        if ($this->isGlobalConference()) {
764
765
            return 'url_'.api_get_current_access_url_id().'_mod';
766
        }
767
768
        return api_get_course_id().'mod';
769
    }
770
771
    /**
772
     * Get users online in the current course room
773
     * @return int The number of users currently connected to the videoconference
774
     * @assert () > -1
775
     */
776
    public function getUsersOnlineInCurrentRoom()
777
    {
778
        $courseId = api_get_course_int_id();
779
        $sessionId = api_get_session_id();
780
781
        $conditions = array(
782
            'where' => array(
783
                'c_id = ? AND session_id = ? AND status = 1 ' => array(
784
                    $courseId,
785
                    $sessionId,
786
                ),
787
            ),
788
        );
789
790 View Code Duplication
        if ($this->hasGroupSupport()) {
791
            $groupId = api_get_group_id();
792
            $conditions = array(
793
                'where' => array(
794
                    'c_id = ? AND session_id = ? AND group_id = ? AND status = 1 ' => array(
795
                        $courseId,
796
                        $sessionId,
797
                        $groupId
798
                    ),
799
                ),
800
            );
801
        }
802
        $meetingData = Database::select(
803
            '*',
804
            $this->table,
805
            $conditions,
806
            'first'
807
        );
808
809
        if (empty($meetingData)) {
810
            return 0;
811
        }
812
        $pass = $this->getModMeetingPassword();
813
        $info = $this->getMeetingInfo(array('meetingId' => $meetingData['remote_id'], 'password' => $pass));
814 View Code Duplication
        if ($info === false) {
815
            //checking with the remote_id didn't work, so just in case and
816
            // to provide backwards support, check with the id
817
            $params = array(
818
                'meetingId' => $meetingData['id'],
819
                //  -- REQUIRED - The unique id for the meeting
820
                'password' => $pass
821
                //  -- REQUIRED - The moderator password for the meeting
822
            );
823
            $info = $this->getMeetingInfo($params);
824
        }
825
826
        if (!empty($info) && isset($info['participantCount'])) {
827
            return $info['participantCount'];
828
829
        }
830
        return 0;
831
    }
832
833
    /**
834
     * Deletes a previous recording of a meeting
835
     * @param int integral ID of the recording
836
     * @return array ?
837
     * @assert () === false
838
     * @todo Also delete links and agenda items created from this recording
839
     */
840
    public function deleteRecord($id)
841
    {
842
        if (empty($id)) {
843
            return false;
844
        }
845
846
        $meetingData = Database::select(
847
            '*',
848
            $this->table,
849
            array('where' => array('id = ?' => array($id))),
850
            'first'
851
        );
852
853
        $recordingParams = array(
854
            /*
855
             * NOTE: Set the recordId below to a valid id after you have
856
             * created a recorded meeting, and received a real recordID
857
             * back from your BBB server using the
858
             * getRecordingsWithXmlResponseArray method.
859
             */
860
861
            // REQUIRED - We have to know which recording:
862
            'recordId' => $meetingData['remote_id'],
863
        );
864
865
        $result = $this->api->deleteRecordingsWithXmlResponseArray($recordingParams);
866
867
        if (!empty($result) && isset($result['deleted']) && $result['deleted'] == 'true') {
868
            Database::delete(
869
                $this->table,
870
                array('id = ?' => array($id))
871
            );
872
        }
873
874
        return $result;
875
    }
876
877
    /**
878
     * Creates a link in the links tool from the given videoconference recording
879
     * @param int ID of the item in the plugin_bbb_meeting table
880
     * @param string Hash identifying the recording, as provided by the API
881
     * @return mixed ID of the newly created link, or false on error
882
     * @assert (null, null) === false
883
     * @assert (1, null) === false
884
     * @assert (null, 'abcdefabcdefabcdefabcdef') === false
885
     */
886
    public function copyRecordToLinkTool($id)
887
    {
888
        if (empty($id)) {
889
            return false;
890
        }
891
        //$records =  BigBlueButtonBN::getRecordingsUrl($id);
892
        $meetingData = Database::select('*', $this->table, array('where' => array('id = ?' => array($id))), 'first');
893
894
        $records = $this->api->getRecordingsWithXmlResponseArray(array('meetingId' => $meetingData['remote_id']));
895
896
        if (!empty($records)) {
897
            if (isset($records['message']) && !empty($records['message'])) {
898
                if ($records['messageKey'] == 'noRecordings') {
899
                    $recordArray[] = get_lang('NoRecording');
900
                } 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...
901
                    //$recordArray[] = $records['message'];
902
                }
903
                return false;
904
            } else {
905
                $record = $records[0];
906
                if (is_array($record) && isset($record['recordId'])) {
907
                    $url = $record['playbackFormatUrl'];
908
                    $link = new Link();
0 ignored issues
show
Bug introduced by
The call to Link::__construct() misses some required arguments starting with $id.
Loading history...
909
                    $params['url'] = $url;
910
                    $params['title'] = $meetingData['meeting_name'];
911
                    $id = $link->save($params);
912
                    return $id;
913
                }
914
            }
915
        }
916
917
        return false;
918
    }
919
920
    /**
921
     * Checks if the videoconference server is running.
922
     * Function currently disabled (always returns 1)
923
     * @return bool True if server is running, false otherwise
924
     * @assert () === false
925
     */
926
    public function isServerRunning()
927
    {
928
        return true;
929
        //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url);
930
    }
931
932
    /**
933
     * Get active session in the all platform
934
     */
935
    public function getActiveSessionsCount()
936
    {
937
        $meetingList = Database::select(
938
            'count(id) as count',
939
            $this->table,
940
            array('where' => array('status = ?' => array(1))),
941
            'first'
942
        );
943
944
        return $meetingList['count'];
945
    }
946
947
    /**
948
     * @param string $url
949
     */
950
    public function redirectToBBB($url)
951
    {
952
        if (file_exists(__DIR__ . '/../config.vm.php')) {
953
            // Using VM
954
            echo Display::url(get_lang('ClickToContinue'), $url);
955
            exit;
956
        } else {
957
            // Classic
958
            header("Location: $url");
959
            exit;
960
        }
961
962
        // js
963
        /*echo '<script>';
964
        echo 'window.location = "'.$url.'"';
965
        echo '</script>';
966
        exit;*/
967
    }
968
969
    /**
970
     * @return string
971
     */
972
    public function getUrlParams()
973
    {
974
        $courseInfo = api_get_course_info();
975
976
        if (empty($courseInfo)) {
977
978
            if ($this->isGlobalConference()) {
979
                return 'global=1';
980
            }
981
982
            return '';
983
        }
984
985
        return api_get_cidreq();
986
    }
987
988
    /**
989
     * @return string
990
     */
991
    public function getCurrentVideoConferenceName()
992
    {
993
        if ($this->isGlobalConference()) {
994
            return 'url_'.api_get_current_access_url_id();
995
        }
996
997
        if ($this->hasGroupSupport()) {
998
999
            return api_get_course_id().'-'.api_get_session_id().'-'.api_get_group_id();
1000
        }
1001
        
1002
        return api_get_course_id().'-'.api_get_session_id();
1003
    }
1004
1005
    /**
1006
     * @return string
1007
     */
1008
    public function getConferenceUrl()
1009
    {
1010
        return api_get_path(WEB_PLUGIN_PATH).'bbb/start.php?launch=1&'.$this->getUrlParams();
1011
    }
1012
1013
    /**
1014
     * @return string
1015
     */
1016
    public function getListingUrl()
1017
    {
1018
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams();
1019
    }
1020
1021
    /**
1022
     * @param array $meeting
1023
     * @return string
1024
     */
1025
    public function endUrl($meeting)
1026
    {
1027
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=end&id='.$meeting['id'];
1028
    }
1029
1030
    /**
1031
     * @param array $meeting
1032
     * @param array $record
1033
     * @return string
1034
     */
1035
    public function addToCalendarUrl($meeting, $record = [])
1036
    {
1037
        $url = isset($record['playbackFormatUrl']) ? $record['playbackFormatUrl'] : '';
1038
1039
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=add_to_calendar&id='.$meeting['id'].'&start='.api_strtotime($meeting['created_at']).'&url='.$url;
1040
    }
1041
1042
    /**
1043
     * @param array $meeting
1044
     * @return string
1045
     */
1046
    public function publishUrl($meeting)
1047
    {
1048
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=publish&id='.$meeting['id'];
1049
    }
1050
1051
    /**
1052
     * @param array $meeting
1053
     * @return string
1054
     */
1055
    public function unPublishUrl($meeting)
1056
    {
1057
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=unpublish&id='.$meeting['id'];
1058
    }
1059
1060
    /**
1061
     * @param array $meeting
1062
     * @return string
1063
     */
1064
    public function deleteRecordUrl($meeting)
1065
    {
1066
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=delete_record&id='.$meeting['id'];
1067
    }
1068
1069
    /**
1070
     * @param array $meeting
1071
     * @return string
1072
     */
1073
    public function copyToRecordToLinkTool($meeting)
1074
    {
1075
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=copy_record_to_link_tool&id='.$meeting['id'];
1076
    }
1077
}
1078