bbb::getMeetings()   F
last analyzed

Complexity

Conditions 34
Paths > 20000

Size

Total Lines 242
Code Lines 141

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 141
dl 0
loc 242
rs 0
c 0
b 0
f 0
cc 34
nc 130920
nop 8

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
                foreach ($recordInfo['playbackFormat'] as $format) {
1549
                    if ($format->type->__toString() == 'video') {
1550
                            $recordingUrl = $format->url->__toString();
1551
                    }
1552
                }
1553
                $links[] = Display::url(
1554
                    Display::return_icon('save.png', get_lang('DownloadFile')),
1555
                    $recordingUrl.'video-0.m4v',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $recordingUrl does not seem to be defined for all execution paths leading up to this point.
Loading history...
1556
                    ['target' => '_blank']
1557
                );
1558
            } else {
1559
                $links[] = Display::url(
1560
                    Display::return_icon('save.png', get_lang('DownloadFile')),
1561
                    '#',
1562
                    [
1563
                        'id' => "btn-check-meeting-video-{$meetingInfo['id']}",
1564
                        'class' => 'check-meeting-video',
1565
                        'data-id' => $meetingInfo['id'],
1566
                    ]
1567
                );
1568
            }
1569
        }
1570
1571
1572
        if (!$isAdminReport) {
1573
            $links[] = Display::url(
1574
                Display::return_icon('delete.png', get_lang('Delete')),
1575
                $this->deleteRecordUrl($meetingInfo)
1576
            );
1577
            $links[] = $linkVisibility;
1578
        } else {
1579
            $links[] = Display::url(
1580
                Display::return_icon('course_home.png', get_lang('GoToCourse')),
1581
                $this->getListingUrl($meetingInfo['c_id'], $meetingInfo['session_id'], $meetingInfo['group_id'])
1582
            );
1583
        }
1584
1585
1586
        return $links;
1587
    }
1588
1589
    /**
1590
     * @param array $meeting
1591
     *
1592
     * @return string
1593
     */
1594
    public function unPublishUrl($meeting)
1595
    {
1596
        if (!isset($meeting['id'])) {
1597
            return null;
1598
        }
1599
1600
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1601
            ).'&action=unpublish&id='.$meeting['id'];
1602
    }
1603
1604
    /**
1605
     * @param array $meeting
1606
     *
1607
     * @return string
1608
     */
1609
    public function publishUrl($meeting)
1610
    {
1611
        if (!isset($meeting['id'])) {
1612
            return '';
1613
        }
1614
1615
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1616
            ).'&action=publish&id='.$meeting['id'];
1617
    }
1618
1619
    /**
1620
     * @param array $meeting
1621
     * @param array $recordInfo
1622
     *
1623
     * @return string
1624
     */
1625
    public function regenerateRecordUrl($meeting, $recordInfo)
1626
    {
1627
        if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
1628
            return '';
1629
        }
1630
1631
        if (!isset($meeting['id'])) {
1632
            return '';
1633
        }
1634
1635
        if (empty($recordInfo) || (!empty($recordInfo['recordId']) && !isset($recordInfo['recordId']))) {
1636
            return '';
1637
        }
1638
1639
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().
1640
            '&action=regenerate_record&id='.$meeting['id'].'&record_id='.$recordInfo['recordId'];
1641
    }
1642
1643
    /**
1644
     * @param array $meeting
1645
     *
1646
     * @return string
1647
     */
1648
    public function regenerateRecordUrlFromMeeting($meeting)
1649
    {
1650
        if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
1651
            return '';
1652
        }
1653
1654
        if (!isset($meeting['id'])) {
1655
            return '';
1656
        }
1657
1658
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams().
1659
            '&action=regenerate_record&id='.$meeting['id'];
1660
    }
1661
1662
    /**
1663
     * @param array $meeting
1664
     *
1665
     * @return string
1666
     */
1667
    public function deleteRecordUrl($meeting)
1668
    {
1669
        if (!isset($meeting['id'])) {
1670
            return '';
1671
        }
1672
1673
        return api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php?'.$this->getUrlParams(
1674
            ).'&action=delete_record&id='.$meeting['id'];
1675
    }
1676
1677
    /**
1678
     * @param array $meeting
1679
     *
1680
     * @return string
1681
     */
1682
    public function copyToRecordToLinkTool($meeting)
