bbb::createMeeting()   F
last analyzed

Complexity

Conditions 14
Paths 352

Size

Total Lines 93
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 63
c 0
b 0
f 0
dl 0
loc 93
rs 3.5333
cc 14
nc 352
nop 1

How to fix   Long Method    Complexity   

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
3
/* For licensing terms, see /license.txt */
4
5
/**
6
 * Class bbb
7
 * This script initiates a video conference session, calling the BigBlueButton
8
 * API BigBlueButton-Chamilo connector class
9
 */
10
class bbb
11
{
12
    public $url;
13
    public $salt;
14
    public $api;
15
    public $userCompleteName = '';
16
    public $protocol = 'http://';
17
    public $debug = false;
18
    public $logoutUrl = '';
19
    public $pluginEnabled = false;
20
    public $enableGlobalConference = false;
21
    public $enableGlobalConferencePerUser = false;
22
    public $isGlobalConference = false;
23
    public $groupSupport = false;
24
    public $userSupport = false;
25
    public $accessUrl = 1;
26
    public $userId = 0;
27
    public $plugin;
28
    private $courseCode;
29
    private $courseId;
30
    private $sessionId;
31
    private $groupId;
32
    private $maxUsersLimit;
33
34
    /**
35
     * Constructor (generates a connection to the API and the Chamilo settings
36
     * required for the connection to the video conference server)
37
     *
38
     * @param string $host
39
     * @param string $salt
40
     * @param bool   $isGlobalConference
41
     * @param int    $isGlobalPerUser
42
     */
43
    public function __construct(
44
        $host = '',
45
        $salt = '',
46
        $isGlobalConference = false,
47
        $isGlobalPerUser = 0
48
    ) {
49
        $this->courseCode = api_get_course_id();
50
        $this->courseId = api_get_course_int_id();
51
        $this->sessionId = api_get_session_id();
52
        $this->groupId = api_get_group_id();
53
54
        // Initialize video server settings from global settings
55
        $this->plugin = BBBPlugin::create();
56
        $bbbPluginEnabled = $this->plugin->get('tool_enable');
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

56
        /** @scrutinizer ignore-call */ 
57
        $bbbPluginEnabled = $this->plugin->get('tool_enable');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
57
58
        $bbb_host = !empty($host) ? $host : $this->plugin->get('host');
59
        $bbb_salt = !empty($salt) ? $salt : $this->plugin->get('salt');
60
61
        $this->table = Database::get_main_table('plugin_bbb_meeting');
62
        $this->enableGlobalConference = $this->plugin->get('enable_global_conference') === 'true';
63
        $this->isGlobalConference = (bool) $isGlobalConference;
64
65
        $columns = Database::listTableColumns($this->table);
66
        $this->groupSupport = isset($columns['group_id']) ? true : false;
67
        $this->userSupport = isset($columns['user_id']) ? true : false;
68
        $this->accessUrl = api_get_current_access_url_id();
69
70
        $this->enableGlobalConferencePerUser = false;
71
        if ($this->userSupport && !empty($isGlobalPerUser)) {
72
            $this->enableGlobalConferencePerUser = $this->plugin->get('enable_global_conference_per_user') === 'true';
73
            $this->userId = $isGlobalPerUser;
74
        }
75
76
        if ($this->groupSupport) {
77
            // Plugin check
78
            $this->groupSupport = $this->plugin->get('enable_conference_in_course_groups') === 'true' ? true : false;
79
            if ($this->groupSupport) {
80
                // Platform check
81
                $bbbSetting = api_get_setting('bbb_enable_conference_in_course_groups');
82
                $bbbSetting = isset($bbbSetting['bbb']) ? $bbbSetting['bbb'] === 'true' : false;
83
84
                if ($bbbSetting) {
85
                    // Course check
86
                    $courseInfo = api_get_course_info();
87
                    if ($courseInfo) {
88
                        $this->groupSupport = api_get_course_plugin_setting(
89
                                'bbb',
90
                                'bbb_enable_conference_in_groups',
91
                                $courseInfo
92
                            ) === '1';
93
                    }
94
                }
95
            }
96
        }
97
        $this->maxUsersLimit = $this->plugin->get('max_users_limit');
98
99
        if ($bbbPluginEnabled === 'true') {
100
            $userInfo = api_get_user_info();
101
            if (empty($userInfo) && !empty($isGlobalPerUser)) {
102
                // If we are following a link to a global "per user" conference
103
                // then generate a random guest name to join the conference
104
                // because there is no part of the process where we give a name
105
                //$this->userCompleteName = 'Guest'.rand(1000, 9999);
106
            } else {
107
                $this->userCompleteName = $userInfo['complete_name'];
108
            }
109
110
            if (api_is_anonymous()) {
111
                $this->userCompleteName = get_lang('Guest').'_'.rand(1000, 9999);
112
            }
113
114
            $this->salt = $bbb_salt;
115
            if (!empty($bbb_host)) {
116
                if (substr($bbb_host, -1, 1) !== '/') {
117
                    $bbb_host .= '/';
118
                }
119
                $this->url = $bbb_host;
120
                if (!preg_match('#/bigbluebutton/$#', $bbb_host)) {
121
                    $this->url = $bbb_host.'bigbluebutton/';
122
                }
123
            }
124
            $info = parse_url($bbb_host);
125
126
            if (isset($info['scheme'])) {
127
                $this->protocol = $info['scheme'].'://';
128
                $this->url = str_replace($this->protocol, '', $this->url);
129
                $urlWithProtocol = $bbb_host;
130
            } else {
131
                // We assume it's an http, if user wants to use https, the host *must* include the protocol.
132
                $this->protocol = 'http://';
133
                $urlWithProtocol = $this->protocol.$bbb_host;
134
            }
135
136
            // Setting BBB api
137
            define('CONFIG_SECURITY_SALT', $this->salt);
138
            define('CONFIG_SERVER_URL_WITH_PROTOCOL', $urlWithProtocol);
139
            define('CONFIG_SERVER_BASE_URL', $this->url);
140
            define('CONFIG_SERVER_PROTOCOL', $this->protocol);
141
142
            $this->api = new BigBlueButtonBN();
143
            $this->pluginEnabled = true;
144
            $this->logoutUrl = $this->getListingUrl();
145
        }
146
    }
147
148
    /**
149
     * @param int $courseId  Optional. Course ID.
150
     * @param int $sessionId Optional. Session ID.
151
     * @param int $groupId   Optional. Group ID.
152
     *
153
     * @return string
154
     */
155
    public function getListingUrl($courseId = 0, $sessionId = 0, $groupId = 0)
156
    {
157
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'
158
            .$this->getUrlParams($courseId, $sessionId, $groupId);
159
    }
160
161
    /**
162
     * @param int $courseId  Optional. Course ID.
163
     * @param int $sessionId Optional. Session ID.
164
     * @param int $groupId   Optional. Group ID.
165
     *
166
     * @return string
167
     */
168
    public function getUrlParams($courseId = 0, $sessionId = 0, $groupId = 0)
169
    {
170
        if (empty($this->courseCode) && !$courseId) {
171
            if ($this->isGlobalConferencePerUserEnabled()) {
172
                return 'global=1&user_id='.$this->userId;
173
            }
174
175
            if ($this->isGlobalConference()) {
176
                return 'global=1';
177
            }
178
179
            return '';
180
        }
181
182
        $courseCode = $this->courseCode;
183
        if (!empty($courseId)) {
184
            $course = api_get_course_info_by_id($courseId);
185
            if ($course) {
186
                $courseCode = $course['code'];
187
            }
188
        }
189
190
        return http_build_query(
191
            [
192
                'cidReq' => $courseCode,
193
                'id_session' => $sessionId ?: $this->sessionId,
194
                'gidReq' => $groupId ?: $this->groupId,
195
            ]
196
        );
197
    }
198
199
    /**
200
     * @return bool
201
     */
202
    public function isGlobalConferencePerUserEnabled()
203
    {
204
        return $this->enableGlobalConferencePerUser;
205
    }
206
207
    /**
208
     * @return bool
209
     */
210
    public function isGlobalConference()
211
    {
212
        if ($this->isGlobalConferenceEnabled() === false) {
213
            return false;
214
        }
215
216
        return (bool) $this->isGlobalConference;
217
    }
218
219
    /**
220
     * @return bool
221
     */
222
    public function isGlobalConferenceEnabled()
223
    {
224
        return $this->enableGlobalConference;
225
    }
226
227
    /**
228
     * @param array $userInfo
229
     *
230
     * @return bool
231
     */
232
    public static function showGlobalConferenceLink($userInfo)
233
    {
234
        if (empty($userInfo)) {
235
            return false;
236
        }
237
        $setting = api_get_plugin_setting('bbb', 'enable_global_conference');
238
        $settingLink = api_get_plugin_setting('bbb', 'enable_global_conference_link');
239
        if ($setting === 'true' && $settingLink === 'true') {
240
            //$content = Display::url(get_lang('LaunchVideoConferenceRoom'), $url);
241
            $allowedRoles = api_get_plugin_setting(
242
                'bbb',
243
                'global_conference_allow_roles'
244
            );
245
246
            if (api_is_platform_admin()) {
247
                $userInfo['status'] = PLATFORM_ADMIN;
248
            }
249
250
            $showGlobalLink = true;
251
            if (!empty($allowedRoles)) {
252
                if (!in_array($userInfo['status'], $allowedRoles)) {
253
                    $showGlobalLink = false;
254
                }
255
            }
256
257
            return $showGlobalLink;
258
        }
259
    }
260
261
    /**
262
     * Gets the global limit of users in a video-conference room.
263
     * This value can be overridden by course-specific values
264
     * @return  int Maximum number of users set globally
265
     */
266
    public function getMaxUsersLimit()
267
    {
268
        $limit = $this->maxUsersLimit;
269
        if ($limit <= 0) {
270
            $limit = 0;
271
        }
272
        $courseLimit = 0;
273
        $sessionLimit = 0;
274
        // Check the extra fields for this course and session
275
        // Session limit takes priority over course limit
276
        // Course limit takes priority over global limit
277
        if (!empty($this->courseId)) {
278
            $extraField = new ExtraField('course');
279
            $fieldId = $extraField->get_all(
280
                array('variable = ?' => 'plugin_bbb_course_users_limit')
281
            );
282
            $extraValue = new ExtraFieldValue('course');
283
            $value = $extraValue->get_values_by_handler_and_field_id($this->courseId, $fieldId[0]['id']);
284
            if (!empty($value['value'])) {
285
                $courseLimit = (int) $value['value'];
286
            }
287
        }
288
        if (!empty($this->sessionId)) {
289
            $extraField = new ExtraField('session');
290
            $fieldId = $extraField->get_all(
291
                array('variable = ?' => 'plugin_bbb_session_users_limit')
292
            );
293
            $extraValue = new ExtraFieldValue('session');
294
            $value = $extraValue->get_values_by_handler_and_field_id($this->sessionId, $fieldId[0]['id']);
295
            if (!empty($value['value'])) {
296
                $sessionLimit = (int) $value['value'];
297
            }
298
        }
299
300
        if (!empty($sessionLimit)) {
301
            return $sessionLimit;
302
        } elseif (!empty($courseLimit)) {
303
            return $courseLimit;
304
        }
305
306
        return (int) $limit;
307
    }
308
309
    /**
310
     * Sets the global limit of users in a video-conference room.
311
     *
312
     * @param int Maximum number of users (globally)
313
     */
314
    public function setMaxUsersLimit($max)
315
    {
316
        if ($max < 0) {
317
            $max = 0;
318
        }
319
        $this->maxUsersLimit = (int) $max;
320
    }
321
322
    /**
323
     * See this file in you BBB to set up default values
324
     *
325
     * @param array $params Array of parameters that will be completed if not containing all expected variables
326
     *
327
     * /var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties
328
     *
329
     * More record information:
330
     * http://code.google.com/p/bigbluebutton/wiki/RecordPlaybackSpecification
331
     *
332
     * Default maximum number of users a meeting can have.
333
     * Doesn't get enforced yet but is the default value when the create
334
     * API doesn't pass a value.
335
     * defaultMaxUsers=20
336
     *
337
     * Default duration of the meeting in minutes.
338
     * Current default is 0 (meeting doesn't end).
339
     * defaultMeetingDuration=0
340
     *
341
     * Remove the meeting from memory when the end API is called.
342
     * This allows 3rd-party apps to recycle the meeting right-away
343
     * instead of waiting for the meeting to expire (see below).
344
     * removeMeetingWhenEnded=false
345
     *
346
     * The number of minutes before the system removes the meeting from memory.
347
     * defaultMeetingExpireDuration=1
348
     *
349
     * The number of minutes the system waits when a meeting is created and when
350
     * a user joins. If after this period, a user hasn't joined, the meeting is
351
     * removed from memory.
352
     * defaultMeetingCreateJoinDuration=5
353
     *
354
     * @return mixed
355
     */
356
    public function createMeeting($params)
357
    {
358
        $params['c_id'] = api_get_course_int_id();
359
        $params['session_id'] = api_get_session_id();
360
361
        if ($this->hasGroupSupport()) {
362
            $params['group_id'] = api_get_group_id();
363
        }
364
365
        if ($this->isGlobalConferencePerUserEnabled() && !empty($this->userId)) {
366
            $params['user_id'] = (int) $this->userId;
367
        }
368
369
        $params['attendee_pw'] = isset($params['attendee_pw']) ? $params['attendee_pw'] : $this->getUserMeetingPassword();
370
        $attendeePassword = $params['attendee_pw'];
371
        $params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $this->getModMeetingPassword();
372
        $moderatorPassword = $params['moderator_pw'];
373
374
        $params['record'] = api_get_course_plugin_setting('bbb', 'big_blue_button_record_and_store') == 1;
375
        $max = api_get_course_plugin_setting('bbb', 'max_users_limit');
376
        $max = isset($max) ? $max : -1;
377
378
        $params['status'] = 1;
379
        // Generate a pseudo-global-unique-id to avoid clash of conferences on
380
        // the same BBB server with several Chamilo portals
381
        $params['remote_id'] = uniqid(true, true);
382
        // Each simultaneous conference room needs to have a different
383
        // voice_bridge composed of a 5 digits number, so generating a random one
384
        $params['voice_bridge'] = rand(10000, 99999);
385
        $params['created_at'] = api_get_utc_datetime();
386
        $params['access_url'] = $this->accessUrl;
387
388
        $id = Database::insert($this->table, $params);
389
390
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
391
            Event::addEvent(
0 ignored issues
show
Bug introduced by
The method addEvent() does not exist on Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

391
            Event::/** @scrutinizer ignore-call */ 
392
                   addEvent(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
392
                'bbb_create_meeting',
393
                'meeting_id',
394
                (int) $id,
395
                null,
396
                api_get_user_id(),
397
                api_get_course_int_id(),
398
                api_get_session_id()
399
            );
400
401
            $meetingName = $params['meeting_name'] ?? $this->generateVideoConferenceName();
402
            $welcomeMessage = $params['welcome_msg'] ?? null;
403
            $record = $params['record'] ? 'true' : 'false';
404
            //$duration = isset($params['duration']) ? intval($params['duration']) : 0;
405
            // This setting currently limits the maximum conference duration,
406
            // to avoid lingering sessions on the video-conference server #6261
407
            $duration = 300;
408
            $meetingDuration = (int) $this->plugin->get('meeting_duration');
409
            if (!empty($meetingDuration)) {
410
                $duration = $meetingDuration;
411
            }
412
            $url = api_get_access_url(api_get_current_access_url_id())['url'];
413
            $bbbParams = array(
414
                'meetingId' => $params['remote_id'], // REQUIRED
415
                'meetingName' => $meetingName, // REQUIRED
416
                'attendeePw' => $attendeePassword, // Match this value in getJoinMeetingURL() to join as attendee.
417
                'moderatorPw' => $moderatorPassword, // Match this value in getJoinMeetingURL() to join as moderator.
418
                'welcomeMsg' => $welcomeMessage, // ''= use default. Change to customize.
419
                'dialNumber' => '', // The main number to call into. Optional.
420
                'voiceBridge' => $params['voice_bridge'], // PIN to join voice. Required.
421
                'webVoice' => '', // Alphanumeric to join voice. Optional.
422
                'logoutUrl' => $this->logoutUrl.'&action=logout&remote_id='.$params['remote_id'],
423
                'maxParticipants' => $max, // Optional. -1 = unlimitted. Not supported in BBB. [number]
424
                'record' => $record, // New. 'true' will tell BBB to record the meeting.
425
                'duration' => $duration, // Default = 0 which means no set duration in minutes. [number]
426
                'meta_OriginURL' => $url, // Add url information to BBB meeting info (see 'meta' info at https://docs.bigbluebutton.org/dev/api.html#create)
427
                //'meta_category' => '',  // Use to pass additional info to BBB server. See API docs.
428
            );
429
430
            $status = false;
431
            $meeting = null;
432
            while ($status === false) {
433
                $result = $this->api->createMeetingWithXmlResponseArray($bbbParams);
434
                if (isset($result) && strval($result['returncode']) == 'SUCCESS') {
435
                    if ($this->plugin->get('allow_regenerate_recording') === 'true') {
436
                        $internalId = Database::escape_string($result['internalMeetingID']);
437
                        $sql = "UPDATE $this->table SET internal_meeting_id = '".$internalId."'
438
                                WHERE id = $id";
439
                        Database::query($sql);
440
                    }
441
                    $meeting = $this->joinMeeting($meetingName, true);
442
443
                    return $meeting;
444
                }
445
            }
446
        }
447
448
        return false;
449
    }
450
451
    /**
452
     * @return bool
453
     */
454
    public function hasGroupSupport()
455
    {
456
        return $this->groupSupport;
457
    }
458
459
    /**
460
     * Gets the password for a specific meeting for the current user
461
     *
462
     * @param string $courseCode
463
     *
464
     * @return string A moderator password if user is teacher, or the course code otherwise
465
     *
466
     */
467
    public function getUserMeetingPassword($courseCode = null)
468
    {
469
        if ($this->isGlobalConferencePerUserEnabled()) {
470
            return 'url_'.$this->userId.'_'.api_get_current_access_url_id();
471
        }
472
473
        if ($this->isGlobalConference()) {
474
            return 'url_'.api_get_current_access_url_id();
475
        }
476
        $courseCode = empty($courseCode) ? api_get_course_id() : $courseCode;
477
478
        return $courseCode;
479
    }
480
481
    /**
482
     * Generated a moderator password for the meeting.
483
     *
484
     * @param string $courseCode
485
     *
486
     * @return string A password for the moderation of the videoconference
487
     */
488
    public function getModMeetingPassword($courseCode = null)
489
    {
490
        if ($this->isGlobalConferencePerUserEnabled()) {
491
            return 'url_'.$this->userId.'_'.api_get_current_access_url_id().'_mod';
492
        }
493
494
        if ($this->isGlobalConference()) {
495
            return 'url_'.api_get_current_access_url_id().'_mod';
496
        }
497
498
        $courseCode = empty($courseCode) ? api_get_course_id() : $courseCode;
499
500
        return $courseCode.'mod';
501
    }
502
503
    /**
504
     * Get the info from the current open videoconference.
505
     * Otherwise, return false.
506
     *
507
     * @return array|bool
508
     */
509
    public function getCurrentVideoConference()
510
    {
511
        $whereConditions = [
512
            'status = ?' => 1,
513
        ];
514
515
        if ($this->isGlobalConferencePerUserEnabled()) {
516
            $whereConditions[' AND user_id = ?'] = $this->userId;
517
        }
518
519
        if ($this->isGlobalConference()) {
520
            $whereConditions[' AND access_url = ?'] = api_get_current_access_url_id();
521
        }
522
523
        if ($this->hasGroupSupport()) {
524
            $whereConditions[' AND group_id = ?'] = api_get_group_id();
525
        }
526
527
        $cId = api_get_course_int_id();
528
        $sessionId = api_get_session_id();
529
530
        if ($cId) {
531
            $whereConditions[' AND c_id = ?'] = api_get_course_int_id();
532
        }
533
534
        if ($sessionId) {
535
            $whereConditions[' AND session_id = ?'] = api_get_session_id();
536
        }
537
538
        return Database::select(
539
            '*',
540
            $this->table,
541
            [
542
                'where' => $whereConditions,
543
                'order' => 'created_at DESC',
544
            ],
545
            'first'
546
        );
547
    }
548
549
    public function generateVideoConferenceName(string $defaultName = null): string
550
    {
551
        $nameFilter = function ($name) {
552
            return URLify::filter(
553
                $name,
554
                64,
555
                '',
556
                true,
557
                true,
558
                true,
559
                false
560
            );
561
        };
562
563
        if (!empty($defaultName)) {
564
            $name = $nameFilter($defaultName);
565
566
            if (!empty($name)) {
567
                return $name;
568
            }
569
        }
570
571
        $urlId = api_get_current_access_url_id();
572
573
        if ($this->isGlobalConferencePerUserEnabled()) {
574
            return $nameFilter("url_{$this->userId}_$urlId");
575
        }
576
577
        if ($this->isGlobalConference()) {
578
            return $nameFilter("url_$urlId");
579
        }
580
581
        $course = api_get_course_entity();
582
        $session = api_get_session_entity();
583
        $group = api_get_group_entity();
584
585
        if ($this->hasGroupSupport()) {
586
            $name = implode(
587
                '-',
588
                [
589
                    $course->getCode(),
590
                    $session ? $session->getName() : '',
0 ignored issues
show
introduced by
$session is of type Chamilo\CoreBundle\Entity\Session, thus it always evaluated to true.
Loading history...
591
                    $group ? $group->getName() : '',
592
                ]
593
            );
594
595
            return $nameFilter($name);
596
        }
597
598
        $name = implode(
599
            '-',
600
            [
601
                $course->getCode(),
602
                $session ? $session->getName() : '',
0 ignored issues
show
introduced by
$session is of type Chamilo\CoreBundle\Entity\Session, thus it always evaluated to true.
Loading history...
603
            ]
604
        );
605
606
        return $nameFilter($name);
607
    }
608
609
    /**
610
     * Returns a meeting "join" URL
611
     *
612
     * @param string The name of the meeting (usually the course code)
613
     *
614
     * @return mixed The URL to join the meeting, or false on error
615
     * @todo implement moderator pass
616
     * @assert ('') === false
617
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
618
     */
619
    public function joinMeeting($meetingName)
620
    {
621
        if ($this->debug) {
622
            error_log("joinMeeting: $meetingName");
623
        }
624
625
        if (empty($meetingName)) {
626
            return false;
627
        }
628
629
        $manager = $this->isConferenceManager();
630
        if ($manager) {
631
            $pass = $this->getModMeetingPassword();
632
        } else {
633
            $pass = $this->getUserMeetingPassword();
634
        }
635
636
        $meetingData = Database::select(
637
            '*',
638
            $this->table,
639
            array(
640
                'where' => array(
641
                    'meeting_name = ? AND status = 1' => array(
642
                        $meetingName,
643
                    ),
644
                ),
645
            ),
646
            'first'
647
        );
648
649
        if (empty($meetingData) || !is_array($meetingData)) {
650
            if ($this->debug) {
651
                error_log("meeting does not exist: $meetingName");
652
            }
653
654
            return false;
655
        }
656
657
        $params = array(
658
            'meetingId' => $meetingData['remote_id'],
659
            //  -- REQUIRED - The unique id for the meeting
660
            'password' => $this->getModMeetingPassword()
661
            //  -- REQUIRED - The moderator password for the meeting
662
        );
663
664
        $meetingInfoExists = false;
665
        $meetingIsRunningInfo = $this->getMeetingInfo($params);
666
        if ($this->debug) {
667
            error_log('Searching meeting with params:');
668
            error_log(print_r($params, 1));
669
            error_log('Result:');
670
            error_log(print_r($meetingIsRunningInfo, 1));
671
        }
672
673
        if ($meetingIsRunningInfo === false) {
674
            // checking with the remote_id didn't work, so just in case and
675
            // to provide backwards support, check with the id
676
            $params = array(
677
                'meetingId' => $meetingData['id'],
678
                //  -- REQUIRED - The unique id for the meeting
679
                'password' => $this->getModMeetingPassword()
680
                //  -- REQUIRED - The moderator password for the meeting
681
            );
682
            $meetingIsRunningInfo = $this->getMeetingInfo($params);
683
            if ($this->debug) {
684
                error_log('Searching meetingId with params:');
685
                error_log(print_r($params, 1));
686
                error_log('Result:');
687
                error_log(print_r($meetingIsRunningInfo, 1));
688
            }
689
        }
690
691
        if (strval($meetingIsRunningInfo['returncode']) === 'SUCCESS' &&
692
            isset($meetingIsRunningInfo['meetingName']) &&
693
            !empty($meetingIsRunningInfo['meetingName'])
694
        ) {
695
            $meetingInfoExists = true;
696
        }
697
698
        if ($this->debug) {
699
            error_log(
700
                "meeting is running: ".intval($meetingInfoExists)
701
            );
702
        }
703
704
        $url = false;
705
        if ($meetingInfoExists) {
706
            $joinParams = [
707
                'meetingId' => $meetingData['remote_id'],
708
                //	-- REQUIRED - A unique id for the meeting
709
                'username' => $this->userCompleteName,
710
                //-- REQUIRED - The name that will display for the user in the meeting
711
                'password' => $pass,
712
                //-- REQUIRED - The attendee or moderator password, depending on what's passed here
713
                //'createTime' => api_get_utc_datetime(),			//-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
714
                'userID' => api_get_user_id(),
715
                //-- OPTIONAL - string
716
                'webVoiceConf' => '',
717
            ];
718
            $url = $this->api->getJoinMeetingURL($joinParams);
719
            $url = $this->protocol.$url;
720
        }
721
722
        if ($this->debug) {
723
            error_log("return url :".$url);
0 ignored issues
show
Bug introduced by
Are you sure $url of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

723
            error_log("return url :"./** @scrutinizer ignore-type */ $url);
Loading history...
724
        }
725
726
        return $url;
727
    }
728
729
    /**
730
     * Checks whether a user is teacher in the current course
731
     * @return bool True if the user can be considered a teacher in this course, false otherwise
732
     */
733
    public function isConferenceManager()
734
    {
735
        if (api_is_coach() || api_is_platform_admin(false, true)) {
736
            return true;
737
        }
738
739
        if ($this->isGlobalConferencePerUserEnabled()) {
740
            $currentUserId = api_get_user_id();
741
            if ($this->userId === $currentUserId) {
742
                return true;
743
            } else {
744
                return false;
745
            }
746
        }
747
748
        $courseInfo = api_get_course_info();
749
        $groupId = api_get_group_id();
750
        if (!empty($groupId) && !empty($courseInfo)) {
751
            $groupEnabled = api_get_course_plugin_setting('bbb', 'bbb_enable_conference_in_groups') === '1';
752
            if ($groupEnabled) {
753
                $studentCanStartConference = api_get_course_plugin_setting(
754
                        'bbb',
755
                        'big_blue_button_students_start_conference_in_groups'
756
                    ) === '1';
757
758
                if ($studentCanStartConference) {
759
                    $isSubscribed = GroupManager::is_user_in_group(
760
                        api_get_user_id(),
761
                        GroupManager::get_group_properties($groupId)
762
                    );
763
                    if ($isSubscribed) {
764
                        return true;
765
                    }
766
                }
767
            }
768
        }
769
770
        if (!empty($courseInfo)) {
771
            return api_is_course_admin();
772
        }
773
774
        return false;
775
    }
776
777
    /**
778
     * Get information about the given meeting
779
     *
780
     * @param array ...?
781
     *
782
     * @return mixed Array of information on success, false on error
783
     * @assert (array()) === false
784
     */
785
    public function getMeetingInfo($params)
786
    {
787
        try {
788
            $result = $this->api->getMeetingInfoWithXmlResponseArray($params);
789
            if ($result == null) {
790
                if ($this->debug) {
791
                    error_log("Failed to get any response. Maybe we can't contact the BBB server.");
792
                }
793
            }
794
795
            return $result;
796
        } catch (Exception $e) {
797
            if ($this->debug) {
798
                error_log('Caught exception: ', $e->getMessage(), "\n");
799
            }
800
        }
801
802
        return false;
803
    }
804
805
806
    /**
807
     * @param int $meetingId
808
     * @param int $userId
809
     *
810
     * @return array
811
     */
812
    public function getMeetingParticipantInfo($meetingId, $userId)
813
    {
814
        $meetingData = Database::select(
815
            '*',
816
            'plugin_bbb_room',
817
            array('where' => array('meeting_id = ? AND participant_id = ?' => [$meetingId, $userId])),
818
            'first'
819
        );
820
821
        if ($meetingData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $meetingData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
822
            return $meetingData;
823
        }
824
825
        return [];
826
    }
827
828
    /**
829
     * Save a participant in a meeting room
830
     *
831
     * @param int $meetingId
832
     * @param int $participantId
833
     *
834
     * @return false|int The last inserted ID. Otherwise return false
835
     */
836
    public function saveParticipant($meetingId, $participantId)
837
    {
838
        $meetingData = Database::select(
839
            '*',
840
            'plugin_bbb_room',
841
            [
842
                'where' => [
843
                    'meeting_id = ? AND participant_id = ? AND close = ?' => [
844
                        $meetingId,
845
                        $participantId,
846
                        BBBPlugin::ROOM_OPEN,
847
                    ],
848
                ],
849
            ]
850
        );
851
852
        foreach ($meetingData as $roomItem) {
853
            $inAt = $roomItem['in_at'];
854
            $outAt = $roomItem['out_at'];
855
            $roomId = $roomItem['id'];
856
            if (!empty($roomId)) {
857
                if ($inAt != $outAt) {
858
                    Database::update(
859
                        'plugin_bbb_room',
860
                        ['close' => BBBPlugin::ROOM_CLOSE],
861
                        ['id = ? ' => $roomId]
862
                    );
863
                } else {
864
                    Database::update(
865
                        'plugin_bbb_room',
866
                        ['out_at' => api_get_utc_datetime(), 'close' => BBBPlugin::ROOM_CLOSE],
867
                        ['id = ? ' => $roomId]
868
                    );
869
                }
870
            }
871
        }
872
873
        $params = [
874
            'meeting_id' => $meetingId,
875
            'participant_id' => $participantId,
876
            'in_at' => api_get_utc_datetime(),
877
            'out_at' => api_get_utc_datetime(),
878
            'close' => BBBPlugin::ROOM_OPEN,
879
        ];
880
881
        return Database::insert(
882
            'plugin_bbb_room',
883
            $params
884
        );
885
    }
886
887
    /**
888
     * Tells whether the given meeting exists and is running
889
     * (using course code as name)
890
     *
891
     * @param string $meetingName Meeting name (usually the course code)
892
     *
893
     * @return bool True if meeting exists, false otherwise
894
     * @assert ('') === false
895
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
896
     */
897
    public function meetingExists($meetingName)
898
    {
899
        $meetingData = $this->getMeetingByName($meetingName);
900
901
        return !empty($meetingData);
902
    }
903
904
    /**
905
     * @param string $meetingName
906
     *
907
     * @return array
908
     */
909
    public function getMeetingByName($meetingName)
910
    {
911
        if (empty($meetingName)) {
912
            return [];
913
        }
914
915
        $courseId = api_get_course_int_id();
916
        $sessionId = api_get_session_id();
917
        $conditions = array(
918
            'where' => array(
919
                'c_id = ? AND session_id = ? AND meeting_name = ? AND status = 1' =>
920
                 array($courseId, $sessionId, $meetingName),
921
        ));
922
923
        if ($this->hasGroupSupport()) {
924
            $groupId = api_get_group_id();
925
            $conditions = array(
926
                'where' => array(
927
                    'c_id = ? AND session_id = ? AND meeting_name = ? AND group_id = ? AND status = 1 AND access_url = ?' =>
928
                        array(
929
                            $courseId,
930
                            $sessionId,
931
                            $meetingName,
932
                            $groupId,
933
                            $this->accessUrl,
934
                        ),
935
                ),
936
            );
937
        }
938
939
        $meetingData = Database::select(
940
            '*',
941
            $this->table,
942
            $conditions,
943
            'first'
944
        );
945
946
        if ($this->debug) {
947
            error_log('meeting_exists '.print_r($meetingData, 1));
0 ignored issues
show
Bug introduced by
Are you sure print_r($meetingData, 1) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

947
            error_log('meeting_exists './** @scrutinizer ignore-type */ print_r($meetingData, 1));
Loading history...
948
        }
949
950
        return $meetingData;
951
    }
952
953
    /**
954
     * Gets a list from the database of all meetings attached to a course with the given status
955
     * @param int $courseId
956
     * @param int $sessionId
957
     * @param int $status 0 for closed meetings, 1 for open meetings
958
     *
959
     * @return array
960
     */
961
    public function getAllMeetingsInCourse($courseId, $sessionId, $status)
962
    {
963
        $conditions = array(
964
            'where' => array(
965
                'status = ? AND c_id = ? AND session_id = ? ' => array(
966
                    $status,
967
                    $courseId,
968
                    $sessionId,
969
                ),
970
            ),
971
        );
972
973
        return Database::select(
974
            '*',
975
            $this->table,
976
            $conditions
977
        );
978
    }
979
980
    /**
981
     * Gets all the course meetings saved in the plugin_bbb_meeting table and
982
     * generate actionable links (join/close/delete/etc)
983
     *
984
     * @param int   $courseId
985
     * @param int   $sessionId
986
     * @param int   $groupId
987
     * @param bool  $isAdminReport Optional. Set to true then the report is for admins
988
     * @param array $dateRange     Optional
989
     * @param int   $start         Optional
990
     * @param int   $limit         Optional
991
     *
992
     * @return array Array of current open meeting rooms
993
     * @throws Exception
994
     */
995
    public function getMeetings(
996
        $courseId = 0,
997
        $sessionId = 0,
998
        $groupId = 0,
999
        $isAdminReport = false,
1000
        $dateRange = [],
1001
        $start = 0,
1002
        $limit = 0,
1003
        $order = "ASC"
1004
    ) {
1005
        $em = Database::getManager();
1006
        $manager = $this->isConferenceManager();
1007
1008
        $conditions = [];
1009
        if ($courseId || $sessionId || $groupId) {
1010
            $conditions = array(
1011
                'where' => array(
1012
                    'c_id = ? AND session_id = ? ' => array($courseId, $sessionId),
1013
                ),
1014
            );
1015
1016
            if ($this->hasGroupSupport()) {
1017
                $conditions = array(
1018
                    'where' => array(
1019
                        'c_id = ? AND session_id = ? AND group_id = ? ' => array(
1020
                            $courseId,
1021
                            $sessionId,
1022
                            $groupId,
1023
                        ),
1024
                    ),
1025
                );
1026
            }
1027
1028
            if ($this->isGlobalConferencePerUserEnabled()) {
1029
                $conditions = array(
1030
                    'where' => array(
1031
                        'c_id = ? AND session_id = ? AND user_id = ?' => array(
1032
                            $courseId,
1033
                            $sessionId,
1034
                            $this->userId,
1035
                        ),
1036
                    ),
1037
                );
1038
            }
1039
	}
1040
        if ($this->isGlobalConference()) {
1041
            $conditions = array(
1042
                'where' => array(
1043
                    'c_id = ? AND user_id = ?' => array(
1044
                        0,
1045
                        $this->userId,
1046
                     ),
1047
                 ),
1048
            );
1049
        }
1050
1051
        if (!empty($dateRange)) {
1052
            $dateStart = date_create($dateRange['search_meeting_start']);
1053
            $dateStart = date_format($dateStart, 'Y-m-d H:i:s');
1054
            $dateEnd = date_create($dateRange['search_meeting_end']);
1055
            $dateEnd = $dateEnd->add(new DateInterval('P1D'));
1056
            $dateEnd = date_format($dateEnd, 'Y-m-d H:i:s');
1057
1058
            $conditions = array(
1059
                'where' => array(
1060
                    'created_at BETWEEN ? AND ? ' => array($dateStart, $dateEnd),
1061
                ),
1062
            );
1063
        }
1064
1065
        $conditions['order'] = 'created_at ' . $order;
1066
1067
        if ($limit) {
1068
            $conditions['limit'] = "$start , $limit";
1069
        }
1070
1071
        $meetingList = Database::select(
1072
            '*',
1073
            $this->table,
1074
            $conditions
1075
        );
1076
        $isGlobal = $this->isGlobalConference();
1077
        $newMeetingList = array();
1078
        foreach ($meetingList as $meetingDB) {
1079
            $item = array();
1080
            $item['metting_name'] = $meetingDB['meeting_name'];
1081
            $courseId = $meetingDB['c_id'];
1082
            $courseInfo = api_get_course_info_by_id($courseId);
1083
            $courseCode = '';
1084
            if (!empty($courseInfo)) {
1085
                $courseCode = $courseInfo['code'];
1086
            }
1087
1088
            if ($manager) {
1089
                $pass = $meetingDB['moderator_pw'];
1090
            } else {
1091
                $pass = $meetingDB['attendee_pw'];
1092
            }
1093
1094
            $meetingBBB = $this->getMeetingInfo(
1095
                [
1096
                    'meetingId' => $meetingDB['remote_id'],
1097
                    'password' => $pass,
1098
                ]
1099
            );
1100
1101
            if ($meetingBBB === false) {
1102
                // Checking with the remote_id didn't work, so just in case and
1103
                // to provide backwards support, check with the id
1104
                $params = array(
1105
                    'meetingId' => $meetingDB['id'],
1106
                    //  -- REQUIRED - The unique id for the meeting
1107
                    'password' => $pass
1108
                    //  -- REQUIRED - The moderator password for the meeting
1109
                );
1110
                $meetingBBB = $this->getMeetingInfo($params);
1111
            }
1112
1113
            if ($meetingDB['visibility'] == 0 && $this->isConferenceManager() === false) {
1114
                continue;
1115
            }
1116
1117
            $meetingBBB['end_url'] = $this->endUrl($meetingDB);
1118
1119
            if (isset($meetingBBB['returncode']) && (string) $meetingBBB['returncode'] === 'FAILED') {
1120
                if ($meetingDB['status'] == 1 && $this->isConferenceManager()) {
1121
                    $this->endMeeting($meetingDB['id'], $courseCode);
1122
                }
1123
            } else {
1124
                $meetingBBB['add_to_calendar_url'] = $this->addToCalendarUrl($meetingDB);
1125
            }
1126
1127
            if ($meetingDB['record'] == 1) {
1128
                // backwards compatibility (when there was no remote ID)
1129
                $mId = $meetingDB['remote_id'];
1130
                if (empty($mId)) {
1131
                    $mId = $meetingDB['id'];
1132
                }
1133
                if (empty($mId)) {
1134
                    // if the id is still empty (should *never* occur as 'id' is
1135
                    // the table's primary key), skip this conference
1136
                    continue;
1137
                }
1138
1139
                $record = [];
1140
                $recordingParams = ['meetingId' => $mId];
1141
                $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
1142
1143
                if (!empty($records)) {
1144
                    if (!isset($records['messageKey']) || $records['messageKey'] !== 'noRecordings') {
1145
                        $record = end($records);
1146
                        if (!is_array($record) || !isset($record['recordId'])) {
1147
                            continue;
1148
                        }
1149
1150
                        if (!empty($record['playbackFormat'])) {
1151
                            $this->updateMeetingVideoUrl($meetingDB['id'], $record['playbackFormatUrl']);
1152
                        }
1153
                    }
1154
                }
1155
1156
                if (isset($record['playbackFormat']) && !empty($record['playbackFormat'])) {
1157
                    $recordLink = [];
1158
                    foreach ($record['playbackFormat'] as $format) {
1159
                        $this->insertMeetingFormat(intval($meetingDB['id']), $format->type->__toString(), $format->url->__toString());
1160
                        $recordLink['record'][] = 1;
1161
                        $recordLink[] = Display::url(
1162
                            $this->plugin->get_lang($format->type->__toString()),
1163
                            $format->url->__toString(),
1164
                            ['target' => '_blank', 'class' => 'btn btn-default']
1165
                        );
1166
                    }
1167
                } else {
1168
                    $recordLink = $this->plugin->get_lang('NoRecording');
1169
                }
1170
1171
                if ($isAdminReport) {
1172
                    $this->forceCIdReq(
1173
                        $courseInfo['code'],
1174
                        $meetingDB['session_id'],
1175
                        $meetingDB['group_id']
1176
                    );
1177
                }
1178
1179
                $actionLinks = $this->getActionLinks(
1180
                    $meetingDB,
1181
                    $record,
1182
                    $isGlobal,
1183
                    $isAdminReport
1184
                );
1185
                $item['show_links'] = $recordLink;
1186
                $item['record'] = true;
1187
            } else {
1188
                $actionLinks = $this->getActionLinks(
1189
                    $meetingDB,
1190
                    [],
1191
                    $isGlobal,
1192
                    $isAdminReport
1193
                );
1194
1195
                $item['show_links'] = $this->plugin->get_lang('NoRecording');
1196
                $item['record'] = false;
1197
            }
1198
1199
            $item['action_links'] = implode(PHP_EOL, $actionLinks);
1200
            $item['created_at'] = api_convert_and_format_date($meetingDB['created_at']);
1201
            // created_at
1202
            $meetingDB['created_at'] = $item['created_at']; //avoid overwrite in array_merge() below
1203
1204
            $item['closed_at'] = '';
1205
            if (!empty($meetingDB['closed_at'])) {
1206
                $item['closed_at'] = api_convert_and_format_date($meetingDB['closed_at']);
1207
                $meetingDB['closed_at'] = $item['closed_at'];
1208
            }
1209
1210
            $item['publish_url'] = $this->publishUrl($meetingDB);
1211
            $item['unpublish_url'] = $this->unPublishUrl($meetingBBB);
1212
1213
            if ($meetingDB['status'] == 1) {
1214
                $joinParams = [
1215
                    'meetingId' => $meetingDB['remote_id'],
1216
                    //-- REQUIRED - A unique id for the meeting
1217
                    'username' => $this->userCompleteName,
1218
                    //-- REQUIRED - The name that will display for the user in the meeting
1219
                    'password' => $pass,
1220
                    //-- REQUIRED - The attendee or moderator password, depending on what's passed here
1221
                    'createTime' => '',
1222
                    //-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
1223
                    'userID' => '',
1224
                    //	-- OPTIONAL - string
1225
                    'webVoiceConf' => '',
1226
                ];
1227
                $item['go_url'] = $this->protocol.$this->api->getJoinMeetingURL($joinParams);
1228
            }
1229
            $item = array_merge($item, $meetingDB, $meetingBBB);
1230
1231
            $item['course'] = $em->find('ChamiloCoreBundle:Course', $item['c_id']);
1232
            $item['session'] = $em->find('ChamiloCoreBundle:Session', $item['session_id']);
1233
            $newMeetingList[] = $item;
1234
        }
1235
1236
        return $newMeetingList;
1237
    }
1238
1239
    /**
1240
     * Counts all the course meetings saved in the plugin_bbb_meeting table.
1241
     *
1242
     * @param int   $courseId
1243
     * @param int   $sessionId
1244
     * @param int   $groupId
1245
     * @param array $dateRange
1246
     *
1247
     * @return int Count of meetings
1248
     * @throws Exception
1249
     */
1250
    public function getCountMeetings(
1251
        $courseId = 0,
1252
        $sessionId = 0,
1253
        $groupId = 0,
1254
        $dateRange = []
1255
    ) {
1256
        $conditions = [];
1257
        if ($courseId || $sessionId || $groupId) {
1258
            $conditions = array(
1259
                'where' => array(
1260
                    'c_id = ? AND session_id = ? ' => array($courseId, $sessionId),
1261
                ),
1262
            );
1263
1264
            if ($this->hasGroupSupport()) {
1265
                $conditions = array(
1266
                    'where' => array(
1267
                        'c_id = ? AND session_id = ? AND group_id = ? ' => array(
1268
                            $courseId,
1269
                            $sessionId,
1270
                            $groupId,
1271
                        ),
1272
                    ),
1273
                );
1274
            }
1275
1276
            if ($this->isGlobalConferencePerUserEnabled()) {
1277
                $conditions = array(
1278
                    'where' => array(
1279
                        'c_id = ? AND session_id = ? AND user_id = ?' => array(
1280
                            $courseId,
1281
                            $sessionId,
1282
                            $this->userId,
1283
                        ),
1284
                    ),
1285
                );
1286
            }
1287
        }
1288
1289
        if (!empty($dateRange)) {
1290
            $dateStart = date_create($dateRange['search_meeting_start']);
1291
            $dateStart = date_format($dateStart, 'Y-m-d H:i:s');
1292
            $dateEnd = date_create($dateRange['search_meeting_end']);
1293
            $dateEnd = $dateEnd->add(new DateInterval('P1D'));
1294
            $dateEnd = date_format($dateEnd, 'Y-m-d H:i:s');
1295
1296
            $conditions = array(
1297
                'where' => array(
1298
                    'created_at BETWEEN ? AND ? ' => array($dateStart, $dateEnd),
1299
                ),
1300
            );
1301
        }
1302
1303
        $row = Database::select(
1304
            'count(*) as count',
1305
            $this->table,
1306
            $conditions,
1307
            'first'
1308
        );
1309
1310
        return $row['count'];
1311
    }
1312
1313
    /**
1314
     * @param array $meeting
1315
     *
1316
     * @return string
1317
     */
1318
    public function endUrl($meeting)
1319
    {
1320
        if (!isset($meeting['id'])) {
1321
            return '';
1322
        }
1323
1324
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().'&action=end&id='.$meeting['id'];
1325
    }
1326
1327
    /**
1328
     * Closes a meeting (usually when the user click on the close button from
1329
     * the conferences listing.
1330
     *
1331
     * @param string The internal ID of the meeting (id field for this meeting)
1332
     * @param string $courseCode
1333
     *
1334
     * @return void
1335
     * @assert (0) === false
1336
     */
1337
    public function endMeeting($id, $courseCode = null)
1338
    {
1339
        if (empty($id)) {
1340
            return false;
1341
        }
1342
1343
        $meetingData = Database::select(
1344
            '*',
1345
            $this->table,
1346
            array('where' => array('id = ?' => array($id))),
1347
            'first'
1348
        );
1349
        $manager = $this->isConferenceManager();
1350
        if ($manager) {
1351
            $pass = $meetingData['moderator_pw'];
1352
        } else {
1353
            $pass = $meetingData['attendee_pw'];
1354
        }
1355
1356
        Event::addEvent(
1357
            'bbb_end_meeting',
1358
            'meeting_id',
1359
            (int) $id,
1360
            null,
1361
            api_get_user_id(),
1362
            api_get_course_int_id(),
1363
            api_get_session_id()
1364
        );
1365
1366
        $endParams = array(
1367
            'meetingId' => $meetingData['remote_id'], // REQUIRED - We have to know which meeting to end.
1368
            'password' => $pass, // REQUIRED - Must match moderator pass for meeting.
1369
        );
1370
        $this->api->endMeetingWithXmlResponseArray($endParams);
1371
        Database::update(
1372
            $this->table,
1373
            array('status' => 0, 'closed_at' => api_get_utc_datetime()),
1374
            array('id = ? ' => $id)
1375
        );
1376
1377
        // Update users with in_at y ou_at field equal
1378
        $roomTable = Database::get_main_table('plugin_bbb_room');
1379
        $conditions['where'] = ['meeting_id=? AND in_at=out_at AND close=?' => [$id, BBBPlugin::ROOM_OPEN]];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$conditions was never initialized. Although not strictly required by PHP, it is generally a good practice to add $conditions = array(); before regardless.
Loading history...
1380
        $roomList = Database::select(
1381
            '*',
1382
            $roomTable,
1383
            $conditions
1384
        );
1385
1386
        foreach ($roomList as $roomDB) {
1387
            $roomId = $roomDB['id'];
1388
            if (!empty($roomId)) {
1389
                Database::update(
1390
                    $roomTable,
1391
                    ['out_at' => api_get_utc_datetime(), 'close' => BBBPlugin::ROOM_CLOSE],
1392
                    ['id = ? ' => $roomId]
1393
                );
1394
            }
1395
        }
1396
1397
        // Close all meeting rooms with meeting ID
1398
        Database::update(
1399
            $roomTable,
1400
            ['close' => BBBPlugin::ROOM_CLOSE],
1401
            ['meeting_id = ? ' => $id]
1402
        );
1403
    }
1404
1405
    /**
1406
     * @param array $meeting
1407
     * @param array $record
1408
     *
1409
     * @return string
1410
     */
1411
    public function addToCalendarUrl($meeting, $record = [])
1412
    {
1413
        $url = isset($record['playbackFormatUrl']) ? $record['playbackFormatUrl'] : '';
1414
1415
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1416
            ).'&action=add_to_calendar&id='.$meeting['id'].'&start='.api_strtotime($meeting['created_at']).'&url='.$url;
1417
    }
