Completed
Push — 1.10.x ( d0b403...7fd4c8 )
by Angel Fernando Quiroz
36:26
created

bbb::findMeetingByName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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