Passed
Push — master ( c22b6a...5f79f5 )
by Julito
11:21
created

ZoomPlugin::createScheduleMeeting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 15
c 0
b 0
f 0
nc 2
nop 9
dl 0
loc 28
rs 9.7666

How to fix   Many Parameters   

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
use Chamilo\CoreBundle\Entity\Course;
6
use Chamilo\CoreBundle\Entity\Session;
7
use Chamilo\CourseBundle\Entity\CGroupInfo;
8
use Chamilo\PluginBundle\Zoom\API\JWTClient;
9
use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet;
10
use Chamilo\PluginBundle\Zoom\API\MeetingRegistrant;
11
use Chamilo\PluginBundle\Zoom\API\MeetingSettings;
12
use Chamilo\PluginBundle\Zoom\API\RecordingFile;
13
use Chamilo\PluginBundle\Zoom\API\RecordingList;
14
use Chamilo\PluginBundle\Zoom\Meeting;
15
use Chamilo\PluginBundle\Zoom\MeetingActivity;
16
use Chamilo\PluginBundle\Zoom\MeetingRepository;
17
use Chamilo\PluginBundle\Zoom\Recording;
18
use Chamilo\PluginBundle\Zoom\RecordingRepository;
19
use Chamilo\PluginBundle\Zoom\Registrant;
20
use Chamilo\PluginBundle\Zoom\RegistrantRepository;
21
use Chamilo\UserBundle\Entity\User;
22
use Doctrine\ORM\EntityRepository;
23
use Doctrine\ORM\OptimisticLockException;
24
use Doctrine\ORM\Tools\SchemaTool;
25
use Doctrine\ORM\Tools\ToolsException;
26
27
/**
28
 * Class ZoomPlugin. Integrates Zoom meetings in courses.
29
 */
