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
                $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