1683
    {
1684
        if (!isset($meeting['id'])) {
1685
            return '';
1686
        }
1687
1688
        return api_get_path(WEB_PLUGIN_PATH).
1689
            'bbb/listing.php?'.$this->getUrlParams().'&action=copy_record_to_link_tool&id='.$meeting['id'];
1690
    }
1691
1692
    /**
1693
     * Function disabled
1694
     */
1695
    public function publishMeeting($id)
1696
    {
1697
        //return BigBlueButtonBN::setPublishRecordings($id, 'true', $this->url, $this->salt);
1698
        if (empty($id)) {
1699
            return false;
1700
        }
1701
        $id = intval($id);
1702
        Database::update($this->table, array('visibility' => 1), array('id = ? ' => $id));
1703
1704
        return true;
1705
    }
1706
1707
    /**
1708
     * Function disabled
1709
     */
1710
    public function unpublishMeeting($id)
1711
    {
1712
        //return BigBlueButtonBN::setPublishRecordings($id, 'false', $this->url, $this->salt);
1713
        if (empty($id)) {
1714
            return false;
1715
        }
1716
        $id = intval($id);
1717
        Database::update($this->table, array('visibility' => 0), array('id = ?' => $id));
1718
1719
        return true;
1720
    }
1721
1722
    /**
1723
     * Get users online in the current course room.
1724
     *
1725
     * @return int The number of users currently connected to the videoconference
1726
     * @assert () > -1
1727
     */
1728
    public function getUsersOnlineInCurrentRoom()
1729
    {
1730
        $courseId = api_get_course_int_id();
1731
        $sessionId = api_get_session_id();
1732
1733
        $conditions = array(
1734
            'where' => array(
1735
                'c_id = ? AND session_id = ? AND status = 1 AND access_url = ?' => array(
1736
                    $courseId,
1737
                    $sessionId,
1738
                    $this->accessUrl,
1739
                ),
1740
            ),
1741
        );
1742
1743
        if ($this->hasGroupSupport()) {
1744
            $groupId = api_get_group_id();
1745
            $conditions = array(
1746
                'where' => array(
1747
                    'c_id = ? AND session_id = ? AND group_id = ? AND status = 1 AND access_url = ?' => array(
1748
                        $courseId,
1749
                        $sessionId,
1750
                        $groupId,
1751
                        $this->accessUrl,
1752
                    ),
1753
                ),
1754
            );
1755
        }
1756
1757
        if ($this->isGlobalConferencePerUserEnabled()) {
1758
            $conditions = array(
1759
                'where' => array(
1760
                    'user_id = ? AND status = 1 AND access_url = ?' => array(
1761
                        $this->userId,
1762
                        $this->accessUrl,
1763
                    ),
1764
                ),
1765
            );
1766
        }
1767
1768
        $meetingData = Database::select(
1769
            '*',
1770
            $this->table,
1771
            $conditions,
1772
            'first'
1773
        );
1774
1775
        if (empty($meetingData)) {
1776
            return 0;
1777
        }
1778
        $pass = $meetingData['moderator_pw'];
1779
        $info = $this->getMeetingInfo(array('meetingId' => $meetingData['remote_id'], 'password' => $pass));
1780
        if ($info === false) {
1781
            //checking with the remote_id didn't work, so just in case and
1782
            // to provide backwards support, check with the id
1783
            $params = array(
1784
                'meetingId' => $meetingData['id'],
1785
                //  -- REQUIRED - The unique id for the meeting
1786
                'password' => $pass
1787
                //  -- REQUIRED - The moderator password for the meeting
1788
            );
1789
            $info = $this->getMeetingInfo($params);
1790
        }
1791
1792
        if (!empty($info) && isset($info['participantCount'])) {
1793
            return $info['participantCount'];
1794
        }
1795
1796
        return 0;
1797
    }
1798
1799
    /**
1800
     * @param int    $id
1801
     * @param string $recordId
1802
     *
1803
     * @return bool
1804
     */
1805
    public function regenerateRecording($id, $recordId = '')