1418
1419
    /**
1420
     * @param int    $meetingId
1421
     * @param string $videoUrl
1422
     *
1423
     * @return bool|int
1424
     */
1425
    public function updateMeetingVideoUrl($meetingId, $videoUrl)
1426
    {
1427
        return Database::update(
1428
            'plugin_bbb_meeting',
1429
            ['video_url' => $videoUrl],
1430
            ['id = ?' => intval($meetingId)]
1431
        );
1432
    }
1433
1434
    /**
1435
     * @param int $meetingId
1436
     * @param string $formatType
1437
     * @param string $resourceUrl
1438
     *
1439
     * @return bool|int
1440
     */
1441
    public function insertMeetingFormat(int $meetingId, string $formatType, string $resourceUrl)
1442
    {
1443
        $em = Database::getManager();
1444
        $sm = $em->getConnection()->getSchemaManager();
1445
        if ($sm->tablesExist('plugin_bbb_meeting_format')) {
1446
            return Database::insert(
1447
                'plugin_bbb_meeting_format',
1448
                [
1449
                    'format_type' => $formatType,
1450
                    'resource_url' => $resourceUrl,
1451
                    'meeting_id' => $meetingId
1452
                ]
1453
            );
1454
        }
1455
1456
    }
1457
1458
    /**
1459
     * Force the course, session and/or group IDs
1460
     *
1461
     * @param string $courseCode
1462
     * @param int    $sessionId
1463
     * @param int    $groupId
1464
     */