30
class ZoomPlugin extends Plugin
31
{
32
    const RECORDING_TYPE_CLOUD = 'cloud';
33
    const RECORDING_TYPE_LOCAL = 'local';
34
    const RECORDING_TYPE_NONE = 'none';
35
    public $isCoursePlugin = true;
36
37
    /**
38
     * @var JWTClient
39
     */
40
    private $jwtClient;
41
42
    /**
43
     * ZoomPlugin constructor.
44
     * {@inheritdoc}
45
     * Initializes the API JWT client and the entity repositories.
46
     */
47
    public function __construct()
48
    {
49
        parent::__construct(
50
            '0.3',
51
            'Sébastien Ducoulombier, Julio Montoya',
52
            [
53
                'tool_enable' => 'boolean',
54
                'apiKey' => 'text',
55
                'apiSecret' => 'text',
56
                'verificationToken' => 'text',
57
                'enableParticipantRegistration' => 'boolean',
58
                'enableCloudRecording' => [
59
                    'type' => 'select',
60
                    'options' => [
61
                        self::RECORDING_TYPE_CLOUD => 'Cloud',
62
                        self::RECORDING_TYPE_LOCAL => 'Local',
63
                        self::RECORDING_TYPE_NONE => get_lang('None'),
64
                    ],
65
                ],
66
                'enableGlobalConference' => 'boolean',
67
                'globalConferenceAllowRoles' => [
68
                    'type' => 'select',
69
                    'options' => [
70
                        PLATFORM_ADMIN => get_lang('Administrator'),
71
                        COURSEMANAGER => get_lang('Teacher'),
72
                        STUDENT => get_lang('Student'),
73
                        STUDENT_BOSS => get_lang('StudentBoss'),
74
                    ],
75
                    'attributes' => ['multiple' => 'multiple'],
76
                ],
77
            ]
78
        );
79
80
        $this->isAdminPlugin = true;
81
        $this->jwtClient = new JWTClient($this->get('apiKey'), $this->get('apiSecret'));
82
    }
83
84
    /**
85
     * Caches and returns an instance of this class.
86
     *
87
     * @return ZoomPlugin the instance to use
88
     */
89
    public static function create()
90
    {
91
        static $instance = null;
92
93
        return $instance ? $instance : $instance = new self();
94
    }
95
96
    /**
97
     * @return bool
98
     */
99
    public static function currentUserCanJoinGlobalMeeting()
100
    {
101
        $user = api_get_user_entity(api_get_user_id());
102
103
        if (null === $user) {
104
            return false;
105
        }
106
107
        //return 'true' === api_get_plugin_setting('zoom', 'enableGlobalConference') && api_user_is_login();
108
        return
109
            'true' === api_get_plugin_setting('zoom', 'enableGlobalConference')
110
            && in_array(
111
                (api_is_platform_admin() ? PLATFORM_ADMIN : $user->getStatus()),
112
                (array) api_get_plugin_setting('zoom', 'globalConferenceAllowRoles')
113
            );
114
    }
115
116
    /**
117
     * @return array
118
     */
119
    public function getProfileBlockItems()
120
    {
121
        $elements = $this->meetingsToWhichCurrentUserIsRegisteredComingSoon();
122
        $addMeetingLink = false;
123
        if (self::currentUserCanJoinGlobalMeeting()) {
124
            $addMeetingLink = true;
125
        }
126
127
        if ($addMeetingLink) {
128
            $elements[$this->get_lang('Meetings')] = api_get_path(WEB_PLUGIN_PATH).'zoom/meetings.php';
129
        }
130
131
        $items = [];
132
        foreach ($elements as $title => $link) {
133
            $items[] = [
134
                'class' => 'video-conference',
135
                'icon' => Display::return_icon(
136
                    'bbb.png',
137
                    get_lang('VideoConference')
138
                ),
139
                'link' => $link,
140
                'title' => $title,
141
            ];
142
        }
143
144
        return $items;
145
    }
146
147
    /**
148
     * @return array [ $title => $link ]
149
     */
150
    public function meetingsToWhichCurrentUserIsRegisteredComingSoon()
151
    {
152
        $linkTemplate = api_get_path(WEB_PLUGIN_PATH).'zoom/join_meeting.php?meetingId=%s';
153
        $user = api_get_user_entity(api_get_user_id());
154
        $meetings = self::getRegistrantRepository()->meetingsComingSoonRegistrationsForUser($user);
155
        $items = [];
156
        foreach ($meetings as $registrant) {
157
            $meeting = $registrant->getMeeting();
158
            $items[sprintf(
159
                $this->get_lang('DateMeetingTitle'),
160
                $meeting->formattedStartTime,
161
                $meeting->getMeetingInfoGet()->topic
162
            )] = sprintf($linkTemplate, $meeting->getId());
163
        }
164
165
        return $items;
166
    }
167
168
    /**
169
     * @return RegistrantRepository|EntityRepository
170
     */
171
    public static function getRegistrantRepository()
172
    {
173
        return Database::getManager()->getRepository(Registrant::class);
174
    }
175
176
    /**
177
     * Creates this plugin's related tables in the internal database.
178
     * Installs course fields in all courses.
179
     *
180
     * @throws ToolsException
181
     */
182
    public function install()
183
    {
184
        (new SchemaTool(Database::getManager()))->createSchema(
185
            [
186
                Database::getManager()->getClassMetadata(Meeting::class),
187
                Database::getManager()->getClassMetadata(MeetingActivity::class),
188
                Database::getManager()->getClassMetadata(Recording::class),
189
                Database::getManager()->getClassMetadata(Registrant::class),
190
            ]
191
        );
192
        $this->install_course_fields_in_all_courses();
193
    }
194
195
    /**
196
     * Drops this plugins' related tables from the internal database.
197
     * Uninstalls course fields in all courses().
198
     */
199
    public function uninstall()
200
    {
201
        (new SchemaTool(Database::getManager()))->dropSchema(
202
            [
203
                Database::getManager()->getClassMetadata(Meeting::class),
204
                Database::getManager()->getClassMetadata(MeetingActivity::class),
205
                Database::getManager()->getClassMetadata(Recording::class),
206
                Database::getManager()->getClassMetadata(Registrant::class),
207
            ]
208
        );
209
        $this->uninstall_course_fields_in_all_courses();
210
    }
211
212
    /**
213
     * Generates the search form to include in the meeting list administration page.
214
     * The form has DatePickers 'start' and 'end' and Checkbox 'reloadRecordingLists'.
215
     *
216
     * @return FormValidator the form
217
     */
218
    public function getAdminSearchForm()
219
    {
220
        $form = new FormValidator('search');
221
        $form->addHeader($this->get_lang('SearchMeeting'));
222
        $form->addDatePicker('start', get_lang('StartDate'));
223
        $form->addDatePicker('end', get_lang('EndDate'));
224
        $form->addButtonSearch(get_lang('Search'));
225
        $oneMonth = new DateInterval('P1M');
226
        if ($form->validate()) {
227
            try {
228
                $start = new DateTime($form->getSubmitValue('start'));
229
            } catch (Exception $exception) {
230
                $start = new DateTime();
231
                $start->sub($oneMonth);
232
            }
233
            try {
234
                $end = new DateTime($form->getSubmitValue('end'));
235
            } catch (Exception $exception) {
236
                $end = new DateTime();
237
                $end->add($oneMonth);
238
            }
239
        } else {
240
            $start = new DateTime();
241
            $start->sub($oneMonth);
242
            $end = new DateTime();
243
            $end->add($oneMonth);
244
        }
245
        try {
246
            $form->setDefaults(
247
                [
248
                    'start' => $start->format('Y-m-d'),
249
                    'end' => $end->format('Y-m-d'),
250
                ]
251
            );
252
        } catch (Exception $exception) {
253
            error_log(join(':', [__FILE__, __LINE__, $exception]));
254
        }
255
256
        return $form;
257
    }
258
259
    /**
260
     * Generates a meeting edit form and updates the meeting on validation.
261
     *
262
     * @param Meeting $meeting the meeting
263
     *
264
     * @throws Exception
265
     *
266
     * @return FormValidator
267
     */
268
    public function getEditMeetingForm($meeting)
269
    {
270
        $meetingInfoGet = $meeting->getMeetingInfoGet();
271
        $form = new FormValidator('edit', 'post', $_SERVER['REQUEST_URI']);
272
        $form->addHeader($this->get_lang('UpdateMeeting'));
273
        $form->addText('topic', $this->get_lang('Topic'));
274
        if ($meeting->requiresDateAndDuration()) {
275
            $startTimeDatePicker = $form->addDateTimePicker('startTime', get_lang('StartTime'));
276
            $form->setRequired($startTimeDatePicker);
277
            $durationNumeric = $form->addNumeric('duration', $this->get_lang('DurationInMinutes'));
278
            $form->setRequired($durationNumeric);
279
        }
280
        $form->addTextarea('agenda', get_lang('Agenda'), ['maxlength' => 2000]);
281
        //$form->addLabel(get_lang('Password'), $meeting->getMeetingInfoGet()->password);
282
        // $form->addText('password', get_lang('Password'), false, ['maxlength' => '10']);
283
        $form->addButtonUpdate(get_lang('Update'));
284
        if ($form->validate()) {
285
            if ($meeting->requiresDateAndDuration()) {
286
                $meetingInfoGet->start_time = (new DateTime($form->getSubmitValue('startTime')))->format(
287
                    DateTimeInterface::ISO8601
288
                );
289
                $meetingInfoGet->timezone = date_default_timezone_get();
290
                $meetingInfoGet->duration = (int) $form->getSubmitValue('duration');
291
            }
292
            $meetingInfoGet->topic = $form->getSubmitValue('topic');
293
            $meetingInfoGet->agenda = $form->getSubmitValue('agenda');
294
            try {
295
                $meetingInfoGet->update();
296
                $meeting->setMeetingInfoGet($meetingInfoGet);
297
                Database::getManager()->persist($meeting);
298
                Database::getManager()->flush();
299
                Display::addFlash(
300
                    Display::return_message($this->get_lang('MeetingUpdated'), 'confirm')
301
                );
302
            } catch (Exception $exception) {
303
                Display::addFlash(
304
                    Display::return_message($exception->getMessage(), 'error')
305
                );
306
            }
307
        }
308
        $defaults = [
309
            'topic' => $meetingInfoGet->topic,
310
            'agenda' => $meetingInfoGet->agenda,
311
        ];
312
        if ($meeting->requiresDateAndDuration()) {
313
            $defaults['startTime'] = $meeting->startDateTime->format('Y-m-d H:i');
314
            $defaults['duration'] = $meetingInfoGet->duration;
315
        }
316
        $form->setDefaults($defaults);
317
318
        return $form;
319
    }
320
321
    /**
322
     * Generates a meeting delete form and deletes the meeting on validation.
323
     *
324
     * @param Meeting $meeting
325
     * @param string  $returnURL where to redirect to on successful deletion
326
     *
327
     * @throws Exception
328
     *
329
     * @return FormValidator
330
     */
331
    public function getDeleteMeetingForm($meeting, $returnURL)
332
    {
333
        $id = $meeting->getMeetingId();
334
        $form = new FormValidator('delete', 'post', api_get_self().'?meetingId='.$id);
335
        $form->addButtonDelete($this->get_lang('DeleteMeeting'));
336
        if ($form->validate()) {
337
            $this->deleteMeeting($meeting, $returnURL);
338
        }
339
340
        return $form;
341
    }
342
343
    /**
344
     * @param Meeting $meeting
345
     * @param string  $returnURL
346
     *
347
     * @return false
348
     */
349
    public function deleteMeeting($meeting, $returnURL)
350
    {
351
        if (null === $meeting) {
352
            return false;
353
        }
354
355
        $em = Database::getManager();
356
        try {
357
            // No need to delete a instant meeting.
358
            if (\Chamilo\PluginBundle\Zoom\API\Meeting::TYPE_INSTANT != $meeting->getMeetingInfoGet()->type) {
359
                $meeting->getMeetingInfoGet()->delete();
360
            }
361
362
            $em->remove($meeting);
363
            $em->flush();
364
365
            Display::addFlash(
366
                Display::return_message($this->get_lang('MeetingDeleted'), 'confirm')
367
            );
368
            api_location($returnURL);
369
        } catch (Exception $exception) {
370
            $this->handleException($exception);
371
        }
372
    }
373
374
    /**
375
     * @param Exception $exception
376
     */
377
    public function handleException($exception)
378
    {
379
        if ($exception instanceof Exception) {
0 ignored issues
show
introduced by
$exception is always a sub-type of Exception.
Loading history...
380
            $error = json_decode($exception->getMessage());
381
            $message = $exception->getMessage();
382
            if ($error->message) {
383
                $message = $error->message;
384
            }
385
            Display::addFlash(
386
                Display::return_message($message, 'error')
387
            );
388
        }
389
    }
390
391
    /**
392
     * Generates a registrant list update form listing course and session users.
393
     * Updates the list on validation.
394
     *
395
     * @param Meeting $meeting
396
     *
397
     * @throws Exception
398
     *
399
     * @return FormValidator
400
     */
401
    public function getRegisterParticipantForm($meeting)
402
    {
403
        $form = new FormValidator('register', 'post', $_SERVER['REQUEST_URI']);
404
        $userIdSelect = $form->addSelect('userIds', $this->get_lang('RegisteredUsers'));
405
        $userIdSelect->setMultiple(true);
406
        $form->addButtonSend($this->get_lang('UpdateRegisteredUserList'));
407
408
        $users = $meeting->getRegistrableUsers();
409
        foreach ($users as $user) {
410
            $userIdSelect->addOption(
411
                api_get_person_name($user->getFirstname(), $user->getLastname()),
412
                $user->getId()
413
            );
414
        }
415
416
        if ($form->validate()) {
417
            $selectedUserIds = $form->getSubmitValue('userIds');
418
            $selectedUsers = [];
419
            if (!empty($selectedUserIds)) {
420
                foreach ($users as $user) {
421
                    if (in_array($user->getId(), $selectedUserIds)) {
422
                        $selectedUsers[] = $user;
423
                    }
424
                }
425
            }
426
427
            try {
428
                $this->updateRegistrantList($meeting, $selectedUsers);
429
                Display::addFlash(
430
                    Display::return_message($this->get_lang('RegisteredUserListWasUpdated'), 'confirm')
431
                );
432
            } catch (Exception $exception) {
433
                Display::addFlash(
434
                    Display::return_message($exception->getMessage(), 'error')
435
                );
436
            }
437
        }
438
        $registeredUserIds = [];
439
        foreach ($meeting->getRegistrants() as $registrant) {
440
            $registeredUserIds[] = $registrant->getUser()->getId();
441
        }
442
        $userIdSelect->setSelected($registeredUserIds);
443
444
        return $form;
445
    }
446
447
    /**
448
     * Generates a meeting recording files management form.
449
     * Takes action on validation.
450
     *
451
     * @param Meeting $meeting
452
     *
453
     * @throws Exception
454
     *
455
     * @return FormValidator
456
     */
457
    public function getFileForm($meeting, $returnURL)
458
    {
459
        $form = new FormValidator('fileForm', 'post', $_SERVER['REQUEST_URI']);
460
        if (!$meeting->getRecordings()->isEmpty()) {
461
            $fileIdSelect = $form->addSelect('fileIds', get_lang('Files'));
462
            $fileIdSelect->setMultiple(true);
463
            $recordingList = $meeting->getRecordings();
464
            foreach ($recordingList as &$recording) {
465
                // $recording->instanceDetails = $plugin->getPastMeetingInstanceDetails($instance->uuid);
466
                $options = [];
467
                $recordings = $recording->getRecordingMeeting()->recording_files;
468
                foreach ($recordings as $file) {
469
                    $options[] = [
470
                        'text' => sprintf(
471
                            '%s.%s (%s)',
472
                            $file->recording_type,
473
                            $file->file_type,
474
                            $file->file_size
475
                        ),
476
                        'value' => $file->id,
477
                    ];
478
                }
479
                $fileIdSelect->addOptGroup(
480
                    $options,
481
                    sprintf("%s (%s)", $recording->formattedStartTime, $recording->formattedDuration)
482
                );
483
            }
484
            $actions = [];
485
            if ($meeting->isCourseMeeting()) {
486
                $actions['CreateLinkInCourse'] = $this->get_lang('CreateLinkInCourse');
487
                $actions['CopyToCourse'] = $this->get_lang('CopyToCourse');
488
            }
489
            $actions['DeleteFile'] = $this->get_lang('DeleteFile');
490
            $form->addRadio(
491
                'action',
492
                get_lang('Action'),
493
                $actions
494
            );
495
            $form->addButtonUpdate($this->get_lang('DoIt'));
496
            if ($form->validate()) {
497
                $action = $form->getSubmitValue('action');
498
                $idList = $form->getSubmitValue('fileIds');
499
500
                foreach ($recordingList as $recording) {
501
                    $recordings = $recording->getRecordingMeeting()->recording_files;
502
503
                    foreach ($recordings as $file) {
504
                        if (in_array($file->id, $idList)) {
505
                            $name = sprintf(
506
                                $this->get_lang('XRecordingOfMeetingXFromXDurationXDotX'),
507
                                $file->recording_type,
508
                                $meeting->getId(),
509
                                $recording->formattedStartTime,
510
                                $recording->formattedDuration,
511
                                $file->file_type
512
                            );
513
                            if ('CreateLinkInCourse' === $action && $meeting->isCourseMeeting()) {
514
                                try {
515
                                    $this->createLinkToFileInCourse($meeting, $file, $name);
516
                                    Display::addFlash(
517
                                        Display::return_message(
518
                                            $this->get_lang('LinkToFileWasCreatedInCourse'),
519
                                            'success'
520
                                        )
521
                                    );
522
                                } catch (Exception $exception) {
523
                                    Display::addFlash(
524
                                        Display::return_message($exception->getMessage(), 'error')
525
                                    );
526
                                }
527
                            } elseif ('CopyToCourse' === $action && $meeting->isCourseMeeting()) {
528
                                try {
529
                                    $this->copyFileToCourse($meeting, $file, $name);
530
                                    Display::addFlash(
531
                                        Display::return_message($this->get_lang('FileWasCopiedToCourse'), 'confirm')
532
                                    );
533
                                } catch (Exception $exception) {
534
                                    Display::addFlash(
535
                                        Display::return_message($exception->getMessage(), 'error')
536
                                    );
537
                                }
538
                            } elseif ('DeleteFile' === $action) {
539
                                try {
540
                                    $name = $file->recording_type;
541
                                    $file->delete();
542
                                    Display::addFlash(
543
                                        Display::return_message($this->get_lang('FileWasDeleted').': '.$name, 'confirm')
544
                                    );
545
                                } catch (Exception $exception) {
546
                                    Display::addFlash(
547
                                        Display::return_message($exception->getMessage(), 'error')
548
                                    );
549
                                }
550
                            }
551
                        }
552
                    }
553
                }
554
                api_location($returnURL);
555
            }
556
        }
557
558
        return $form;
559
    }
560
561
    /**
562
     * Adds to the meeting course documents a link to a meeting instance recording file.
563
     *
564
     * @param Meeting       $meeting
565
     * @param RecordingFile $file
566
     * @param string        $name
567
     *
568
     * @throws Exception
569
     */
570
    public function createLinkToFileInCourse($meeting, $file, $name)
571
    {
572
        $course = $meeting->getCourse();
573
        if (null === $course) {
574
            throw new Exception('This meeting is not linked to a course');
575
        }
576
        $courseInfo = api_get_course_info_by_id($course->getId());
577
        if (empty($courseInfo)) {
578
            throw new Exception('This meeting is not linked to a valid course');
579
        }
580
        $path = '/zoom_meeting_recording_file_'.$file->id.'.'.$file->file_type;
581
        $docId = DocumentManager::addCloudLink($courseInfo, $path, $file->play_url, $name);
582
        if (!$docId) {
583
            throw new Exception(get_lang(DocumentManager::cloudLinkExists($courseInfo, $path, $file->play_url) ? 'UrlAlreadyExists' : 'ErrorAddCloudLink'));
584
        }
585
    }
586
587
    /**
588
     * Copies a recording file to a meeting's course.
589
     *
590
     * @param Meeting       $meeting
591
     * @param RecordingFile $file
592
     * @param string        $name
593
     *
594
     * @throws Exception
595
     */
596
    public function copyFileToCourse($meeting, $file, $name)
597
    {
598
        $course = $meeting->getCourse();
599
        if (null === $course) {
600
            throw new Exception('This meeting is not linked to a course');
601
        }
602
        $courseInfo = api_get_course_info_by_id($course->getId());
603
        if (empty($courseInfo)) {
604
            throw new Exception('This meeting is not linked to a valid course');
605
        }
606
        $tmpFile = tmpfile();
607
        if (false === $tmpFile) {
608
            throw new Exception('tmpfile() returned false');
609
        }
610
        $curl = curl_init($file->getFullDownloadURL($this->jwtClient->token));
611
        if (false === $curl) {
612
            throw new Exception('Could not init curl: '.curl_error($curl));
613
        }
614
        if (!curl_setopt_array(
615
            $curl,
616
            [
617
                CURLOPT_FILE => $tmpFile,
618
                CURLOPT_FOLLOWLOCATION => true,
619
                CURLOPT_MAXREDIRS => 10,
620
                CURLOPT_TIMEOUT => 120,
621
            ]
622
        )) {
623
            throw new Exception("Could not set curl options: ".curl_error($curl));
624
        }
625
        if (false === curl_exec($curl)) {
626
            throw new Exception("curl_exec failed: ".curl_error($curl));
627
        }
628
629
        $sessionId = 0;
630
        $session = $meeting->getSession();
631
        if (null !== $session) {
632
            $sessionId = $session->getId();
633
        }
634
635
        $groupId = 0;
636
        $group = $meeting->getGroup();
637
        if (null !== $group) {
638
            $groupId = $group->getIid();
639
        }
640
641
        $newPath = handle_uploaded_document(
642
            $courseInfo,
643
            [
644
                'name' => $name,
645
                'tmp_name' => stream_get_meta_data($tmpFile)['uri'],
646
                'size' => filesize(stream_get_meta_data($tmpFile)['uri']),
647
                'from_file' => true,
648
                'move_file' => true,
649
                'type' => $file->file_type,
650
            ],
651
            api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document',
652
            '/',
653
            api_get_user_id(),
654
            $groupId,
655
            null,
656
            0,
657
            'overwrite',
658
            true,
659
            false,
660
            null,
661
            $sessionId,
662
            true
663
        );
664
665
        fclose($tmpFile);
666
        if (false === $newPath) {
667
            throw new Exception('Could not handle uploaded document');
668
        }
669
    }
670
671
    /**
672
     * Generates a form to fast and easily create and start an instant meeting.
673
     * On validation, create it then redirect to it and exit.
674
     *
675
     * @return FormValidator
676
     */
677
    public function getCreateInstantMeetingForm(
678
        User $user,
679
        Course $course,
680
        CGroupInfo $group = null,
681
        Session $session = null
682
    ) {
683
        $extraUrl = '';
684
        if (!empty($course)) {
685
            $extraUrl = api_get_cidreq();
686
        }
687
        $form = new FormValidator('createInstantMeetingForm', 'post', api_get_self().'?'.$extraUrl, '_blank');
688
        $form->addButton('startButton', $this->get_lang('StartInstantMeeting'), 'video-camera', 'primary');
689
        if ($form->validate()) {
690
            try {
691
                $this->startInstantMeeting($this->get_lang('InstantMeeting'), $user, $course, $group, $session);
692
            } catch (Exception $exception) {
693
                Display::addFlash(
694
                    Display::return_message($exception->getMessage(), 'error')
695
                );
696
            }
697
        }
698
699
        return $form;
700
    }
701
702
    /**
703
     * Generates a form to schedule a meeting.
704
     * On validation, creates it and redirects to its page.
705
     *
706
     * @throws Exception
707
     *
708
     * @return FormValidator
709
     */
710
    public function getScheduleMeetingForm(User $user, Course $course = null, CGroupInfo $group = null, Session $session = null)
711
    {
712
        $extraUrl = '';
713
        if (!empty($course)) {
714
            $extraUrl = api_get_cidreq();
715
        }
716
        $form = new FormValidator('scheduleMeetingForm', 'post', api_get_self().'?'.$extraUrl);
717
        $form->addHeader($this->get_lang('ScheduleAMeeting'));
718
        $startTimeDatePicker = $form->addDateTimePicker('startTime', get_lang('StartTime'));
719
        $form->setRequired($startTimeDatePicker);
720
721
        $form->addText('topic', $this->get_lang('Topic'), true);
722
        $form->addTextarea('agenda', get_lang('Agenda'), ['maxlength' => 2000]);
723
724
        $durationNumeric = $form->addNumeric('duration', $this->get_lang('DurationInMinutes'));
725
        $form->setRequired($durationNumeric);
726
727
        if (null === $course && 'true' === $this->get('enableGlobalConference')) {
728
            $options = [];
729
            $options['everyone'] = $this->get_lang('ForEveryone');
730
            $options['registered_users'] = $this->get_lang('SomeUsers');
731
            if (!empty($options)) {
732
                if (1 === count($options)) {
733
                    $form->addHidden('type', key($options));
734
                } else {
735
                    $form->addSelect('type', $this->get_lang('ConferenceType'), $options);
736
                }
737
            }
738
        } else {
739
            // To course
740
            $form->addHidden('type', 'course');
741
        }
742
743
        /*
744
       // $passwordText = $form->addText('password', get_lang('Password'), false, ['maxlength' => '10']);
745
       if (null !== $course) {
746
           $registrationOptions = [
747
               'RegisterAllCourseUsers' => $this->get_lang('RegisterAllCourseUsers'),
748
           ];
749
           $groups = GroupManager::get_groups();
750
           if (!empty($groups)) {
751
               $registrationOptions['RegisterTheseGroupMembers'] = get_lang('RegisterTheseGroupMembers');
752
           }
753
           $registrationOptions['RegisterNoUser'] = $this->get_lang('RegisterNoUser');
754
           $userRegistrationRadio = $form->addRadio(
755
               'userRegistration',
756
               $this->get_lang('UserRegistration'),
757
               $registrationOptions
758
           );
759
           $groupOptions = [];
760
           foreach ($groups as $group) {
761
               $groupOptions[$group['id']] = $group['name'];
762
           }
763
           $groupIdsSelect = $form->addSelect(
764
               'groupIds',
765
               $this->get_lang('RegisterTheseGroupMembers'),
766
               $groupOptions
767
           );
768
           $groupIdsSelect->setMultiple(true);
769
           if (!empty($groups)) {
770
               $jsCode = sprintf(
771
                   "getElementById('%s').parentNode.parentNode.parentNode.style.display = getElementById('%s').checked ? 'block' : 'none'",
772
                   $groupIdsSelect->getAttribute('id'),
773
                   $userRegistrationRadio->getelements()[1]->getAttribute('id')
774
               );
775
776
               $form->setAttribute('onchange', $jsCode);
777
           }
778
       }*/
779
780
        $form->addButtonCreate(get_lang('Save'));
781
782
        if ($form->validate()) {
783
            $type = $form->getSubmitValue('type');
784
785
            switch ($type) {
786
                case 'everyone':
787
                    $user = null;
788
                    $group = null;
789
                    $course = null;
790
                    $session = null;
791
792
                    break;
793
                case 'registered_users':
794
                    //$user = null;
795
                    $course = null;
796
                    $session = null;
797
798
                    break;
799
                case 'course':
800
                    $user = null;
801
                    //$course = null;
802
                    //$session = null;
803
804
                    break;
805
            }
806
807
            try {
808
                $newMeeting = $this->createScheduleMeeting(
809
                    $user,
810
                    $course,
811
                    $group,
812
                    $session,
813
                    new DateTime($form->getSubmitValue('startTime')),
814
                    $form->getSubmitValue('duration'),
815
                    $form->getSubmitValue('topic'),
816
                    $form->getSubmitValue('agenda'),
817
                    substr(uniqid('z', true), 0, 10)
818
                );
819
820
                Display::addFlash(
821
                    Display::return_message($this->get_lang('NewMeetingCreated'))
822
                );
823
824
                if ($newMeeting->isCourseMeeting()) {
825
                    if ('RegisterAllCourseUsers' === $form->getSubmitValue('userRegistration')) {
826
                        $this->registerAllCourseUsers($newMeeting);
827
                        Display::addFlash(
828
                            Display::return_message($this->get_lang('AllCourseUsersWereRegistered'))
829
                        );
830
                    } elseif ('RegisterTheseGroupMembers' === $form->getSubmitValue('userRegistration')) {
831
                        $userIds = [];
832
                        foreach ($form->getSubmitValue('groupIds') as $groupId) {
833
                            $userIds = array_unique(array_merge($userIds, GroupManager::get_users($groupId)));
834
                        }
835
                        $users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy(
836
                            ['id' => $userIds]
837
                        );
838
                        $this->registerUsers($newMeeting, $users);
839
                        Display::addFlash(
840
                            Display::return_message($this->get_lang('GroupUsersWereRegistered'))
841
                        );
842
                    }
843
                }
844
                api_location('meeting.php?meetingId='.$newMeeting->getMeetingId().'&'.$extraUrl);
845
            } catch (Exception $exception) {
846
                Display::addFlash(
847
                    Display::return_message($exception->getMessage(), 'error')
848
                );
849
            }
850
        } else {
851
            $form->setDefaults(
852
                [
853
                    'duration' => 60,
854
                    'userRegistration' => 'RegisterAllCourseUsers',
855
                ]
856
            );
857
        }
858
859
        return $form;
860
    }
861
862
    /**
863
     * Return the current global meeting (create it if needed).
864
     *
865
     * @throws Exception
866
     *
867
     * @return string
868
     */
869
    public function getGlobalMeeting()
870
    {
871
        foreach ($this->getMeetingRepository()->unfinishedGlobalMeetings() as $meeting) {
872
            return $meeting;
873
        }
874
875
        return $this->createGlobalMeeting();
876
    }
877
878
    /**
879
     * @return MeetingRepository|EntityRepository
880
     */
881
    public static function getMeetingRepository()
882
    {
883
        return Database::getManager()->getRepository(Meeting::class);
884
    }
885
886
    /**
887
     * Returns the URL to enter (start or join) a meeting or null if not possible to enter the meeting,
888
     * The returned URL depends on the meeting current status (waiting, started or finished) and the current user.
889
     *
890
     * @param Meeting $meeting
891
     *
892
     * @throws OptimisticLockException
893
     * @throws Exception
894
     *
895
     * @return string|null
896
     */
897
    public function getStartOrJoinMeetingURL($meeting)
898
    {
899
        $status = $meeting->getMeetingInfoGet()->status;
900
        $userId = api_get_user_id();
901
        $currentUser = api_get_user_entity($userId);
902
        $isGlobal = 'true' === $this->get('enableGlobalConference') && $meeting->isGlobalMeeting();
903
904
        switch ($status) {
905
            case 'ended':
906
                if ($this->userIsConferenceManager($meeting)) {
907
                    return $meeting->getMeetingInfoGet()->start_url;
908
                }
909
                break;
910
            case 'waiting':
911
                // Zoom does not allow for a new meeting to be started on first participant join.
912
                // It requires the host to start the meeting first.
913
                // Therefore for global meetings we must make the first participant the host
914
                // that is use start_url rather than join_url.
915
                // the participant will not be registered and will appear as the Zoom user account owner.
916
                // For course and user meetings, only the host can start the meeting.
917
                if ($this->userIsConferenceManager($meeting)) {
918
                    return $meeting->getMeetingInfoGet()->start_url;
919
                }
920
921
                break;
922
            case 'started':
923
                // User per conference.
924
                if ($currentUser === $meeting->getUser()) {
925
                    return $meeting->getMeetingInfoGet()->join_url;
926
                }
927
928
                // The participant is not registered, he can join only the global meeting (automatic registration).
929
                if ($isGlobal) {
930
                    return $this->registerUser($meeting, $currentUser)->getCreatedRegistration()->join_url;
931
                }
932
933
                if ($meeting->isCourseMeeting()) {
934
                    if ($this->userIsCourseConferenceManager()) {
935
                        return $meeting->getMeetingInfoGet()->start_url;
936
                    }
937
938
                    $sessionId = api_get_session_id();
939
                    $courseCode = api_get_course_id();
940
941
                    if (empty($sessionId)) {
942
                        $isSubscribed = CourseManager::is_user_subscribed_in_course(
943
                            $userId,
944
                            $courseCode,
945
                            false
946
                        );
947
                    } else {
948
                        $isSubscribed = CourseManager::is_user_subscribed_in_course(
949
                            $userId,
950
                            $courseCode,
951
                            true,
952
                            $sessionId
953
                        );
954
                    }
955
956
                    if ($isSubscribed) {
957
                        if ($meeting->isCourseGroupMeeting()) {
958
                            $groupInfo = GroupManager::get_group_properties($meeting->getGroup()->getIid(), true);
959
                            $isInGroup = GroupManager::is_user_in_group($userId, $groupInfo);
960
                            if (false === $isInGroup) {
961
                                throw new Exception($this->get_lang('YouAreNotRegisteredToThisMeeting'));
962
                            }
963
                        }
964
965
                        if (\Chamilo\PluginBundle\Zoom\API\Meeting::TYPE_INSTANT == $meeting->getMeetingInfoGet()->type) {
966
                            return $meeting->getMeetingInfoGet()->join_url;
967
                        }
968
969
                        return $this->registerUser($meeting, $currentUser)->getCreatedRegistration()->join_url;
970
                    }
971
972
                    throw new Exception($this->get_lang('YouAreNotRegisteredToThisMeeting'));
973
                }
974
975
                //if ('true' === $this->get('enableParticipantRegistration')) {
976
                    //if ('true' === $this->get('enableParticipantRegistration') && $meeting->requiresRegistration()) {
977
                    // the participant must be registered
978
                    $registrant = $meeting->getRegistrant($currentUser);
979
                    if (null == $registrant) {
980
                        throw new Exception($this->get_lang('YouAreNotRegisteredToThisMeeting'));
981
                    }
982
983
                    // the participant is registered
984
                    return $registrant->getCreatedRegistration()->join_url;
985
                //}
986
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
987
        }
988
989
        return null;
990
    }
991
992
    /**
993
     * @param Meeting $meeting
994
     *
995
     * @return bool whether the logged-in user can manage conferences in this context, that is either
996
     *              the current course or session coach, the platform admin or the current course admin
997
     */
998
    public function userIsConferenceManager($meeting)
999
    {
1000
        if (null === $meeting) {
1001
            return false;
1002
        }
1003
1004
        if (api_is_coach() || api_is_platform_admin()) {
1005
            return true;
1006
        }
1007
1008
        if ($meeting->isCourseMeeting() && api_get_course_id() && api_is_course_admin()) {
1009
            return true;
1010
        }
1011
1012
        return $meeting->isUserMeeting() && $meeting->getUser()->getId() == api_get_user_id();
1013
    }
1014
1015
    /**
1016
     * @return bool whether the logged-in user can manage conferences in this context, that is either
1017
     *              the current course or session coach, the platform admin or the current course admin
1018
     */
1019
    public function userIsCourseConferenceManager()
1020
    {
1021
        if (api_is_coach() || api_is_platform_admin()) {
1022
            return true;
1023
        }
1024
1025
        if (api_get_course_id() && api_is_course_admin()) {
1026
            return true;
1027
        }
1028
1029
        return false;
1030
    }
1031
1032
    /**
1033
     * Update local recording list from remote Zoom server's version.
1034
     * Kept to implement a future administration button ("import existing data from zoom server").
1035
     *
1036
     * @param DateTime $startDate
1037
     * @param DateTime $endDate
1038
     *
1039
     * @throws OptimisticLockException
1040
     * @throws Exception
1041
     */
1042
    public function reloadPeriodRecordings($startDate, $endDate)
1043
    {
1044
        $em = Database::getManager();
1045
        $recordingRepo = $this->getRecordingRepository();
1046
        $meetingRepo = $this->getMeetingRepository();
1047
        $recordings = RecordingList::loadPeriodRecordings($startDate, $endDate);
1048
1049
        foreach ($recordings as $recordingMeeting) {
1050
            $recordingEntity = $recordingRepo->findOneBy(['uuid' => $recordingMeeting->uuid]);
1051
            if (null === $recordingEntity) {
1052
                $recordingEntity = new Recording();
1053
                $meeting = $meetingRepo->findOneBy(['meetingId' => $recordingMeeting->id]);
1054
                if (null === $meeting) {
1055
                    try {
1056
                        $meetingInfoGet = MeetingInfoGet::fromId($recordingMeeting->id);
1057
                    } catch (Exception $exception) {
1058
                        $meetingInfoGet = null; // deleted meeting with recordings
1059
                    }
1060
                    if (null !== $meetingInfoGet) {
1061
                        $meeting = $this->createMeetingFromMeeting(
1062
                            (new Meeting())->setMeetingInfoGet($meetingInfoGet)
1063
                        );
1064
                        $em->persist($meeting);
1065
                    }
1066
                }
1067
                if (null !== $meeting) {
1068
                    $recordingEntity->setMeeting($meeting);
1069
                }
1070
            }
1071
            $recordingEntity->setRecordingMeeting($recordingMeeting);
1072
            $em->persist($recordingEntity);
1073
        }
1074
        $em->flush();
1075
    }
1076
1077
    /**
1078
     * @return RecordingRepository|EntityRepository
1079
     */
1080
    public static function getRecordingRepository()
1081
    {
1082
        return Database::getManager()->getRepository(Recording::class);
1083
    }
1084
1085
    public function getToolbar($returnUrl = '')
1086
    {
1087
        if (!api_is_platform_admin()) {
1088
            return '';
1089
        }
1090
1091
        $actionsLeft = '';
1092
        $back = '';
1093
        $courseId = api_get_course_id();
1094
        if (empty($courseId)) {
1095
            $actionsLeft .=
1096
                Display::url(
1097
                    Display::return_icon('bbb.png', $this->get_lang('Meetings'), null, ICON_SIZE_MEDIUM),
1098
                    api_get_path(WEB_PLUGIN_PATH).'zoom/meetings.php'
1099
                );
1100
        } else {
1101
            $actionsLeft .=
1102
                Display::url(
1103
                    Display::return_icon('bbb.png', $this->get_lang('Meetings'), null, ICON_SIZE_MEDIUM),
1104
                    api_get_path(WEB_PLUGIN_PATH).'zoom/start.php?'.api_get_cidreq()
1105
                );
1106
        }
1107
1108
        if (!empty($returnUrl)) {
1109
            $back = Display::url(
1110
                Display::return_icon('back.png', get_lang('Back'), null, ICON_SIZE_MEDIUM),
1111
                $returnUrl
1112
            );
1113
        }
1114
1115
        if (api_is_platform_admin()) {
1116
            $actionsLeft .=
1117
                Display::url(
1118
                    Display::return_icon('settings.png', get_lang('Settings'), null, ICON_SIZE_MEDIUM),
1119
                    api_get_path(WEB_CODE_PATH).'admin/configure_plugin.php?name=zoom'
1120
                ).$back;
1121
        }
1122
1123
        return Display::toolbarAction('toolbar', [$actionsLeft]);
1124
    }
1125
1126
    public function getRecordingSetting()
1127
    {
1128
        $recording = (string) $this->get('enableCloudRecording');
1129
1130
        if (in_array($recording, [self::RECORDING_TYPE_LOCAL, self::RECORDING_TYPE_CLOUD], true)) {
1131
            return $recording;
1132
        }
1133
1134
        return self::RECORDING_TYPE_NONE;
1135
    }
1136
1137
    public function hasRecordingAvailable()
1138
    {
1139
        $recording = $this->getRecordingSetting();
1140
1141
        return self::RECORDING_TYPE_NONE !== $recording;
1142
    }
1143
1144
    /**
1145
     * Updates meeting registrants list. Adds the missing registrants and removes the extra.
1146
     *
1147
     * @param Meeting $meeting
1148
     * @param User[]  $users   list of users to be registered
1149
     *
1150
     * @throws Exception
1151
     */
1152
    private function updateRegistrantList($meeting, $users)
1153
    {
1154
        $usersToAdd = [];
1155
        foreach ($users as $user) {
1156
            $found = false;
1157
            foreach ($meeting->getRegistrants() as $registrant) {
1158
                if ($registrant->getUser() === $user) {
1159
                    $found = true;
1160
                    break;
1161
                }
1162
            }
1163
            if (!$found) {
1164
                $usersToAdd[] = $user;
1165
            }
1166
        }
1167
        $registrantsToRemove = [];
1168
        foreach ($meeting->getRegistrants() as $registrant) {
1169
            $found = false;
1170
            foreach ($users as $user) {
1171
                if ($registrant->getUser() === $user) {
1172
                    $found = true;
1173
                    break;
1174
                }
1175
            }
1176
            if (!$found) {
1177
                $registrantsToRemove[] = $registrant;
1178
            }
1179
        }
1180
        $this->registerUsers($meeting, $usersToAdd);
1181
        $this->unregister($meeting, $registrantsToRemove);
1182
    }
1183
1184
    /**
1185
     * Register users to a meeting.
1186
     *
1187
     * @param Meeting $meeting
1188
     * @param User[]  $users
1189
     *
1190
     * @throws OptimisticLockException
1191
     *
1192
     * @return User[] failed registrations [ user id => errorMessage ]
1193
     */
1194
    private function registerUsers($meeting, $users)
1195
    {
1196
        $failedUsers = [];
1197
        foreach ($users as $user) {
1198
            try {
1199
                $this->registerUser($meeting, $user, false);
1200
            } catch (Exception $exception) {
1201
                $failedUsers[$user->getId()] = $exception->getMessage();
1202
            }
1203
        }
1204
        Database::getManager()->flush();
1205
1206
        return $failedUsers;
1207
    }
1208
1209
    /**
1210
     * @throws Exception
1211
     * @throws OptimisticLockException
1212
     *
1213
     * @return Registrant
1214
     */
1215
    private function registerUser(Meeting $meeting, User $user, $andFlush = true)
1216
    {
1217
        if (empty($user->getEmail())) {
1218
            throw new Exception($this->get_lang('CannotRegisterWithoutEmailAddress'));
1219
        }
1220
1221
        $meetingRegistrant = MeetingRegistrant::fromEmailAndFirstName(
1222
            $user->getEmail(),
1223
            $user->getFirstname(),
1224
            $user->getLastname()
1225
        );
1226
1227
        $registrantEntity = (new Registrant())
1228
            ->setMeeting($meeting)
1229
            ->setUser($user)
1230
            ->setMeetingRegistrant($meetingRegistrant)
1231
            ->setCreatedRegistration($meeting->getMeetingInfoGet()->addRegistrant($meetingRegistrant));
1232
        Database::getManager()->persist($registrantEntity);
1233
1234
        if ($andFlush) {
1235
            Database::getManager()->flush($registrantEntity);
1236
        }
1237
1238
        return $registrantEntity;
1239
    }
1240
1241
    /**
1242
     * Removes registrants from a meeting.
1243
     *
1244
     * @param Meeting      $meeting
1245
     * @param Registrant[] $registrants
1246
     *
1247
     * @throws Exception
1248
     */
1249
    private function unregister($meeting, $registrants)
1250
    {
1251
        $meetingRegistrants = [];
1252
        foreach ($registrants as $registrant) {
1253
            $meetingRegistrants[] = $registrant->getMeetingRegistrant();
1254
        }
1255
        $meeting->getMeetingInfoGet()->removeRegistrants($meetingRegistrants);
1256
        $em = Database::getManager();
1257
        foreach ($registrants as $registrant) {
1258
            $em->remove($registrant);
1259
        }
1260
        $em->flush();
1261
    }
1262
1263
    /**
1264
     * Starts a new instant meeting and redirects to its start url.
1265
     *
1266
     * @param string          $topic
1267
     * @param User|null       $user
1268
     * @param Course|null     $course
1269
     * @param CGroupInfo|null $group
1270
     * @param Session|null    $session
1271
     *
1272
     * @throws Exception
1273
     */
1274
    private function startInstantMeeting($topic, $user = null, $course = null, $group = null, $session = null)
1275
    {
1276
        $meetingInfoGet = MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_INSTANT);
1277
        //$meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE;
1278
        $meeting = $this->createMeetingFromMeeting(
1279
            (new Meeting())
1280
                ->setMeetingInfoGet($meetingInfoGet)
1281
                ->setUser($user)
1282
                ->setGroup($group)
1283
                ->setCourse($course)
1284
                ->setSession($session)
1285
        );
1286
        api_location($meeting->getMeetingInfoGet()->start_url);
1287
    }