1806
    {
1807
        if ($this->plugin->get('allow_regenerate_recording') !== 'true') {
1808
            return false;
1809
        }
1810
1811
        if (empty($id)) {
1812
            return false;
1813
        }
1814
1815
        $meetingData = Database::select(
1816
            '*',
1817
            $this->table,
1818
            array('where' => array('id = ?' => array($id))),
1819
            'first'
1820
        );
1821
1822
        Event::addEvent(
1823
            'bbb_regenerate_record',
1824
            'record_id',
1825
            (int) $recordId,
1826
            null,
1827
            api_get_user_id(),
1828
            api_get_course_int_id(),
1829
            api_get_session_id()
1830
        );
1831
1832
        // Check if there are recordings for this meeting
1833
        $recordings = $this->api->getRecordings(['meetingId' => $meetingData['remote_id']]);
1834
        if (!empty($recordings) && isset($recordings['messageKey']) && $recordings['messageKey'] === 'noRecordings') {
1835
            // Regenerate the meeting id
1836
            if (!empty($meetingData['internal_meeting_id'])) {
1837
                return $this->api->generateRecording(['recordId' => $meetingData['internal_meeting_id']]);
1838
            }
1839
1840
            /*$pass = $this->getModMeetingPassword();
1841
            $info = $this->getMeetingInfo(['meetingId' => $meetingData['remote_id'], 'password' => $pass]);
1842
            if (!empty($info) && isset($info['internalMeetingID'])) {
1843
                return $this->api->generateRecording(['recordId' => $meetingData['internal_meeting_id']]);
1844
            }*/
1845
1846
            return false;
1847
        } else {
1848
            if (!empty($recordings['records'])) {
1849
                $recordExists = false;
1850
                foreach ($recordings['records'] as $record) {
1851
                    if ($recordId == $record['recordId']) {
1852
                        $recordExists = true;
1853
                        break;
1854
                    }
1855
                }
1856
1857
                if ($recordExists) {
1858
                    return $this->api->generateRecording(['recordId' => $recordId]);
1859
                }
1860
            }
1861
        }
1862
1863
        return false;
1864
    }
1865
1866
    /**
1867
     * Deletes a recording of a meeting
1868
     *
1869
     * @param int $id ID of the recording
1870
     *
1871
     * @return bool
1872
     *
1873
     * @assert () === false
1874
     * @todo Also delete links and agenda items created from this recording
1875
     */
1876
    public function deleteRecording($id)
1877
    {
1878
        if (empty($id)) {
1879
            return false;
1880
        }
1881
1882
        $meetingData = Database::select(
1883
            '*',
1884
            $this->table,
1885
            array('where' => array('id = ?' => array($id))),
1886
            'first'
1887
        );
1888
1889
        Event::addEvent(
1890
            'bbb_delete_record',
1891
            'meeting_id',
1892
            $id,
1893
            null,
1894
            api_get_user_id(),
1895
            api_get_course_int_id(),
1896
            api_get_session_id()
1897
        );
1898
1899
        $delete = false;
1900
        $recordings = [];
1901
        // Check if there are recordings for this meeting
1902
        if (!empty($meetingData['remote_id'])) {
1903
            Event::addEvent(
1904
                'bbb_delete_record',
1905
                'remote_id',
1906
                $meetingData['remote_id'],
1907
                null,
1908
                api_get_user_id(),
1909
                api_get_course_int_id(),
1910
                api_get_session_id()
1911
            );
1912
            $recordings = $this->api->getRecordings(['meetingId' => $meetingData['remote_id']]);
1913
        }
1914
        if (!empty($recordings) && isset($recordings['messageKey']) && $recordings['messageKey'] == 'noRecordings') {
1915
            $delete = true;
1916
        } else {
1917
            if (!empty($recordings['records'])) {
1918
                $recordsToDelete = [];
1919
                foreach ($recordings['records'] as $record) {
1920
                    $recordsToDelete[] = $record['recordId'];
1921
                }
1922
                $delete = true;
1923
                if (!empty($recordsToDelete)) {
1924
                    $recordingParams = ['recordId' => implode(',', $recordsToDelete)];
1925
                    Event::addEvent(
1926
                        'bbb_delete_record',
1927
                        'record_id_list',
1928
                        implode(',', $recordsToDelete),
1929
                        null,
1930
                        api_get_user_id(),
1931
                        api_get_course_int_id(),
1932
                        api_get_session_id()
1933
                    );
1934
                    $result = $this->api->deleteRecordingsWithXmlResponseArray($recordingParams);
1935
                    if (!empty($result) && isset($result['deleted']) && $result['deleted'] === 'true') {
1936
                        $delete = true;
1937
                    }
1938
                }
1939
            }
1940
        }
1941
1942
        if ($delete) {
1943
            Database::delete(
1944
                'plugin_bbb_room',
1945
                array('meeting_id = ?' => array($id))
1946
            );
1947
1948
            Database::delete(
1949
                $this->table,
1950
                array('id = ?' => array($id))
1951
            );
1952
        }
1953
1954
        return $delete;
1955
    }