1465
    public function forceCIdReq($courseCode, $sessionId = 0, $groupId = 0)
1466
    {
1467
        $this->courseCode = $courseCode;
1468
        $this->sessionId = (int) $sessionId;
1469
        $this->groupId = (int) $groupId;
1470
    }
1471
1472
    /**
1473
     * @param array $meetingInfo
1474
     * @param array $recordInfo
1475
     * @param bool  $isGlobal
1476
     * @param bool  $isAdminReport
1477
     *
1478
     * @return array
1479
     */
1480
    private function getActionLinks(
1481
        $meetingInfo,
1482
        $recordInfo,
1483
        $isGlobal = false,
1484
        $isAdminReport = false
1485
    ) {
1486
        $isVisible = $meetingInfo['visibility'] != 0;
1487
        $linkVisibility = $isVisible
1488
            ? Display::url(
1489
                Display::return_icon('visible.png', get_lang('MakeInvisible')),
1490
                $this->unPublishUrl($meetingInfo)
1491
            )
1492
            : Display::url(
1493
                Display::return_icon('invisible.png', get_lang('MakeVisible')),
1494
                $this->publishUrl($meetingInfo)
1495
            );
1496
1497
        $links = [];
1498
        if ($this->plugin->get('allow_regenerate_recording') === 'true' && $meetingInfo['record'] == 1) {
1499
            if (!empty($recordInfo)) {
1500
                $links[] = Display::url(
1501
                    Display::return_icon('reload.png', get_lang('RegenerateRecord')),
1502
                    $this->regenerateRecordUrl($meetingInfo, $recordInfo)
1503
                );
1504
            } else {
1505
                $links[] = Display::url(
1506
                    Display::return_icon('reload.png', get_lang('RegenerateRecord')),
1507
                    $this->regenerateRecordUrlFromMeeting($meetingInfo)
1508
                );
1509
            }
1510
        }
1511
1512
        if (empty($recordInfo)) {
1513
            if (!$isAdminReport) {
1514
                if ($meetingInfo['status'] == 0) {
1515
                    $links[] = Display::url(
1516
                        Display::return_icon('delete.png', get_lang('Delete')),
1517
                        $this->deleteRecordUrl($meetingInfo)
1518
                    );
1519
                    $links[] = $linkVisibility;
1520
                }
1521
1522
                return $links;
1523
            } else {
1524
                $links[] = Display::url(
1525
                    Display::return_icon('course_home.png', get_lang('GoToCourse')),
1526
                    $this->getListingUrl($meetingInfo['c_id'], $meetingInfo['session_id'], $meetingInfo['group_id'])
1527
                );
1528
1529
                return $links;
1530
            }
1531
        }
1532
1533
        if (!$isGlobal) {
1534
            $links[] = Display::url(
1535
                Display::return_icon('link.gif', get_lang('UrlMeetingToShare')),
1536
                $this->copyToRecordToLinkTool($meetingInfo)
1537
            );
1538
            $links[] = Display::url(
1539
                Display::return_icon('agenda.png', get_lang('AddToCalendar')),
1540
                $this->addToCalendarUrl($meetingInfo, $recordInfo)
1541
            );
1542
        }
1543
1544
        $hide = $this->plugin->get('disable_download_conference_link') === 'true' ? true : false;
1545
1546
        if ($hide == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1547
            if ($meetingInfo['has_video_m4v']) {
1548
                $links[] = Display::url(
1549
                    Display::return_icon('save.png', get_lang('DownloadFile')),
1550
                    $recordInfo['playbackFormatUrl'].'/capture.m4v',
1551
                    ['target' => '_blank']
1552
                );
1553
            } else {
1554
                $links[] = Display::url(
1555
                    Display::return_icon('save.png', get_lang('DownloadFile')),
1556
                    '#',
1557
                    [
1558
                        'id' => "btn-check-meeting-video-{$meetingInfo['id']}",
1559
                        'class' => 'check-meeting-video',
1560
                        'data-id' => $meetingInfo['id'],
1561
                    ]
1562
                );
1563
            }
1564
        }
1565
1566
1567
        if (!$isAdminReport) {
1568
            $links[] = Display::url(
1569
                Display::return_icon('delete.png', get_lang('Delete')),
1570
                $this->deleteRecordUrl($meetingInfo)
1571
            );
1572
            $links[] = $linkVisibility;
1573
        } else {
1574
            $links[] = Display::url(
1575
                Display::return_icon('course_home.png', get_lang('GoToCourse')),
1576
                $this->getListingUrl($meetingInfo['c_id'], $meetingInfo['session_id'], $meetingInfo['group_id'])
1577
            );
1578
        }
1579
1580
1581
        return $links;
1582
    }