1288
1289
    /**
1290
     * Creates a meeting on Zoom servers and stores it in the local database.
1291
     *
1292
     * @param Meeting $meeting a new, unsaved meeting with at least a type and a topic
1293
     *
1294
     * @throws Exception
1295
     *
1296
     * @return Meeting
1297
     */
1298
    private function createMeetingFromMeeting($meeting)
1299
    {
1300
        $currentUser = api_get_user_entity(api_get_user_id());
1301
1302
        $meeting->getMeetingInfoGet()->settings->contact_email = $currentUser->getEmail();
1303
        $meeting->getMeetingInfoGet()->settings->contact_name = $currentUser->getFullname();
1304
        $meeting->getMeetingInfoGet()->settings->auto_recording = $this->getRecordingSetting();
1305
        $meeting->getMeetingInfoGet()->settings->registrants_email_notification = false;
1306
1307
        //$meeting->getMeetingInfoGet()->host_email = $currentUser->getEmail();
1308
        //$meeting->getMeetingInfoGet()->settings->alternative_hosts = $currentUser->getEmail();
1309
1310
        // Send create to Zoom.
1311
        $meeting->setMeetingInfoGet($meeting->getMeetingInfoGet()->create());
1312
1313
        Database::getManager()->persist($meeting);
1314
        Database::getManager()->flush();
1315
1316
        return $meeting;
1317
    }
