Completed
Push — 1.10.x ( f81539...c82817 )
by Yannick
157:21 queued 99:33
created

bbb::getActionLinks()   C

Complexity

Conditions 7
Paths 20

Size

Total Lines 73
Code Lines 48

Duplication

Lines 22
Ratio 30.14 %

Importance

Changes 0
Metric Value
cc 7
eloc 48
nc 20
nop 4
dl 22
loc 73
rs 6.6896
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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