1583
1584
    /**
1585
     * @param array $meeting
1586
     *
1587
     * @return string
1588
     */
1589
    public function unPublishUrl($meeting)
1590
    {
1591
        if (!isset($meeting['id'])) {
1592
            return null;
1593
        }
1594
1595
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1596
            ).'&action=unpublish&id='.$meeting['id'];
1597
    }
1598
1599
    /**
1600
     * @param array $meeting
1601
     *
1602
     * @return string
1603
     */
1604
    public function publishUrl($meeting)
1605
    {
1606
        if (!isset($meeting['id'])) {
1607
            return '';
1608
        }
1609
1610
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1611
            ).'&action=publish&id='.$meeting['id'];
1612
    }
1613
1614
    /**
1615
     * @param array $meeting
1616
     * @param array $recordInfo
1617
     *
1618
     * @return string
1619
     */
1620
    public function regenerateRecordUrl($meeting, $recordInfo)
1621
    {
1622
        if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
1623
            return '';
1624
        }
1625
1626
        if (!isset($meeting['id'])) {
1627
            return '';
1628
        }
1629
1630
        if (empty($recordInfo) || (!empty($recordInfo['recordId']) && !isset($recordInfo['recordId']))) {
1631
            return '';
1632
        }
1633
1634
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().
1635
            '&action=regenerate_record&id='.$meeting['id'].'&record_id='.$recordInfo['recordId'];