1318
1319
    /**
1320
     * @throws Exception
1321
     *
1322
     * @return Meeting
1323
     */
1324
    private function createGlobalMeeting()
1325
    {
1326
        $meetingInfoGet = MeetingInfoGet::fromTopicAndType(
1327
            $this->get_lang('GlobalMeeting'),
1328
            MeetingInfoGet::TYPE_SCHEDULED
1329
        );
1330
        $meetingInfoGet->start_time = (new DateTime())->format(DateTimeInterface::ISO8601);
1331
        $meetingInfoGet->duration = 60;
1332
        $meetingInfoGet->settings->approval_type =
1333
            ('true' === $this->get('enableParticipantRegistration'))
1334
                ? MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE
1335
                : MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED;
1336
        // $meetingInfoGet->settings->host_video = true;
1337
        $meetingInfoGet->settings->participant_video = true;
1338
        $meetingInfoGet->settings->join_before_host = true;
1339
        $meetingInfoGet->settings->registrants_email_notification = false;
1340
1341
        return $this->createMeetingFromMeeting((new Meeting())->setMeetingInfoGet($meetingInfoGet));
1342
    }
1343
1344
    /**
1345
     * Schedules a meeting and returns it.
1346
     * set $course, $session and $user to null in order to create a global meeting.
1347
     *
1348
     * @param DateTime $startTime meeting local start date-time (configure local timezone on your Zoom account)
1349
     * @param int      $duration  in minutes
1350
     * @param string   $topic     short title of the meeting, required
1351
     * @param string   $agenda    ordre du jour
1352
     * @param string   $password  meeting password
1353
     *
1354
     * @throws Exception
1355
     *
1356
     * @return Meeting meeting
1357
     */
