Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

plugin/openmeetings/lib/openmeetings.class.php (1 issue)

1
<?php
2
/**
3
 * Chamilo-OpenMeetings integration plugin library, defining methods to connect
4
 * to OpenMeetings from Chamilo by calling its web services.
5
 *
6
 * @package chamilo.plugin.openmeetings
7
 */
8
9
namespace Chamilo\Plugin\OpenMeetings;
10
11
include_once __DIR__.'/session.class.php';
12
include_once __DIR__.'/room.class.php';
13
include_once __DIR__.'/user.class.php';
14
15
/**
16
 * Open Meetings-Chamilo connector class.
17
 */
18
class OpenMeetings
19
{
20
    public $url;
21
    public $user;
22
    public $pass;
23
    public $api;
24
    public $user_complete_name = null;
25
    public $protocol = 'http://';
26
    public $debug = false;
27
    public $logout_url = null;
28
    public $plugin_enabled = false;
29
    public $sessionId = "";
30
    public $roomName = '';
31
    public $chamiloCourseId;
32
    public $chamiloSessionId;
33
    public $externalType;
34
35
    /**
36
     * Constructor (generates a connection to the API and the Chamilo settings
37
     * required for the connection to the video conference server).
38
     */
39
    public function __construct()
40
    {
41
        global $_configuration;
42
43
        // initialize video server settings from global settings
44
        $plugin = \OpenMeetingsPlugin::create();
45
46
        $om_plugin = (bool) $plugin->get('tool_enable');
47
        $om_host = $plugin->get('host');
48
        $om_user = $plugin->get('user');
49
        $om_pass = $plugin->get('pass');
50
        $accessUrl = api_get_access_url($_configuration['access_url']);
51
        $this->externalType = substr($accessUrl['url'], strpos($accessUrl['url'], '://') + 3, -1);
52
        if (strcmp($this->externalType, 'localhost') == 0) {
53
            $this->externalType = substr(api_get_path(WEB_PATH), strpos(api_get_path(WEB_PATH), '://') + 3, -1);
54
        }
55
        $this->externalType = 'chamilolms.'.$this->externalType;
56
        $this->table = \Database::get_main_table('plugin_openmeetings');
57
58
        if ($om_plugin) {
59
            $user_info = api_get_user_info();
60
            $this->user_complete_name = $user_info['complete_name'];
61
            $this->user = $om_user;
62
            $this->pass = $om_pass;
63
            $this->url = $om_host;
64
65
            // Setting OM api
66
            define('CONFIG_OPENMEETINGS_USER', $this->user);
67
            define('CONFIG_OPENMEETINGS_PASS', $this->pass);
68
            define('CONFIG_OPENMEETINGS_SERVER_URL', $this->url);
69
70
            $this->gateway = new \OpenMeetingsGateway($this->url, $this->user, $this->pass);
71
            $this->plugin_enabled = $om_plugin;
72
            // The room has a name composed of C + course ID + '-' + session ID
73
            $this->chamiloCourseId = api_get_course_int_id();
74
            $this->chamiloSessionId = api_get_session_id();
75
            $this->roomName = 'C'.$this->chamiloCourseId.'-'.$this->chamiloSessionId;
76
            $return = $this->gateway->loginUser();
77
            if ($return == 0) {
78
                $msg = 'Could not initiate session with server through OpenMeetingsGateway::loginUser()';
79
                error_log(__FILE__.'+'.__LINE__.': '.$msg);
80
                exit($msg);
81
            }
82
            $this->sessionId = $this->gateway->sessionId;
83
        }
84
    }
85
86
    /**
87
     * Checks whether a user is teacher in the current course.
88
     *
89
     * @return bool True if the user can be considered a teacher in this course, false otherwise
90
     */
91
    public function isTeacher()
92
    {
93
        return api_is_course_admin() || api_is_coach() || api_is_platform_admin();
94
    }
95
96
    /*
97
     * Creating a Room for the meeting
98
    * @return bool True if the user is correct and false when is incorrect
99
    */
100
    public function createMeeting($params)
101
    {
102
        global $_configuration;
103
        // First, try to see if there is an active room for this course and session.
104
        $roomId = null;
105
106
        $meetingData = \Database::select(
107
            '*',
108
            $this->table,
109
            [
110
                'where' => [
111
                    'c_id = ?' => $this->chamiloCourseId,
112
                    ' AND session_id = ? ' => $this->chamiloSessionId,
113
                    ' AND status <> ? ' => 2,
114
                ],
115
            ],
116
            'first'
117
        );
118
119
        if ($meetingData != false && count($meetingData) > 0) {
120
            // There has been a room in the past for this course. It should
121
            // still be on the server, so update (instead of creating a new one)
122
            // This fills the following attributes: status, name, comment, chamiloCourseId, chamiloSessionId
123
            $room = new Room();
124
            $room->loadRoomId($meetingData['room_id']);
125
            $roomArray = (array) $room;
126
            $roomArray['SID'] = $this->sessionId;
127
            $roomId = $this->gateway->updateRoomWithModeration($room);
128
            if ($roomId != $meetingData['room_id']) {
129
                $msg = 'Something went wrong: the updated room ID ('.$roomId.') is not the same as the one we had ('.$meetingData['room_id'].')';
130
                exit($msg);
131
            }
132
        } else {
133
            $room = new Room();
134
            $room->SID = $this->sessionId;
135
            $room->name = $this->roomName;
136
            //$room->roomtypes_id = $room->roomtypes_id;
137
            $room->comment = urlencode(get_lang('Course').': '.$params['meeting_name'].' - '.$_configuration['software_name']);
138
            //$room->numberOfPartizipants = $room->numberOfPartizipants;
139
            $room->ispublic = boolval($room->getString('isPublic', 'false'));
140
            //$room->appointment = $room->getString('appointment');
141
            //$room->isDemoRoom = $room->getString('isDemoRoom');
142
            //$room->demoTime = $room->demoTime;
143
            //$room->isModeratedRoom = $room->getString('isModeratedRoom');
144
            $roomId = $this->gateway->createRoomWithModAndType($room);
145
        }
146
147
        if (!empty($roomId)) {
148
            /*
149
            // Find the biggest room_id so far, and create a new one
150
            if (empty($roomId)) {
151
                $roomData = \Database::select('MAX(room_id) as room_id', $this->table, array(), 'first');
152
                $roomId = $roomData['room_id'] + 1;
153
            }*/
154
155
            $params['status'] = '1';
156
            $params['meeting_name'] = $room->name;
157
            $params['created_at'] = api_get_utc_datetime();
158
            $params['room_id'] = $roomId;
159
            $params['c_id'] = api_get_course_int_id();
160
            $params['session_id'] = api_get_session_id();
161
            $params['record'] = ($room->allowRecording ? 1 : 0);
162
163
            $id = \Database::insert($this->table, $params);
164
165
            $this->joinMeeting($id);
166
        } else {
167
            return -1;
168
        }
169
    }
170
171
    /**
172
     * Returns a meeting "join" URL.
173
     *
174
     * @param string The name of the meeting (usually the course code)
175
     *
176
     * @return mixed The URL to join the meeting, or false on error
177
     *
178
     * @todo implement moderator pass
179
     * @assert ('') === false
180
     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
181
     */
182
    public function joinMeeting($meetingId)
183
    {
184
        if (empty($meetingId)) {
185
            return false;
186
        }
187
        $meetingData = \Database::select(
188
            '*',
189
            $this->table,
190
            ['where' => ['id = ? AND status = 1 ' => $meetingId]],
191
            'first'
192
        );
193
194
        if (empty($meetingData)) {
195
            if ($this->debug) {
196
                error_log("meeting does not exist: $meetingId ");
197
            }
198
199
            return false;
200
        }
201
        $params = ['room_id' => $meetingData['room_id']];
202
        $returnVal = $this->setUserObjectAndGenerateRoomHashByURLAndRecFlag($params);
203
        $iframe = $this->url."/?"."secureHash=".$returnVal;
204
        printf("<iframe src='%s' width='%s' height = '%s' />", $iframe, "100%", 640);
205
    }
206
207
    /**
208
     * Checks if the videoconference server is running.
209
     * Function currently disabled (always returns 1).
210
     *
211
     * @return bool True if server is running, false otherwise
212
     * @assert () === false
213
     */
214
    public function isServerRunning()
215
    {
216
        // Always return true for now as this requires the openmeetings object
217
        // to have been instanciated and this includes a loginUser() which
218
        // connects to the server
219
        return true;
220
    }
221
222
    /**
223
     * Gets the password for a specific meeting for the current user.
224
     *
225
     * @return string A moderator password if user is teacher, or the course code otherwise
226
     */
227
    public function getMeetingUserPassword()
228
    {
229
        if ($this->isTeacher()) {
230
            return $this->getMeetingModerationPassword();
231
        } else {
232
            return api_get_course_id();
233
        }
234
    }
235
236
    /**
237
     * Generated a moderator password for the meeting.
238
     *
239
     * @return string A password for the moderation of the video conference
240
     */
241
    public function getMeetingModerationPassword()
242
    {
243
        return api_get_course_id().'mod';
244
    }
245
246
    /**
247
     * Get information about the given meeting.
248
     *
249
     * @param array ...?
250
     *
251
     * @return mixed Array of information on success, false on error
252
     * @assert (array()) === false
253
     */
254
    public function getMeetingInfo($params)
255
    {
256
        try {
257
            $result = $this->api->getMeetingInfoArray($params);
258
            if ($result == null) {
259
                if ($this->debug) {
260
                    error_log(__FILE__.'+'.__LINE__." Failed to get any response. Maybe we can't contact the OpenMeetings server.");
261
                }
262
            } else {
263
                return $result;
264
            }
265
        } catch (Exception $e) {
0 ignored issues
show
The type Chamilo\Plugin\OpenMeetings\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
266
            if ($this->debug) {
267
                error_log(__FILE__.'+'.__LINE__.' Caught exception: ', $e->getMessage(), "\n");
268
            }
269
        }
270
271
        return false;
272
    }
273
274
    /**
275
     * @param array $params Array of parameters
276
     *
277
     * @return mixed
278
     */
279
    public function setUserObjectAndGenerateRecordingHashByURL($params)
280
    {
281
        $username = $_SESSION['_user']['username'];
282
        $firstname = $_SESSION['_user']['firstname'];
283
        $lastname = $_SESSION['_user']['lastname'];
284
        $userId = $_SESSION['_user']['user_id'];
285
        $systemType = 'chamilo';
286
        $room_id = $params['room_id'];
287
288
        $urlWsdl = $this->url."/services/UserService?wsdl";
289
        $omServices = new \SoapClient($urlWsdl);
290
        $objRec = new User();
291
292
        $objRec->SID = $this->sessionId;
293
        $objRec->username = $username;
294
        $objRec->firstname = $firstname;
295
        $objRec->lastname = $lastname;
296
        $objRec->externalUserId = $userId;
297
        $objRec->externalUserType = $systemType;
298
        $objRec->recording_id = $recording_id;
299
        $orFn = $omServices->setUserObjectAndGenerateRecordingHashByURL($objRec);
300
301
        return $orFn->return;
302
    }
303
304
    /**
305
     * @param array $params Array of parameters
306
     *
307
     * @return mixed
308
     */
309
    public function setUserObjectAndGenerateRoomHashByURLAndRecFlag($params)
310
    {
311
        $username = $_SESSION['_user']['username'];
312
        $firstname = $_SESSION['_user']['firstname'];
313
        $lastname = $_SESSION['_user']['lastname'];
314
        $profilePictureUrl = $_SESSION['_user']['avatar'];
315
        $email = $_SESSION['_user']['mail'];
316
        $userId = $_SESSION['_user']['user_id'];
317
        $systemType = 'Chamilo';
318
        $room_id = $params['room_id'];
319
        $becomeModerator = ($this->isTeacher() ? 1 : 0);
320
        $allowRecording = 1; //Provisional
321
322
        $urlWsdl = $this->url."/services/UserService?wsdl";
323
        $omServices = new \SoapClient($urlWsdl);
324
        $objRec = new User();
325
326
        $objRec->SID = $this->sessionId;
327
        $objRec->username = $username;
328
        $objRec->firstname = $firstname;
329
        $objRec->lastname = $lastname;
330
        $objRec->profilePictureUrl = $profilePictureUrl;
331
        $objRec->email = $email;
332
        $objRec->externalUserId = $userId;
333
        $objRec->externalUserType = $systemType;
334
        $objRec->room_id = $room_id;
335
        $objRec->becomeModeratorAsInt = $becomeModerator;
336
        $objRec->showAudioVideoTestAsInt = 1;
337
        $objRec->allowRecording = $allowRecording;
338
        $rcFn = $omServices->setUserObjectAndGenerateRoomHashByURLAndRecFlag($objRec);
339
340
        return $rcFn->return;
341
    }
342
343
    /**
344
     * Gets all the course meetings saved in the plugin_openmeetings table.
345
     *
346
     * @return array Array of current open meeting rooms
347
     */
348
    public function getCourseMeetings()
349
    {
350
        $newMeetingsList = [];
351
        $item = [];
352
        $meetingsList = \Database::select(
353
            '*',
354
            $this->table,
355
            ['where' => [
356
                    'c_id = ? ' => api_get_course_int_id(),
357
                    ' AND session_id = ? ' => api_get_session_id(),
358
                    ' AND status <> ? ' => 2, // status deleted
359
                ],
360
            ]
361
        );
362
        $room = new Room();
363
        $room->SID = $this->sessionId;
364
        if (!empty($meetingsList)) {
365
            foreach ($meetingsList as $meetingDb) {
366
                //$room->rooms_id = $meetingDb['room_id'];
367
                error_log(__FILE__.'+'.__LINE__.' Meetings found: '.print_r($meetingDb, 1));
368
                $remoteMeeting = [];
369
                $meetingDb['created_at'] = api_get_local_time($meetingDb['created_at']);
370
                $meetingDb['closed_at'] = (!empty($meetingDb['closed_at']) ? api_get_local_time($meetingDb['closed_at']) : '');
371
                // Fixed value for now
372
                $meetingDb['participantCount'] = 40;
373
                $rec = $this->gateway->getFlvRecordingByRoomId($meetingDb['room_id']);
374
                $links = [];
375
                // Links to videos look like these:
376
                // http://video2.openmeetings.com:5080/openmeetings/DownloadHandler?fileName=flvRecording_4.avi&moduleName=lzRecorderApp&parentPath=&room_id=&sid=dfc0cac396d384f59242aa66e5a9bbdd
377
                $link = $this->url.'/DownloadHandler?fileName=%s&moduleName=lzRecorderApp&parentPath=&room_id=%s&sid=%s';
378
                if (!empty($rec)) {
379
                    $link1 = sprintf($link, $rec['fileHash'], $meetingDb['room_id'], $this->sessionId);
380
                    $link2 = sprintf($link, $rec['alternateDownload'], $meetingDb['room_id'], $this->sessionId);
381
                    $links[] = $rec['fileName'].' '.
382
                        \Display::url('[.flv]', $link1, ['target' => '_blank']).' '.
383
                        \Display::url('[.avi]', $link2, ['target' => '_blank']);
384
                }
385
                $item['show_links'] = implode('<br />', $links);
386
387
                // The following code is currently commented because the web service
388
                // says this is not allowed by the SOAP user.
389
                /*
390
                try {
391
                    // Get the conference room object from OpenMeetings server - requires SID and rooms_id to be defined
392
                    $objRoomId = $this->gateway->getRoomById($meetingDb['room_id']);
393
                    if (empty($objRoomId->return)) {
394
                        error_log(__FILE__.'+'.__LINE__.' Emptyyyyy ');
395
                        //\Database::delete($this->table, "id = {$meetingDb['id']}");
396
                        // Don't delete expired rooms, just mark as closed
397
                        \Database::update($this->table, array('status' => 0, 'closed_at' => api_get_utc_datetime()), array('id = ? ' => $meetingDb['id']));
398
                        continue;
399
                    }
400
                    //$objCurUs = $omServices->getRoomWithCurrentUsersById($objCurrentUsers);
401
                } catch  (SoapFault $e) {
402
                    error_log(__FILE__.'+'.__LINE__.' '.$e->faultstring);
403
                    exit;
404
                }
405
                //if( empty($objCurUs->returnMeetingID) ) continue;
406
407
                $current_room = array(
408
                    'roomtype' => $objRoomId->return->roomtype->roomtypes_id,
409
                    'meetingName' => $objRoomId->return->name,
410
                    'meetingId' => $objRoomId->return->meetingID,
411
                    'createTime' => $objRoomId->return->rooms_id,
412
                    'showMicrophoneStatus' => $objRoomId->return->showMicrophoneStatus,
413
                    'attendeePw' => $objRoomId->return->attendeePW,
414
                    'moderatorPw' => $objRoomId->return->moderators,
415
                    'isClosed' => $objRoomId->return->isClosed,
416
                    'allowRecording' => $objRoomId->return->allowRecording,
417
                    'startTime' => $objRoomId->return->startTime,
418
                    'endTime' => $objRoomId->return->updatetime,
419
                    'participantCount' => count($objRoomId->return->currentusers),
420
                    'maxUsers' => $objRoomId->return->numberOfPartizipants,
421
                    'moderatorCount' => count($objRoomId->return->moderators)
422
                );
423
                    // Then interate through attendee results and return them as part of the array:
424
                if (!empty($objRoomId->return->currentusers)) {
425
                        foreach ($objRoomId->return->currentusers as $a)
426
                          $current_room[] = array(
427
                                    'userId' => $a->username,
428
                                    'fullName' => $a->firstname . " " . $a->lastname,
429
                                    'isMod' => $a->isMod
430
                          );
431
                }
432
                $remoteMeeting = $current_room;
433
                */
434
435
                if (empty($remoteMeeting)) {
436
                    /*
437
                        error_log(__FILE__.'+'.__LINE__.' Empty remote Meeting for now');
438
                        if ($meetingDb['status'] == 1 && $this->isTeacher()) {
439
                            $this->endMeeting($meetingDb['id']);
440
                        }
441
                    */
442
                } else {
443
                    $remoteMeeting['add_to_calendar_url'] = api_get_self().'?action=add_to_calendar&id='.$meetingDb['id'].'&start='.api_strtotime($meetingDb['startTime']);
444
                }
445
                $remoteMeeting['end_url'] = api_get_self().'?action=end&id='.$meetingDb['id'];
446
                $remoteMeeting['delete_url'] = api_get_self().'?action=delete&id='.$meetingDb['id'];
447
448
                //$record_array = array();
449
450
                //            if ($meetingDb['record'] == 1) {
451
                //                $recordingParams = array(
452
                //                    'meetingId' => $meetingDb['id'],        //-- OPTIONAL - comma separate if multiple ids
453
                //                );
454
                //
455
                //                $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
456
                //                if (!empty($records)) {
457
                //                    $count = 1;
458
                //                    if (isset($records['message']) && !empty($records['message'])) {
459
                //                        if ($records['messageKey'] == 'noRecordings') {
460
                //                            $record_array[] = get_lang('NoRecording');
461
                //                        } else {
462
                //                            //$record_array[] = $records['message'];
463
                //                        }
464
                //                    } else {
465
                //                        foreach ($records as $record) {
466
                //                            if (is_array($record) && isset($record['recordId'])) {
467
                //                                $url = Display::url(get_lang('ViewRecord'), $record['playbackFormatUrl'], array('target' => '_blank'));
468
                //                                if ($this->is_teacher()) {
469
                //                                    $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meetingDb['id'].'&record_id='.$record['recordId']);
470
                //                                    $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meetingDb['id'].'&start='.api_strtotime($meetingDb['created_at']).'&url='.$record['playbackFormatUrl']);
471
                //                                    $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordId']);
472
                //                                }
473
                //                                //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
474
                //                                $count++;
475
                //                                $record_array[] = $url;
476
                //                            } else {
477
                //
478
                //                            }
479
                //                        }
480
                //                    }
481
                //                }
482
                //                //var_dump($record_array);
483
                //                $item['show_links']  = implode('<br />', $record_array);
484
                //
485
                //            }
486
                //
487
                //$item['created_at'] = api_convert_and_format_date($meetingDb['created_at']);
488
                //            //created_at
489
                //
490
                //            $item['publish_url'] = api_get_self().'?action=publish&id='.$meetingDb['id'];
491
                //            $item['unpublish_url'] = api_get_self().'?action=unpublish&id='.$meetingDb['id'];
492
                //
493
                //if ($meetingDb['status'] == 1) {
494
                //                $joinParams = array(
495
                //                    'meetingId' => $meetingDb['id'],        //-- REQUIRED - A unique id for the meeting
496
                //                    'username' => $this->user_complete_name,    //-- REQUIRED - The name that will display for the user in the meeting
497
                //                    'password' => $pass,            //-- REQUIRED - The attendee or moderator password, depending on what's passed here
498
                //                    'createTime' => '',            //-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
499
                //                    'userID' => '',            //    -- OPTIONAL - string
500
                //                    'webVoiceConf' => ''    //    -- OPTIONAL - string
501
                //                );
502
                //                $returnVal = $this->setUserObjectAndGenerateRoomHashByURLAndRecFlag( array('room_id' => $meetingDb['id']) );
503
                //                $joinUrl = CONFIG_OPENMEETINGS_SERVER_URL . "?" .
504
                //                           "secureHash=" . $returnVal;
505
                //
506
                //                $item['go_url'] = $joinUrl;
507
                //}
508
                $item = array_merge($item, $meetingDb, $remoteMeeting);
509
                //error_log(__FILE__.'+'.__LINE__.'  Item: '.print_r($item,1));
510
                $newMeetingsList[] = $item;
511
            } //end foreach $meetingsList
512
        }
513
514
        return $newMeetingsList;
515
    }
516
517
    /**
518
     * Send a command to the OpenMeetings server to close the meeting.
519
     *
520
     * @param int $meetingId
521
     *
522
     * @return int
523
     */
524
    public function endMeeting($meetingId)
525
    {
526
        try {
527
            $room = new Room($meetingId);
528
            $room->SID = $this->sessionId;
529
            $room->room_id = intval($meetingId);
530
            $room->status = false;
531
532
            $urlWsdl = $this->url."/services/RoomService?wsdl";
533
            $ws = new \SoapClient($urlWsdl);
534
535
            $roomClosed = $ws->closeRoom($room);
536
            if ($roomClosed > 0) {
537
                \Database::update(
538
                    $this->table,
539
                    [
540
                        'status' => 0,
541
                        'closed_at' => api_get_utc_datetime(),
542
                    ],
543
                    ['id = ? ' => $meetingId]
544
                );
545
            }
546
        } catch (SoapFault $e) {
547
            error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems: Fault: '.$e->faultstring);
548
            exit;
549
550
            return -1;
551
        }
552
    }
553
554
    /**
555
     * @param int $id
556
     *
557
     * @return int
558
     */
559
    public function deleteMeeting($id)
560
    {
561
        try {
562
            $room = new Room();
563
            $room->loadRoomId($id);
564
            $this->gateway->deleteRoom($room);
565
            \Database::update(
566
                $this->table,
567
                [
568
                    'status' => 2,
569
                ],
570
                ['id = ? ' => $id]
571
            );
572
573
            return $id;
574
        } catch (SoapFault $e) {
575
            error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems: Fault: '.$e->faultstring);
576
            exit;
577
578
            return -1;
579
        }
580
    }
581
}
582