1636
    }
1637
1638
    /**
1639
     * @param array $meeting
1640
     *
1641
     * @return string
1642
     */
1643
    public function regenerateRecordUrlFromMeeting($meeting)
1644
    {
1645
        if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
1646
            return '';
1647
        }
1648
1649
        if (!isset($meeting['id'])) {
1650
            return '';
1651
        }
1652
1653
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().
1654
            '&action=regenerate_record&id='.$meeting['id'];
1655
    }
1656
1657
    /**
1658
     * @param array $meeting
1659
     *
1660
     * @return string
1661
     */
1662
    public function deleteRecordUrl($meeting)
1663
    {
1664
        if (!isset($meeting['id'])) {
1665
            return '';
1666
        }
1667
1668
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1669
            ).'&action=delete_record&id='.$meeting['id'];
1670
    }
1671
1672
    /**
1673
     * @param array $meeting
1674
     *
1675
     * @return string
1676
     */
1677
    public function copyToRecordToLinkTool($meeting)
1678
    {
1679
        if (!isset($meeting['id'])) {
1680
            return '';
1681
        }
1682
1683
        return api_get_path(WEB_PLUGIN_PATH).
1684
            'bbb/listing.php?'.$this->getUrlParams().'&action=copy_record_to_link_tool&id='.$meeting['id'];
1685
    }