1956
1957
    /**
1958
     * Creates a link in the links tool from the given videoconference recording
1959
     *
1960
     * @param int $id ID of the item in the plugin_bbb_meeting table
1961
     * @param string Hash identifying the recording, as provided by the API
1962
     *
1963
     * @return mixed ID of the newly created link, or false on error
1964
     * @assert (null, null) === false
1965
     * @assert (1, null) === false
1966
     * @assert (null, 'abcdefabcdefabcdefabcdef') === false
1967
     */
1968
    public function copyRecordingToLinkTool($id)
1969
    {
1970
        if (empty($id)) {
1971
            return false;
1972
        }
1973
        //$records =  BigBlueButtonBN::getRecordingsUrl($id);
1974
        $meetingData = Database::select(
1975
            '*',
1976
            $this->table,
1977
            array('where' => array('id = ?' => array($id))),
1978
            'first'
1979
        );
1980
1981
        $records = $this->api->getRecordingsWithXmlResponseArray(
1982
            array('meetingId' => $meetingData['remote_id'])
1983
        );
1984
1985
        if (!empty($records)) {
1986
            if (isset($records['message']) && !empty($records['message'])) {
1987
                if ($records['messageKey'] == 'noRecordings') {
1988
                    $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...
1989
                } else {
1990
                    //$recordArray[] = $records['message'];
1991
                }
1992
1993
                return false;
1994
            } else {
1995
                $record = $records[0];
1996
                if (is_array($record) && isset($record['recordId'])) {
1997
                    $url = $record['playbackFormatUrl'];
1998
                    $link = new Link();
1999
                    $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...
2000
                    $params['title'] = $meetingData['meeting_name'];
2001
                    $id = $link->save($params);
2002
2003
                    return $id;
2004
                }
2005
            }
2006
        }
2007
2008
        return false;
2009
    }
2010
2011
    /**
2012
     * Checks if the video conference server is running.
2013
     * Function currently disabled (always returns 1)
2014
     * @return bool True if server is running, false otherwise
2015
     * @assert () === false
2016
     */
2017
    public function isServerRunning()
2018
    {
2019
        return true;
2020
        //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url);
2021
    }
2022
2023
    /**
2024
     * Checks if the video conference plugin is properly configured
2025
     * @return bool True if plugin has a host and a salt, false otherwise
2026
     * @assert () === false
2027
     */
2028
    public function isServerConfigured()
2029
    {
2030
        $host = $this->plugin->get('host');
2031
2032
        if (empty($host)) {
2033
            return false;
2034
        }
2035
2036
        $salt = $this->plugin->get('salt');
2037
2038
        if (empty($salt)) {
2039
            return false;
2040
        }
2041
2042
        return true;
2043
        //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url);
2044
    }
2045
2046
    /**
2047
     * Get active session in the all platform
2048
     */
2049
    public function getActiveSessionsCount()
2050
    {
2051
        $meetingList = Database::select(
2052
            'count(id) as count',
2053
            $this->table,
2054
            array('where' => array('status = ? AND access_url = ?' => array(1, $this->accessUrl))),
2055
            'first'
2056
        );
2057
2058
        return $meetingList['count'];
2059
    }
2060
2061
    /**
2062
     * Get active session in the all platform
2063
     *
2064
     * @param boolean $allSites Parameter to indicate whether to get the result from all sites
2065
     *
2066
     * @return array
2067
     */
2068
    public function getActiveSessions(bool $allSites = false): array
2069
    {
2070
        $where = ['where' => ['status = ?' => 1]];
2071
2072
        if (!$allSites) {
2073
            $where['where'][' AND access_url = ?'] = $this->accessUrl;
2074
        }
2075
2076
        return Database::select(
2077
            '*',
2078
            $this->table,
2079
            $where
2080
        );
2081
    }
2082
2083
    /**
2084
     * @param string $url
2085
     */
2086
    public function redirectToBBB($url)