1358
    private function createScheduleMeeting(
1359
        User $user = null,
1360
        Course $course = null,
1361
        CGroupInfo $group = null,
1362
        Session $session = null,
1363
        $startTime,
1364
        $duration,
1365
        $topic,
1366
        $agenda,
1367
        $password
1368
    ) {
1369
        $meetingInfoGet = MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_SCHEDULED);
1370
        $meetingInfoGet->duration = $duration;
1371
        $meetingInfoGet->start_time = $startTime->format(DateTimeInterface::ISO8601);
1372
        $meetingInfoGet->agenda = $agenda;
1373
        $meetingInfoGet->password = $password;
1374
        $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED;
1375
        if ('true' === $this->get('enableParticipantRegistration')) {
1376
            $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE;
1377
        }
1378
1379
        return $this->createMeetingFromMeeting(
1380
            (new Meeting())
1381
                ->setMeetingInfoGet($meetingInfoGet)
1382
                ->setUser($user)
1383
                ->setCourse($course)
1384
                ->setGroup($group)
1385
                ->setSession($session)
1386
        );
1387
    }
1388
1389
    /**
1390
     * Registers all the course users to a course meeting.
1391
     *
1392
     * @param Meeting $meeting
1393
     *
1394
     * @throws OptimisticLockException
1395
     */
1396
    private function registerAllCourseUsers($meeting)
1397
    {
1398
        $this->registerUsers($meeting, $meeting->getRegistrableUsers());
1399
    }
1400
}
1401