1686
1687
    /**
1688
     * Function disabled
1689
     */
1690
    public function publishMeeting($id)
1691
    {
1692
        //return BigBlueButtonBN::setPublishRecordings($id, 'true', $this->url, $this->salt);
1693
        if (empty($id)) {
1694
            return false;
1695
        }
1696
        $id = intval($id);
1697
        Database::update($this->table, array('visibility' => 1), array('id = ? ' => $id));
1698
1699
        return true;
1700
    }
1701
1702
    /**
1703
     * Function disabled
1704
     */
1705
    public function unpublishMeeting($id)
1706
    {
1707
        //return BigBlueButtonBN::setPublishRecordings($id, 'false', $this->url, $this->salt);
1708
        if (empty($id)) {
1709
            return false;
1710
        }
1711
        $id = intval($id);
1712
        Database::update($this->table, array('visibility' => 0), array('id = ?' => $id));
1713
1714
        return true;
1715
    }
1716
1717
    /**
1718
     * Get users online in the current course room.
1719
     *
1720
     * @return int The number of users currently connected to the videoconference
1721
     * @assert () > -1
1722
     */
1723
    public function getUsersOnlineInCurrentRoom()
1724
    {
1725
        $courseId = api_get_course_int_id();
1726
        $sessionId = api_get_session_id();
1727
1728
        $conditions = array(
1729
            'where' => array(
1730
                'c_id = ? AND session_id = ? AND status = 1 AND access_url = ?' => array(
1731
                    $courseId,
1732
                    $sessionId,
1733
                    $this->accessUrl,
1734
                ),
1735
            ),
1736
        );
1737
1738
        if ($this->hasGroupSupport()) {
1739
            $groupId = api_get_group_id();
1740
            $conditions = array(
1741
                'where' => array(
1742
                    'c_id = ? AND session_id = ? AND group_id = ? AND status = 1 AND access_url = ?' => array(
1743
                        $courseId,
1744
                        $sessionId,
1745
                        $groupId,
1746
                        $this->accessUrl,
1747
                    ),
1748
                ),
1749
            );
1750
        }
1751
1752
        if ($this->isGlobalConferencePerUserEnabled()) {
1753
            $conditions = array(
1754
                'where' => array(
1755
                    'user_id = ? AND status = 1 AND access_url = ?' => array(
1756
                        $this->userId,
1757
                        $this->accessUrl,
1758
                    ),
1759
                ),
1760
            );
1761
        }
1762
1763
        $meetingData = Database::select(
1764
            '*',
1765
            $this->table,
1766
            $conditions,
1767
            'first'
1768
        );
1769
1770
        if (empty($meetingData)) {
1771
            return 0;
1772
        }
1773
        $pass = $meetingData['moderator_pw'];
1774
        $info = $this->getMeetingInfo(array('meetingId' => $meetingData['remote_id'], 'password' => $pass));
1775
        if ($info === false) {
1776
            //checking with the remote_id didn't work, so just in case and
1777
            // to provide backwards support, check with the id
1778
            $params = array(
1779
                'meetingId' => $meetingData['id'],
1780
                //  -- REQUIRED - The unique id for the meeting
1781
                'password' => $pass
1782
                //  -- REQUIRED - The moderator password for the meeting
1783
            );
1784
            $info = $this->getMeetingInfo($params);
1785
        }
1786
1787
        if (!empty($info) && isset($info['participantCount'])) {
1788
            return $info['participantCount'];
1789
        }
1790
1791
        return 0;
1792
    }