2087
    {
2088
        if (file_exists(__DIR__.'/../config.vm.php')) {
2089
            // Using VM
2090
            echo Display::url($this->plugin->get_lang('ClickToContinue'), $url);
2091
            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...
2092
        } else {
2093
            // Classic
2094
            header("Location: $url");
2095
            exit;
2096
        }
2097
    }
2098
2099
    /**
2100
     * @return string
2101
     */
2102
    public function getConferenceUrl()
2103
    {
2104
        return api_get_path(WEB_PLUGIN_PATH).'bbb/start.php?launch=1&'.$this->getUrlParams();
2105
    }
2106
2107
    /**
2108
     * Get the meeting info from DB by its name
2109
     *
2110
     * @param string $name
2111
     *
2112
     * @return array
2113
     */
2114
    public function findMeetingByName($name)
2115
    {
2116
        $meetingData = Database::select(
2117
            '*',
2118
            'plugin_bbb_meeting',
2119
            array('where' => array('meeting_name = ? AND status = 1 ' => $name)),
2120
            'first'
2121
        );
2122
2123
        return $meetingData;
2124
    }
2125
2126
    /**
2127
     * Get the meeting info from DB by its name
2128
     *
2129
     * @param int $id
2130
     *
2131
     * @return array
2132
     */
2133
    public function getMeeting($id)
2134
    {
2135
        $meetingData = Database::select(
2136
            '*',
2137
            'plugin_bbb_meeting',
2138
            array('where' => array('id = ?' => $id)),
2139
            'first'
2140
        );
2141
2142
        return $meetingData;
2143
    }
2144
2145
    /**
2146
     * Get the meeting info.
2147
     *
2148
     * @param int $id
2149
     *
2150
     * @return array
2151
     */
2152
    public function getMeetingByRemoteId($id)
2153
    {
2154
        $meetingData = Database::select(
2155
            '*',
2156
            'plugin_bbb_meeting',
2157
            array('where' => array('remote_id = ?' => $id)),
2158
            'first'
2159
        );
2160
2161
        return $meetingData;
2162
    }
2163
2164
    /**
2165
     * @param int $meetingId
2166
     *
2167
     * @return array
2168
     */
2169
    public function findConnectedMeetingParticipants($meetingId)
2170
    {
2171
        $meetingData = Database::select(
2172
            '*',
2173
            'plugin_bbb_room',
2174
            array('where' => array('meeting_id = ? AND in_at IS NOT NULL' => $meetingId))
2175
        );
2176
        $participantIds = [];
2177
        $return = [];
2178
2179
        foreach ($meetingData as $participantInfo) {
2180
            if (in_array($participantInfo['participant_id'], $participantIds)) {
2181
                continue;
2182
            }
2183
2184
            $participantIds[] = $participantInfo['participant_id'];
2185
2186
            $return[] = [
2187
                'id' => $participantInfo['id'],
2188
                'meeting_id' => $participantInfo['meeting_id'],
2189
                'participant' => api_get_user_entity($participantInfo['participant_id']),
2190
                'in_at' => $participantInfo['in_at'],
2191
                'out_at' => $participantInfo['out_at'],
2192
            ];
2193
        }
2194
2195
        return $return;
2196
    }
2197
2198
    /**
2199
     * Check if the meeting has a capture.m4v video file. If exists then the has_video_m4v field is updated
2200
     *
2201
     * @param int $meetingId
2202
     *
2203
     * @return bool
2204
     */
2205
    public function checkDirectMeetingVideoUrl($meetingId)
2206
    {
2207
        $meetingInfo = Database::select(
2208
            '*',
2209
            'plugin_bbb_meeting',
2210
            [
2211
                'where' => ['id = ?' => intval($meetingId)],
2212
            ],
2213
            'first'
2214
        );
2215
2216
        if (!isset($meetingInfo['video_url'])) {
2217
            return false;
2218
        }
2219
2220
        $hasCapture = SocialManager::verifyUrl($meetingInfo['video_url'].'/capture.m4v');
2221
2222
        if ($hasCapture) {
2223
            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...
2224
                'plugin_bbb_meeting',
2225
                ['has_video_m4v' => true],
2226
                ['id = ?' => intval($meetingId)]
2227
            );
2228
        }
2229
2230
        return $hasCapture;
2231
    }
2232
}
2233