1793
1794
    /**
1795
     * @param int    $id
1796
     * @param string $recordId
1797
     *
1798
     * @return bool
1799
     */
1800
    public function regenerateRecording($id, $recordId = '')
1801
    {
1802
        if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
1803
            return false;
1804
        }
1805
1806
        if (empty($id)) {
1807
            return false;
1808
        }
1809
1810
        $meetingData = Database::select(
1811
            '*',
1812
            $this->table,
1813
            array('where' => array('id = ?' => array($id))),
1814
            'first'
1815
        );
1816
1817
        Event::addEvent(
1818
            'bbb_regenerate_record',
1819
            'record_id',
1820
            (int) $recordId,
1821
            null,
1822
            api_get_user_id(),
1823
            api_get_course_int_id(),
1824
            api_get_session_id()
1825
        );
1826
1827
        // Check if there are recordings for this meeting
1828
        $recordings = $this->api->getRecordings(['meetingId' => $meetingData['remote_id']]);
1829
        if (!empty($recordings) && isset($recordings['messageKey']) && $recordings['messageKey'] === 'noRecordings') {
1830
            // Regenerate the meeting id
1831
            if (!empty($meetingData['internal_meeting_id'])) {
1832
                return $this->api->generateRecording(['recordId' => $meetingData['internal_meeting_id']]);
1833
            }
1834
1835
            /*$pass = $this->getModMeetingPassword();
1836
            $info = $this->getMeetingInfo(['meetingId' => $meetingData['remote_id'], 'password' => $pass]);
1837
            if (!empty($info) && isset($info['internalMeetingID'])) {
1838
                return $this->api->generateRecording(['recordId' => $meetingData['internal_meeting_id']]);
1839
            }*/
1840
1841
            return false;
1842
        } else {
1843
            if (!empty($recordings['records'])) {
1844
                $recordExists = false;
1845
                foreach ($recordings['records'] as $record) {
1846
                    if ($recordId == $record['recordId']) {
1847
                        $recordExists = true;
1848
                        break;
1849
                    }
1850
                }
1851
1852
                if ($recordExists) {
1853
                    return $this->api->generateRecording(['recordId' => $recordId]);
1854
                }
1855
            }
1856
        }
1857
1858
        return false;
1859
    }
1860
1861
    /**
1862
     * Deletes a recording of a meeting
1863
     *
1864
     * @param int $id ID of the recording
1865
     *
1866
     * @return bool
1867
     *
1868
     * @assert () === false
1869
     * @todo Also delete links and agenda items created from this recording
1870
     */
1871
    public function deleteRecording($id)
1872
    {
1873
        if (empty($id)) {
1874
            return false;
1875
        }
1876
1877
        $meetingData = Database::select(
1878
            '*',
1879
            $this->table,
1880
            array('where' => array('id = ?' => array($id))),
1881
            'first'
1882
        );
1883
1884
        Event::addEvent(
1885
            'bbb_delete_record',
1886
            'meeting_id',
1887
            $id,
1888
            null,
1889
            api_get_user_id(),
1890
            api_get_course_int_id(),
1891
            api_get_session_id()
1892
        );
1893
1894
        $delete = false;
1895
        $recordings = [];
1896
        // Check if there are recordings for this meeting
1897
        if (!empty($meetingData['remote_id'])) {
1898
            Event::addEvent(
1899
                'bbb_delete_record',
1900
                'remote_id',
1901
                $meetingData['remote_id'],
1902
                null,
1903
                api_get_user_id(),
1904
                api_get_course_int_id(),
1905
                api_get_session_id()
1906
            );
1907
            $recordings = $this->api->getRecordings(['meetingId' => $meetingData['remote_id']]);
1908
        }
1909
        if (!empty($recordings) && isset($recordings['messageKey']) && $recordings['messageKey'] == 'noRecordings') {
1910
            $delete = true;
1911
        } else {
1912
            if (!empty($recordings['records'])) {
1913
                $recordsToDelete = [];
1914
                foreach ($recordings['records'] as $record) {
1915
                    $recordsToDelete[] = $record['recordId'];
1916
                }
1917
                $delete = true;
1918
                if (!empty($recordsToDelete)) {
1919
                    $recordingParams = ['recordId' => implode(',', $recordsToDelete)];
1920
                    Event::addEvent(
1921
                        'bbb_delete_record',
1922
                        'record_id_list',
1923
                        implode(',', $recordsToDelete),
1924
                        null,
1925
                        api_get_user_id(),
1926
                        api_get_course_int_id(),
1927
                        api_get_session_id()
1928
                    );
1929
                    $result = $this->api->deleteRecordingsWithXmlResponseArray($recordingParams);
1930
                    if (!empty($result) && isset($result['deleted']) && $result['deleted'] === 'true') {
1931
                        $delete = true;
1932
                    }
1933
                }
1934
            }
1935
        }
1936
1937
        if ($delete) {
1938
            Database::delete(
1939
                'plugin_bbb_room',
1940
                array('meeting_id = ?' => array($id))
1941
            );
1942
1943
            Database::delete(
1944
                $this->table,
1945
                array('id = ?' => array($id))
1946
            );
1947
        }
1948
1949
        return $delete;
1950
    }
1951
1952
    /**
1953
     * Creates a link in the links tool from the given videoconference recording
1954
     *
1955
     * @param int $id ID of the item in the plugin_bbb_meeting table
1956
     * @param string Hash identifying the recording, as provided by the API
1957
     *
1958
     * @return mixed ID of the newly created link, or false on error
1959
     * @assert (null, null) === false
1960
     * @assert (1, null) === false
1961
     * @assert (null, 'abcdefabcdefabcdefabcdef') === false
1962
     */
1963
    public function copyRecordingToLinkTool($id)
1964
    {
1965
        if (empty($id)) {
1966
            return false;
1967
        }
1968
        //$records =  BigBlueButtonBN::getRecordingsUrl($id);
1969
        $meetingData = Database::select(
1970
            '*',
1971
            $this->table,
1972
            array('where' => array('id = ?' => array($id))),
1973
            'first'
1974
        );
1975
1976
        $records = $this->api->getRecordingsWithXmlResponseArray(
1977
            array('meetingId' => $meetingData['remote_id'])
1978
        );
1979
1980
        if (!empty($records)) {
1981
            if (isset($records['message']) && !empty($records['message'])) {
1982
                if ($records['messageKey'] == 'noRecordings') {
1983
                    $recordArray[] = $this->plugin->get_lang('NoRecording');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$recordArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $recordArray = array(); before regardless.
Loading history...
1984
                } else {
1985
                    //$recordArray[] = $records['message'];
1986
                }
1987
1988
                return false;
1989
            } else {
1990
                $record = $records[0];
1991
                if (is_array($record) && isset($record['recordId'])) {
1992
                    $url = $record['playbackFormatUrl'];
1993
                    $link = new Link();
1994
                    $params['url'] = $url;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.
Loading history...
1995
                    $params['title'] = $meetingData['meeting_name'];
1996
                    $id = $link->save($params);
1997
1998
                    return $id;
1999
                }
2000
            }
2001
        }
2002
2003
        return false;
2004
    }
2005
2006
    /**
2007
     * Checks if the video conference server is running.
2008
     * Function currently disabled (always returns 1)
2009
     * @return bool True if server is running, false otherwise
2010
     * @assert () === false
2011
     */
2012
    public function isServerRunning()
2013
    {
2014
        return true;
2015
        //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url);
2016
    }
2017
2018
    /**
2019
     * Checks if the video conference plugin is properly configured
2020
     * @return bool True if plugin has a host and a salt, false otherwise
2021
     * @assert () === false
2022
     */
2023
    public function isServerConfigured()
2024
    {
2025
        $host = $this->plugin->get('host');
2026
2027
        if (empty($host)) {
2028
            return false;
2029
        }
2030
2031
        $salt = $this->plugin->get('salt');
2032
2033
        if (empty($salt)) {
2034
            return false;
2035
        }
2036
2037
        return true;
2038
        //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url);
2039
    }
2040
2041
    /**
2042
     * Get active session in the all platform
2043
     */
2044
    public function getActiveSessionsCount()
2045
    {
2046
        $meetingList = Database::select(
2047
            'count(id) as count',
2048
            $this->table,
2049
            array('where' => array('status = ? AND access_url = ?' => array(1, $this->accessUrl))),
2050
            'first'
2051
        );
2052
2053
        return $meetingList['count'];
2054
    }
2055
2056
    /**
2057
     * Get active session in the all platform
2058
     *
2059
     * @param boolean $allSites Parameter to indicate whether to get the result from all sites
2060
     *
2061
     * @return array
2062
     */
2063
    public function getActiveSessions(bool $allSites = false): array
2064
    {
2065
        $where = ['where' => ['status = ?' => 1]];
2066
2067
        if (!$allSites) {
2068
            $where['where'][' AND access_url = ?'] = $this->accessUrl;
2069
        }
2070
2071
        return Database::select(
2072
            '*',
2073
            $this->table,
2074
            $where
2075
        );
2076
    }
2077
2078
    /**
2079
     * @param string $url
2080
     */
2081
    public function redirectToBBB($url)
2082
    {
2083
        if (file_exists(__DIR__.'/../config.vm.php')) {
2084
            // Using VM
2085
            echo Display::url($this->plugin->get_lang('ClickToContinue'), $url);
2086
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
2087
        } else {
2088
            // Classic
2089
            header("Location: $url");
2090
            exit;
2091
        }
2092
    }
2093
2094
    /**
2095
     * @return string
2096
     */
2097
    public function getConferenceUrl()
2098
    {
2099
        return api_get_path(WEB_PLUGIN_PATH).'bbb/start.php?launch=1&'.$this->getUrlParams();
2100
    }
2101
2102
    /**
2103
     * Get the meeting info from DB by its name
2104
     *
2105
     * @param string $name
2106
     *
2107
     * @return array
2108
     */
2109
    public function findMeetingByName($name)
2110
    {
2111
        $meetingData = Database::select(
2112
            '*',
2113
            'plugin_bbb_meeting',
2114
            array('where' => array('meeting_name = ? AND status = 1 ' => $name)),
2115
            'first'
2116
        );
2117
2118
        return $meetingData;
2119
    }
2120
2121
    /**
2122
     * Get the meeting info from DB by its name
2123
     *
2124
     * @param int $id
2125
     *
2126
     * @return array
2127
     */
2128
    public function getMeeting($id)
2129
    {
2130
        $meetingData = Database::select(
2131
            '*',
2132
            'plugin_bbb_meeting',
2133
            array('where' => array('id = ?' => $id)),
2134
            'first'
2135
        );
2136
2137
        return $meetingData;
2138
    }
2139
2140
    /**
2141
     * Get the meeting info.
2142
     *
2143
     * @param int $id
2144
     *
2145
     * @return array
2146
     */
2147
    public function getMeetingByRemoteId($id)
2148
    {
2149
        $meetingData = Database::select(
2150
            '*',
2151
            'plugin_bbb_meeting',
2152
            array('where' => array('remote_id = ?' => $id)),
2153
            'first'
2154
        );
2155
2156
        return $meetingData;
2157
    }
2158
2159
    /**
2160
     * @param int $meetingId
2161
     *
2162
     * @return array
2163
     */
2164
    public function findConnectedMeetingParticipants($meetingId)
2165
    {
2166
        $meetingData = Database::select(
2167
            '*',
2168
            'plugin_bbb_room',
2169
            array('where' => array('meeting_id = ? AND in_at IS NOT NULL' => $meetingId))
2170
        );
2171
        $participantIds = [];
2172
        $return = [];
2173
2174
        foreach ($meetingData as $participantInfo) {
2175
            if (in_array($participantInfo['participant_id'], $participantIds)) {
2176
                continue;
2177
            }
2178
2179
            $participantIds[] = $participantInfo['participant_id'];
2180
2181
            $return[] = [
2182
                'id' => $participantInfo['id'],
2183
                'meeting_id' => $participantInfo['meeting_id'],
2184
                'participant' => api_get_user_entity($participantInfo['participant_id']),
2185
                'in_at' => $participantInfo['in_at'],
2186
                'out_at' => $participantInfo['out_at'],
2187
            ];
2188
        }
2189
2190
        return $return;
2191
    }
2192
2193
    /**
2194
     * Check if the meeting has a capture.m4v video file. If exists then the has_video_m4v field is updated
2195
     *
2196
     * @param int $meetingId
2197
     *
2198
     * @return bool
2199
     */
2200
    public function checkDirectMeetingVideoUrl($meetingId)
2201
    {
2202
        $meetingInfo = Database::select(
2203
            '*',
2204
            'plugin_bbb_meeting',
2205
            [
2206
                'where' => ['id = ?' => intval($meetingId)],
2207
            ],
2208
            'first'
2209
        );
2210
2211
        if (!isset($meetingInfo['video_url'])) {
2212
            return false;
2213
        }
2214
2215
        $hasCapture = SocialManager::verifyUrl($meetingInfo['video_url'].'/capture.m4v');
2216
2217
        if ($hasCapture) {
2218
            return Database::update(
0 ignored issues
show
Bug Best Practice introduced by
The expression return Database::update(...=> intval($meetingId))) also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
2219
                'plugin_bbb_meeting',
2220
                ['has_video_m4v' => true],
2221
                ['id = ?' => intval($meetingId)]
2222
            );
2223
        }
2224
2225
        return $hasCapture;
2226
    }
2227
}
2228