Passed
Push — 1.11.x ( 930aea...109371 )
by Julito
12:53
created

ZoomPlugin::createScheduleMeeting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 15
c 1
b 0
f 1
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
    public $isCoursePlugin = true;
33
34
    /**
35
     * @var JWTClient
36
     */
37
    private $jwtClient;
38
39
    const RECORDING_TYPE_CLOUD = 'cloud';
40
    const RECORDING_TYPE_LOCAL = 'local';
41
    const RECORDING_TYPE_NONE = 'none';
42
43
    /**
44
     * ZoomPlugin constructor.
45
     * {@inheritdoc}
46
     * Initializes the API JWT client and the entity repositories.
47
     */
48
    public function __construct()
49
    {
50
        parent::__construct(
51
            '0.3',
52
            'Sébastien Ducoulombier, Julio Montoya',
53
            [
54
                'tool_enable' => 'boolean',
55
                'apiKey' => 'text',
56
                'apiSecret' => 'text',
57
                'verificationToken' => 'text',
58
                'enableParticipantRegistration' => 'boolean',
59
                'enableCloudRecording' => [
60
                    'type' => 'select',
61
                    'options' => [
62
                        self::RECORDING_TYPE_CLOUD => 'Cloud',
63
                        self::RECORDING_TYPE_LOCAL => 'Local',
64
                        self::RECORDING_TYPE_NONE => get_lang('None'),
65
                    ],
66
                ],
67
                'enableGlobalConference' => 'boolean',
68
                'globalConferenceAllowRoles' => [
69
                    'type' => 'select',
70
                    'options' => [
71
                        PLATFORM_ADMIN => get_lang('Administrator'),
72
                        COURSEMANAGER => get_lang('Teacher'),
73
                        STUDENT => get_lang('Student'),
74
                        STUDENT_BOSS => get_lang('StudentBoss'),
75
                    ],
76
                    'attributes' => ['multiple' => 'multiple'],
77
                ],
78
            ]
79
        );
80
81
        $this->isAdminPlugin = true;
82
        $this->jwtClient = new JWTClient($this->get('apiKey'), $this->get('apiSecret'));
83
    }
84
85
    /**
86
     * Caches and returns an instance of this class.
87
     *
88
     * @return ZoomPlugin the instance to use
89
     */
90
    public static function create()
91
    {
92
        static $instance = null;
93
94
        return $instance ? $instance : $instance = new self();
95
    }
96
97
    /**
98
     * @return bool
99
     */
100
    public static function currentUserCanJoinGlobalMeeting()
101
    {
102
        $user = api_get_user_entity(api_get_user_id());
103
104
        if (null === $user) {
105
            return false;
106
        }
107
108
        //return 'true' === api_get_plugin_setting('zoom', 'enableGlobalConference') && api_user_is_login();
109
        return
110
            'true' === api_get_plugin_setting('zoom', 'enableGlobalConference')
111
            && in_array(
112
                (api_is_platform_admin() ? PLATFORM_ADMIN : $user->getStatus()),
113
                (array) api_get_plugin_setting('zoom', 'globalConferenceAllowRoles')
114
            );
115
    }
116
117
    /**
118
     * @return array
119
     */
120
    public function getProfileBlockItems()
121
    {
122
        $elements = $this->meetingsToWhichCurrentUserIsRegisteredComingSoon();
123
        $addMeetingLink = false;
124
        if (self::currentUserCanJoinGlobalMeeting()) {
125
            $addMeetingLink = true;
126
        }
127
128
        if ($addMeetingLink) {
129
            $elements[$this->get_lang('Meetings')] = api_get_path(WEB_PLUGIN_PATH).'zoom/meetings.php';
130
        }
131
132
        $items = [];
133
        foreach ($elements as $title => $link) {
134
            $items[] = [
135
                'class' => 'video-conference',
136
                'icon' => Display::return_icon(
137
                    'bbb.png',
138
                    get_lang('VideoConference')
139
                ),
140
                'link' => $link,
141
                'title' => $title,
142
            ];
143
        }
144
145
        return $items;
146
    }
147
148
    /**
149
     * @return array [ $title => $link ]
150
     */
151
    public function meetingsToWhichCurrentUserIsRegisteredComingSoon()
152
    {
153
        $linkTemplate = api_get_path(WEB_PLUGIN_PATH).'zoom/join_meeting.php?meetingId=%s';
154
        $user = api_get_user_entity(api_get_user_id());
155
        $meetings = self::getRegistrantRepository()->meetingsComingSoonRegistrationsForUser($user);
156
        $items = [];
157
        foreach ($meetings as $registrant) {
158
            $meeting = $registrant->getMeeting();
159
            $items[sprintf(
160
                $this->get_lang('DateMeetingTitle'),
161
                $meeting->formattedStartTime,
162
                $meeting->getMeetingInfoGet()->topic
163
            )] = sprintf($linkTemplate, $meeting->getId());
164
        }
165
166
        return $items;
167
    }
168
169
    /**
170
     * @return RegistrantRepository|EntityRepository
171
     */
172
    public static function getRegistrantRepository()
173
    {
174
        return Database::getManager()->getRepository(Registrant::class);
175
    }
176
177
    /**
178
     * Creates this plugin's related tables in the internal database.
179
     * Installs course fields in all courses.
180
     *
181
     * @throws ToolsException
182
     */
183
    public function install()
184
    {
185
        (new SchemaTool(Database::getManager()))->createSchema(
186
            [
187
                Database::getManager()->getClassMetadata(Meeting::class),
188
                Database::getManager()->getClassMetadata(MeetingActivity::class),
189
                Database::getManager()->getClassMetadata(Recording::class),
190
                Database::getManager()->getClassMetadata(Registrant::class),
191
            ]
192
        );
193
        $this->install_course_fields_in_all_courses();
194
    }
195
196
    /**
197
     * Drops this plugins' related tables from the internal database.
198
     * Uninstalls course fields in all courses().
199
     */
200
    public function uninstall()
201
    {
202
        (new SchemaTool(Database::getManager()))->dropSchema(
203
            [
204
                Database::getManager()->getClassMetadata(Meeting::class),
205
                Database::getManager()->getClassMetadata(MeetingActivity::class),
206
                Database::getManager()->getClassMetadata(Recording::class),
207
                Database::getManager()->getClassMetadata(Registrant::class),
208
            ]
209
        );
210
        $this->uninstall_course_fields_in_all_courses();
211
    }
212
213
    /**
214
     * Generates the search form to include in the meeting list administration page.
215
     * The form has DatePickers 'start' and 'end' and Checkbox 'reloadRecordingLists'.
216
     *
217
     * @return FormValidator the form
218
     */
219
    public function getAdminSearchForm()
220
    {
221
        $form = new FormValidator('search');
222
        $form->addHeader($this->get_lang('SearchMeeting'));
223
        $form->addDatePicker('start', get_lang('StartDate'));
224
        $form->addDatePicker('end', get_lang('EndDate'));
225
        $form->addButtonSearch(get_lang('Search'));
226
        $oneMonth = new DateInterval('P1M');
227
        if ($form->validate()) {
228
            try {
229
                $start = new DateTime($form->getSubmitValue('start'));
230
            } catch (Exception $exception) {
231
                $start = new DateTime();
232
                $start->sub($oneMonth);
233
            }
234
            try {
235
                $end = new DateTime($form->getSubmitValue('end'));
236
            } catch (Exception $exception) {
237
                $end = new DateTime();
238
                $end->add($oneMonth);
239
            }
240
        } else {
241
            $start = new DateTime();
242
            $start->sub($oneMonth);
243
            $end = new DateTime();
244
            $end->add($oneMonth);
245
        }
246
        try {
247
            $form->setDefaults(
248
                [
249
                    'start' => $start->format('Y-m-d'),
250
                    'end' => $end->format('Y-m-d'),
251
                ]
252
            );
253
        } catch (Exception $exception) {
254
            error_log(join(':', [__FILE__, __LINE__, $exception]));
255
        }
256
257
        return $form;
258
    }
259
260
    /**
261
     * Generates a meeting edit form and updates the meeting on validation.
262
     *
263
     * @param Meeting $meeting the meeting
264
     *
265
     * @throws Exception
266
     *
267
     * @return FormValidator
268
     */
269
    public function getEditMeetingForm($meeting)
270
    {
271
        $meetingInfoGet = $meeting->getMeetingInfoGet();
272
        $form = new FormValidator('edit', 'post', $_SERVER['REQUEST_URI']);
273
        $form->addHeader($this->get_lang('UpdateMeeting'));
274
        $form->addText('topic', $this->get_lang('Topic'));
275
        if ($meeting->requiresDateAndDuration()) {
276
            $startTimeDatePicker = $form->addDateTimePicker('startTime', get_lang('StartTime'));
277
            $form->setRequired($startTimeDatePicker);
278
            $durationNumeric = $form->addNumeric('duration', $this->get_lang('DurationInMinutes'));
279
            $form->setRequired($durationNumeric);
280
        }
281
        $form->addTextarea('agenda', get_lang('Agenda'), ['maxlength' => 2000]);
282
        //$form->addLabel(get_lang('Password'), $meeting->getMeetingInfoGet()->password);
283
        // $form->addText('password', get_lang('Password'), false, ['maxlength' => '10']);
284
        $form->addButtonUpdate(get_lang('Update'));
285
        if ($form->validate()) {
286
            if ($meeting->requiresDateAndDuration()) {
287
                $meetingInfoGet->start_time = (new DateTime($form->getSubmitValue('startTime')))->format(
288
                    DateTimeInterface::ISO8601
289
                );
290
                $meetingInfoGet->timezone = date_default_timezone_get();
291
                $meetingInfoGet->duration = (int) $form->getSubmitValue('duration');
292
            }
293
            $meetingInfoGet->topic = $form->getSubmitValue('topic');
294
            $meetingInfoGet->agenda = $form->getSubmitValue('agenda');
295
            try {
296
                $meetingInfoGet->update();
297
                $meeting->setMeetingInfoGet($meetingInfoGet);
298
                Database::getManager()->persist($meeting);
299
                Database::getManager()->flush();
300
                Display::addFlash(
301
                    Display::return_message($this->get_lang('MeetingUpdated'), 'confirm')
302
                );
303
            } catch (Exception $exception) {
304
                Display::addFlash(
305
                    Display::return_message($exception->getMessage(), 'error')
306
                );
307
            }
308
        }
309
        $defaults = [
310
            'topic' => $meetingInfoGet->topic,
311
            'agenda' => $meetingInfoGet->agenda,
312
        ];
313
        if ($meeting->requiresDateAndDuration()) {
314
            $defaults['startTime'] = $meeting->startDateTime->format('Y-m-d H:i');
315
            $defaults['duration'] = $meetingInfoGet->duration;
316
        }
317
        $form->setDefaults($defaults);
318
319
        return $form;
320
    }
321
322
    /**
323
     * Generates a meeting delete form and deletes the meeting on validation.
324
     *
325
     * @param Meeting $meeting
326
     * @param string  $returnURL where to redirect to on successful deletion
327
     *
328
     * @throws Exception
329
     *
330
     * @return FormValidator
331
     */
332
    public function getDeleteMeetingForm($meeting, $returnURL)
333
    {
334
        $id = $meeting->getMeetingId();
335
        $form = new FormValidator('delete', 'post', api_get_self().'?meetingId='.$id);
336
        $form->addButtonDelete($this->get_lang('DeleteMeeting'));
337
        if ($form->validate()) {
338
            $this->deleteMeeting($meeting, $returnURL);
339
        }
340
341
        return $form;
342
    }
343
344
    /**
345
     * @param Meeting $meeting
346
     * @param string  $returnURL
347
     *
348
     * @return false
349
     */
350
    public function deleteMeeting($meeting, $returnURL)
351
    {
352
        if (null === $meeting) {
353
            return false;
354
        }
355
356
        $em = Database::getManager();
357
        try {
358
            // No need to delete a instant meeting.
359
            if (\Chamilo\PluginBundle\Zoom\API\Meeting::TYPE_INSTANT != $meeting->getMeetingInfoGet()->type) {
360
                $meeting->getMeetingInfoGet()->delete();
361
            }
362
363
            $em->remove($meeting);
364
            $em->flush();
365
366
            Display::addFlash(
367
                Display::return_message($this->get_lang('MeetingDeleted'), 'confirm')
368
            );
369
            api_location($returnURL);
370
        } catch (Exception $exception) {
371
            $this->handleException($exception);
372
        }
373
    }
374
375
    /**
376
     * @param Exception $exception
377
     */
378
    public function handleException($exception)
379
    {
380
        if ($exception instanceof Exception) {
0 ignored issues
show
introduced by
$exception is always a sub-type of Exception.
Loading history...
381
            $error = json_decode($exception->getMessage());
382
            $message = $exception->getMessage();
383
            if ($error->message) {
384
                $message = $error->message;
385
            }
386
            Display::addFlash(
387
                Display::return_message($message, 'error')
388
            );
389
        }
390
    }
391
392
    /**
393
     * Generates a registrant list update form listing course and session users.
394
     * Updates the list on validation.
395
     *
396
     * @param Meeting $meeting
397
     *
398
     * @throws Exception
399
     *
400
     * @return FormValidator
401
     */
402
    public function getRegisterParticipantForm($meeting)
403
    {
404
        $form = new FormValidator('register', 'post', $_SERVER['REQUEST_URI']);
405
        $userIdSelect = $form->addSelect('userIds', $this->get_lang('RegisteredUsers'));
406
        $userIdSelect->setMultiple(true);
407
        $form->addButtonSend($this->get_lang('UpdateRegisteredUserList'));
408
409
        $users = $meeting->getRegistrableUsers();
410
        foreach ($users as $user) {
411
            $userIdSelect->addOption(
412
                api_get_person_name($user->getFirstname(), $user->getLastname()),
413
                $user->getId()
414
            );
415
        }
416
417
        if ($form->validate()) {
418
            $selectedUserIds = $form->getSubmitValue('userIds');
419
            $selectedUsers = [];
420
            if (!empty($selectedUserIds)) {
421
                foreach ($users as $user) {
422
                    if (in_array($user->getId(), $selectedUserIds)) {
423
                        $selectedUsers[] = $user;
424
                    }
425
                }
426
            }
427
428
            try {
429
                $this->updateRegistrantList($meeting, $selectedUsers);
430
                Display::addFlash(
431
                    Display::return_message($this->get_lang('RegisteredUserListWasUpdated'), 'confirm')
432
                );
433
            } catch (Exception $exception) {
434
                Display::addFlash(
435
                    Display::return_message($exception->getMessage(), 'error')
436
                );
437
            }
438
        }
439
        $registeredUserIds = [];
440
        foreach ($meeting->getRegistrants() as $registrant) {
441
            $registeredUserIds[] = $registrant->getUser()->getId();
442
        }
443
        $userIdSelect->setSelected($registeredUserIds);
444
445
        return $form;
446
    }
447
448
    /**
449
     * Generates a meeting recording files management form.
450
     * Takes action on validation.
451
     *
452
     * @param Meeting $meeting
453
     *
454
     * @throws Exception
455
     *
456
     * @return FormValidator
457
     */
458
    public function getFileForm($meeting, $returnURL)
459
    {
460
        $form = new FormValidator('fileForm', 'post', $_SERVER['REQUEST_URI']);
461
        if (!$meeting->getRecordings()->isEmpty()) {
462
            $fileIdSelect = $form->addSelect('fileIds', get_lang('Files'));
463
            $fileIdSelect->setMultiple(true);
464
            $recordingList = $meeting->getRecordings();
465
            foreach ($recordingList as &$recording) {
466
                // $recording->instanceDetails = $plugin->getPastMeetingInstanceDetails($instance->uuid);
467
                $options = [];
468
                $recordings = $recording->getRecordingMeeting()->recording_files;
469
                foreach ($recordings as $file) {
470
                    $options[] = [
471
                        'text' => sprintf(
472
                            '%s.%s (%s)',
473
                            $file->recording_type,
474
                            $file->file_type,
475
                            $file->file_size
476
                        ),
477
                        'value' => $file->id,
478
                    ];
479
                }
480
                $fileIdSelect->addOptGroup(
481
                    $options,
482
                    sprintf("%s (%s)", $recording->formattedStartTime, $recording->formattedDuration)
483
                );
484
            }
485
            $actions = [];
486
            if ($meeting->isCourseMeeting()) {
487
                $actions['CreateLinkInCourse'] = $this->get_lang('CreateLinkInCourse');
488
                $actions['CopyToCourse'] = $this->get_lang('CopyToCourse');
489
            }
490
            $actions['DeleteFile'] = $this->get_lang('DeleteFile');
491
            $form->addRadio(
492
                'action',
493
                get_lang('Action'),
494
                $actions
495
            );
496
            $form->addButtonUpdate($this->get_lang('DoIt'));
497
            if ($form->validate()) {
498
                $action = $form->getSubmitValue('action');
499
                $idList = $form->getSubmitValue('fileIds');
500
501
                foreach ($recordingList as $recording) {
502
                    $recordings = $recording->getRecordingMeeting()->recording_files;
503
504
                    foreach ($recordings as $file) {
505
                        if (in_array($file->id, $idList)) {
506
                            $name = sprintf(
507
                                $this->get_lang('XRecordingOfMeetingXFromXDurationXDotX'),
508
                                $file->recording_type,
509
                                $meeting->getId(),
510
                                $recording->formattedStartTime,
511
                                $recording->formattedDuration,
512
                                $file->file_type
513
                            );
514
                            if ('CreateLinkInCourse' === $action && $meeting->isCourseMeeting()) {
515
                                try {
516
                                    $this->createLinkToFileInCourse($meeting, $file, $name);
517
                                    Display::addFlash(
518
                                        Display::return_message(
519
                                            $this->get_lang('LinkToFileWasCreatedInCourse'),
520
                                            'success'
521
                                        )
522
                                    );
523
                                } catch (Exception $exception) {
524
                                    Display::addFlash(
525
                                        Display::return_message($exception->getMessage(), 'error')
526
                                    );
527
                                }
528
                            } elseif ('CopyToCourse' === $action && $meeting->isCourseMeeting()) {
529
                                try {
530
                                    $this->copyFileToCourse($meeting, $file, $name);
531
                                    Display::addFlash(
532
                                        Display::return_message($this->get_lang('FileWasCopiedToCourse'), 'confirm')
533
                                    );
534
                                } catch (Exception $exception) {
535
                                    Display::addFlash(
536
                                        Display::return_message($exception->getMessage(), 'error')
537
                                    );
538
                                }
539
                            } elseif ('DeleteFile' === $action) {
540
                                try {
541
                                    $name = $file->recording_type;
542
                                    $file->delete();
543
                                    Display::addFlash(
544
                                        Display::return_message($this->get_lang('FileWasDeleted').': '.$name, 'confirm')
545
                                    );
546
                                } catch (Exception $exception) {
547
                                    Display::addFlash(
548
                                        Display::return_message($exception->getMessage(), 'error')
549
                                    );
550
                                }
551
                            }
552
                        }
553
                    }
554
                }
555
                api_location($returnURL);
556
            }
557
        }
558
559
        return $form;
560
    }
561
562
    /**
563
     * Adds to the meeting course documents a link to a meeting instance recording file.
564
     *
565
     * @param Meeting       $meeting
566
     * @param RecordingFile $file
567
     * @param string        $name
568
     *
569
     * @throws Exception
570
     */
571
    public function createLinkToFileInCourse($meeting, $file, $name)
572
    {
573
        $course = $meeting->getCourse();
574
        if (null === $course) {
575
            throw new Exception('This meeting is not linked to a course');
576
        }
577
        $courseInfo = api_get_course_info_by_id($course->getId());
578
        if (empty($courseInfo)) {
579
            throw new Exception('This meeting is not linked to a valid course');
580
        }
581
        $path = '/zoom_meeting_recording_file_'.$file->id.'.'.$file->file_type;
582
        $docId = DocumentManager::addCloudLink($courseInfo, $path, $file->play_url, $name);
583
        if (!$docId) {
584
            throw new Exception(get_lang(DocumentManager::cloudLinkExists($courseInfo, $path, $file->play_url) ? 'UrlAlreadyExists' : 'ErrorAddCloudLink'));
585
        }
586
    }
587
588
    /**
589
     * Copies a recording file to a meeting's course.
590
     *
591
     * @param Meeting       $meeting
592
     * @param RecordingFile $file
593
     * @param string        $name
594
     *
595
     * @throws Exception
596
     */
597
    public function copyFileToCourse($meeting, $file, $name)
598
    {
599
        $course = $meeting->getCourse();
600
        if (null === $course) {
601
            throw new Exception('This meeting is not linked to a course');
602
        }
603
        $courseInfo = api_get_course_info_by_id($course->getId());
604
        if (empty($courseInfo)) {
605
            throw new Exception('This meeting is not linked to a valid course');
606
        }
607
        $tmpFile = tmpfile();
608
        if (false === $tmpFile) {
609
            throw new Exception('tmpfile() returned false');
610
        }
611
        $curl = curl_init($file->getFullDownloadURL($this->jwtClient->token));
612
        if (false === $curl) {
613
            throw new Exception('Could not init curl: '.curl_error($curl));
614
        }
615
        if (!curl_setopt_array(
616
            $curl,
617
            [
618
                CURLOPT_FILE => $tmpFile,
619
                CURLOPT_FOLLOWLOCATION => true,
620
                CURLOPT_MAXREDIRS => 10,
621
                CURLOPT_TIMEOUT => 120,
622
            ]
623
        )) {
624
            throw new Exception("Could not set curl options: ".curl_error($curl));
625
        }
626
        if (false === curl_exec($curl)) {
627
            throw new Exception("curl_exec failed: ".curl_error($curl));
628
        }
629
630
        $sessionId = 0;
631
        $session = $meeting->getSession();
632
        if (null !== $session) {
633
            $sessionId = $session->getId();
634
        }
635
636
        $groupId = 0;
637
        $group = $meeting->getGroup();
638
        if (null !== $group) {
639
            $groupId = $group->getIid();
640
        }
641
642
        $newPath = handle_uploaded_document(
643
            $courseInfo,
644
            [
645
                'name' => $name,
646
                'tmp_name' => stream_get_meta_data($tmpFile)['uri'],
647
                'size' => filesize(stream_get_meta_data($tmpFile)['uri']),
648
                'from_file' => true,
649
                'move_file' => true,
650
                'type' => $file->file_type,
651
            ],
652
            api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document',
653
            '/',
654
            api_get_user_id(),
655
            $groupId,
656
            null,
657
            0,
658
            'overwrite',
659
            true,
660
            false,
661
            null,
662
            $sessionId,
663
            true
664
        );
665
666
        fclose($tmpFile);
667
        if (false === $newPath) {
668
            throw new Exception('Could not handle uploaded document');
669
        }
670
    }
671
672
    /**
673
     * Generates a form to fast and easily create and start an instant meeting.
674
     * On validation, create it then redirect to it and exit.
675
     *
676
     * @return FormValidator
677
     */
678
    public function getCreateInstantMeetingForm(
679
        User $user,
680
        Course $course,
681
        CGroupInfo $group = null,
682
        Session $session = null
683
    ) {
684
        $extraUrl = '';
685
        if (!empty($course)) {
686
            $extraUrl = api_get_cidreq();
687
        }
688
        $form = new FormValidator('createInstantMeetingForm', 'post', api_get_self().'?'.$extraUrl, '_blank');
689
        $form->addButton('startButton', $this->get_lang('StartInstantMeeting'), 'video-camera', 'primary');
690
        if ($form->validate()) {
691
            try {
692
                $this->startInstantMeeting($this->get_lang('InstantMeeting'), $user, $course, $group, $session);
693
            } catch (Exception $exception) {
694
                Display::addFlash(
695
                    Display::return_message($exception->getMessage(), 'error')
696
                );
697
            }
698
        }
699
700
        return $form;
701
    }
702
703
    /**
704
     * Generates a form to schedule a meeting.
705
     * On validation, creates it and redirects to its page.
706
     *
707
     * @throws Exception
708
     *
709
     * @return FormValidator
710
     */
711
    public function getScheduleMeetingForm(User $user, Course $course = null, CGroupInfo $group = null, Session $session = null)
712
    {
713
        $extraUrl = '';
714
        if (!empty($course)) {
715
            $extraUrl = api_get_cidreq();
716
        }
717
        $form = new FormValidator('scheduleMeetingForm', 'post', api_get_self().'?'.$extraUrl);
718
        $form->addHeader($this->get_lang('ScheduleAMeeting'));
719
        $startTimeDatePicker = $form->addDateTimePicker('startTime', get_lang('StartTime'));
720
        $form->setRequired($startTimeDatePicker);
721
722
        $form->addText('topic', $this->get_lang('Topic'), true);
723
        $form->addTextarea('agenda', get_lang('Agenda'), ['maxlength' => 2000]);
724
725
        $durationNumeric = $form->addNumeric('duration', $this->get_lang('DurationInMinutes'));
726
        $form->setRequired($durationNumeric);
727
728
        if (null === $course && 'true' === $this->get('enableGlobalConference')) {
729
            $options = [];
730
            $options['everyone'] = $this->get_lang('ForEveryone');
731
            $options['registered_users'] = $this->get_lang('SomeUsers');
732
            if (!empty($options)) {
733
                if (1 === count($options)) {
734
                    $form->addHidden('type', key($options));
735
                } else {
736
                    $form->addSelect('type', $this->get_lang('ConferenceType'), $options);
737
                }
738
            }
739
        } else {
740
            // To course
741
            $form->addHidden('type', 'course');
742
        }
743
744
        /*
745
       // $passwordText = $form->addText('password', get_lang('Password'), false, ['maxlength' => '10']);
746
       if (null !== $course) {
747
           $registrationOptions = [
748
               'RegisterAllCourseUsers' => $this->get_lang('RegisterAllCourseUsers'),
749
           ];
750
           $groups = GroupManager::get_groups();
751
           if (!empty($groups)) {
752
               $registrationOptions['RegisterTheseGroupMembers'] = get_lang('RegisterTheseGroupMembers');
753
           }
754
           $registrationOptions['RegisterNoUser'] = $this->get_lang('RegisterNoUser');
755
           $userRegistrationRadio = $form->addRadio(
756
               'userRegistration',
757
               $this->get_lang('UserRegistration'),
758
               $registrationOptions
759
           );
760
           $groupOptions = [];
761
           foreach ($groups as $group) {
762
               $groupOptions[$group['id']] = $group['name'];
763
           }
764
           $groupIdsSelect = $form->addSelect(
765
               'groupIds',
766
               $this->get_lang('RegisterTheseGroupMembers'),
767
               $groupOptions
768
           );
769
           $groupIdsSelect->setMultiple(true);
770
           if (!empty($groups)) {
771
               $jsCode = sprintf(
772
                   "getElementById('%s').parentNode.parentNode.parentNode.style.display = getElementById('%s').checked ? 'block' : 'none'",
773
                   $groupIdsSelect->getAttribute('id'),
774
                   $userRegistrationRadio->getelements()[1]->getAttribute('id')
775
               );
776
777
               $form->setAttribute('onchange', $jsCode);
778
           }
779
       }*/
780
781
        $form->addButtonCreate(get_lang('Save'));
782
783
        if ($form->validate()) {
784
            $type = $form->getSubmitValue('type');
785
786
            switch ($type) {
787
                case 'everyone':
788
                    $user = null;
789
                    $group = null;
790
                    $course = null;
791
                    $session = null;
792
793
                    break;
794
                case 'registered_users':
795
                    //$user = null;
796
                    $course = null;
797
                    $session = null;
798
799
                    break;
800
                case 'course':
801
                    $user = null;
802
                    //$course = null;
803
                    //$session = null;
804
805
                    break;
806
            }
807
808
            try {
809
                $newMeeting = $this->createScheduleMeeting(
810
                    $user,
811
                    $course,
812
                    $group,
813
                    $session,
814
                    new DateTime($form->getSubmitValue('startTime')),
815
                    $form->getSubmitValue('duration'),
816
                    $form->getSubmitValue('topic'),
817
                    $form->getSubmitValue('agenda'),
818
                    substr(uniqid('z', true), 0, 10)
819
                );
820
821
                Display::addFlash(
822
                    Display::return_message($this->get_lang('NewMeetingCreated'))
823
                );
824
825
                if ($newMeeting->isCourseMeeting()) {
826
                    if ('RegisterAllCourseUsers' === $form->getSubmitValue('userRegistration')) {
827
                        $this->registerAllCourseUsers($newMeeting);
828
                        Display::addFlash(
829
                            Display::return_message($this->get_lang('AllCourseUsersWereRegistered'))
830
                        );
831
                    } elseif ('RegisterTheseGroupMembers' === $form->getSubmitValue('userRegistration')) {
832
                        $userIds = [];
833
                        foreach ($form->getSubmitValue('groupIds') as $groupId) {
834
                            $userIds = array_unique(array_merge($userIds, GroupManager::get_users($groupId)));
835
                        }
836
                        $users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy(
837
                            ['id' => $userIds]
838
                        );
839
                        $this->registerUsers($newMeeting, $users);
840
                        Display::addFlash(
841
                            Display::return_message($this->get_lang('GroupUsersWereRegistered'))
842
                        );
843
                    }
844
                }
845
                api_location('meeting.php?meetingId='.$newMeeting->getMeetingId().'&'.$extraUrl);
846
            } catch (Exception $exception) {
847
                Display::addFlash(
848
                    Display::return_message($exception->getMessage(), 'error')
849
                );
850
            }
851
        } else {
852
            $form->setDefaults(
853
                [
854
                    'duration' => 60,
855
                    'userRegistration' => 'RegisterAllCourseUsers',
856
                ]
857
            );
858
        }
859
860
        return $form;
861
    }
862
863
    /**
864
     * Return the current global meeting (create it if needed).
865
     *
866
     * @throws Exception
867
     *
868
     * @return string
869
     */
870
    public function getGlobalMeeting()
871
    {
872
        foreach ($this->getMeetingRepository()->unfinishedGlobalMeetings() as $meeting) {
873
            return $meeting;
874
        }
875
876
        return $this->createGlobalMeeting();
877
    }
878
879
    /**
880
     * @return MeetingRepository|EntityRepository
881
     */
882
    public static function getMeetingRepository()
883
    {
884
        return Database::getManager()->getRepository(Meeting::class);
885
    }
886
887
    /**
888
     * Returns the URL to enter (start or join) a meeting or null if not possible to enter the meeting,
889
     * The returned URL depends on the meeting current status (waiting, started or finished) and the current user.
890
     *
891
     * @param Meeting $meeting
892
     *
893
     * @throws OptimisticLockException
894
     * @throws Exception
895
     *
896
     * @return string|null
897
     */
898
    public function getStartOrJoinMeetingURL($meeting)
899
    {
900
        $status = $meeting->getMeetingInfoGet()->status;
901
        $userId = api_get_user_id();
902
        $currentUser = api_get_user_entity($userId);
903
        $isGlobal = 'true' === $this->get('enableGlobalConference') && $meeting->isGlobalMeeting();
904
905
        switch ($status) {
906
            case 'ended':
907
                if ($this->userIsConferenceManager($meeting)) {
908
                    return $meeting->getMeetingInfoGet()->start_url;
909
                }
910
                break;
911
            case 'waiting':
912
                // Zoom does not allow for a new meeting to be started on first participant join.
913
                // It requires the host to start the meeting first.
914
                // Therefore for global meetings we must make the first participant the host
915
                // that is use start_url rather than join_url.
916
                // the participant will not be registered and will appear as the Zoom user account owner.
917
                // For course and user meetings, only the host can start the meeting.
918
                if ($this->userIsConferenceManager($meeting)) {
919
                    return $meeting->getMeetingInfoGet()->start_url;
920
                }
921
922
                break;
923
            case 'started':
924
                // User per conference.
925
                if ($currentUser === $meeting->getUser()) {
926
                    return $meeting->getMeetingInfoGet()->join_url;
927
                }
928
929
                // The participant is not registered, he can join only the global meeting (automatic registration).
930
                if ($isGlobal) {
931
                    return $this->registerUser($meeting, $currentUser)->getCreatedRegistration()->join_url;
932
                }
933
934
                if ($meeting->isCourseMeeting()) {
935
                    if ($this->userIsCourseConferenceManager()) {
936
                        return $meeting->getMeetingInfoGet()->start_url;
937
                    }
938
939
                    $sessionId = api_get_session_id();
940
                    $courseCode = api_get_course_id();
941
942
                    if (empty($sessionId)) {
943
                        $isSubscribed = CourseManager::is_user_subscribed_in_course(
944
                            $userId,
945
                            $courseCode,
946
                            false
947
                        );
948
                    } else {
949
                        $isSubscribed = CourseManager::is_user_subscribed_in_course(
950
                            $userId,
951
                            $courseCode,
952
                            true,
953
                            $sessionId
954
                        );
955
                    }
956
957
                    if ($isSubscribed) {
958
                        if ($meeting->isCourseGroupMeeting()) {
959
                            $groupInfo = GroupManager::get_group_properties($meeting->getGroup()->getIid(), true);
960
                            $isInGroup = GroupManager::is_user_in_group($userId, $groupInfo);
961
                            if (false === $isInGroup) {
962
                                throw new Exception($this->get_lang('YouAreNotRegisteredToThisMeeting'));
963
                            }
964
                        }
965
966
                        if (\Chamilo\PluginBundle\Zoom\API\Meeting::TYPE_INSTANT == $meeting->getMeetingInfoGet()->type) {
967
                            return $meeting->getMeetingInfoGet()->join_url;
968
                        }
969
970
                        return $this->registerUser($meeting, $currentUser)->getCreatedRegistration()->join_url;
971
                    }
972
973
                    throw new Exception($this->get_lang('YouAreNotRegisteredToThisMeeting'));
974
                }
975
976
                //if ('true' === $this->get('enableParticipantRegistration')) {
977
                    //if ('true' === $this->get('enableParticipantRegistration') && $meeting->requiresRegistration()) {
978
                    // the participant must be registered
979
                    $registrant = $meeting->getRegistrant($currentUser);
980
                    if (null == $registrant) {
981
                        throw new Exception($this->get_lang('YouAreNotRegisteredToThisMeeting'));
982
                    }
983
984
                    // the participant is registered
985
                    return $registrant->getCreatedRegistration()->join_url;
986
                //}
987
                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...
988
        }
989
990
        return null;
991
    }
992
993
    /**
994
     * @param Meeting $meeting
995
     *
996
     * @return bool whether the logged-in user can manage conferences in this context, that is either
997
     *              the current course or session coach, the platform admin or the current course admin
998
     */
999
    public function userIsConferenceManager($meeting)
1000
    {
1001
        if (null === $meeting) {
1002
            return false;
1003
        }
1004
1005
        if (api_is_coach() || api_is_platform_admin()) {
1006
            return true;
1007
        }
1008
1009
        if ($meeting->isCourseMeeting() && api_get_course_id() && api_is_course_admin()) {
1010
            return true;
1011
        }
1012
1013
        return $meeting->isUserMeeting() && $meeting->getUser()->getId() == api_get_user_id();
1014
    }
1015
1016
    /**
1017
     * @return bool whether the logged-in user can manage conferences in this context, that is either
1018
     *              the current course or session coach, the platform admin or the current course admin
1019
     */
1020
    public function userIsCourseConferenceManager()
1021
    {
1022
        if (api_is_coach() || api_is_platform_admin()) {
1023
            return true;
1024
        }
1025
1026
        if (api_get_course_id() && api_is_course_admin()) {
1027
            return true;
1028
        }
1029
1030
        return false;
1031
    }
1032
1033
    /**
1034
     * Update local recording list from remote Zoom server's version.
1035
     * Kept to implement a future administration button ("import existing data from zoom server").
1036
     *
1037
     * @param DateTime $startDate
1038
     * @param DateTime $endDate
1039
     *
1040
     * @throws OptimisticLockException
1041
     * @throws Exception
1042
     */
1043
    public function reloadPeriodRecordings($startDate, $endDate)
1044
    {
1045
        $em = Database::getManager();
1046
        $recordingRepo = $this->getRecordingRepository();
1047
        $meetingRepo = $this->getMeetingRepository();
1048
        $recordings = RecordingList::loadPeriodRecordings($startDate, $endDate);
1049
1050
        foreach ($recordings as $recordingMeeting) {
1051
            $recordingEntity = $recordingRepo->findOneBy(['uuid' => $recordingMeeting->uuid]);
1052
            if (null === $recordingEntity) {
1053
                $recordingEntity = new Recording();
1054
                $meeting = $meetingRepo->findOneBy(['meetingId' => $recordingMeeting->id]);
1055
                if (null === $meeting) {
1056
                    try {
1057
                        $meetingInfoGet = MeetingInfoGet::fromId($recordingMeeting->id);
1058
                    } catch (Exception $exception) {
1059
                        $meetingInfoGet = null; // deleted meeting with recordings
1060
                    }
1061
                    if (null !== $meetingInfoGet) {
1062
                        $meeting = $this->createMeetingFromMeeting(
1063
                            (new Meeting())->setMeetingInfoGet($meetingInfoGet)
1064
                        );
1065
                        $em->persist($meeting);
1066
                    }
1067
                }
1068
                if (null !== $meeting) {
1069
                    $recordingEntity->setMeeting($meeting);
1070
                }
1071
            }
1072
            $recordingEntity->setRecordingMeeting($recordingMeeting);
1073
            $em->persist($recordingEntity);
1074
        }
1075
        $em->flush();
1076
    }
1077
1078
    /**
1079
     * @return RecordingRepository|EntityRepository
1080
     */
1081
    public static function getRecordingRepository()
1082
    {
1083
        return Database::getManager()->getRepository(Recording::class);
1084
    }
1085
1086
    public function getToolbar($returnUrl = '')
1087
    {
1088
        if (!api_is_platform_admin()) {
1089
            return '';
1090
        }
1091
1092
        $actionsLeft = '';
1093
        $back = '';
1094
        $courseId = api_get_course_id();
1095
        if (empty($courseId)) {
1096
            $actionsLeft .=
1097
                Display::url(
1098
                    Display::return_icon('bbb.png', $this->get_lang('Meetings'), null, ICON_SIZE_MEDIUM),
1099
                    api_get_path(WEB_PLUGIN_PATH).'zoom/meetings.php'
1100
                );
1101
        } else {
1102
            $actionsLeft .=
1103
                Display::url(
1104
                    Display::return_icon('bbb.png', $this->get_lang('Meetings'), null, ICON_SIZE_MEDIUM),
1105
                    api_get_path(WEB_PLUGIN_PATH).'zoom/start.php?'.api_get_cidreq()
1106
                );
1107
        }
1108
1109
        if (!empty($returnUrl)) {
1110
            $back = Display::url(
1111
                Display::return_icon('back.png', get_lang('Back'), null, ICON_SIZE_MEDIUM),
1112
                $returnUrl
1113
            );
1114
        }
1115
1116
        if (api_is_platform_admin()) {
1117
            $actionsLeft .=
1118
                Display::url(
1119
                    Display::return_icon('settings.png', get_lang('Settings'), null, ICON_SIZE_MEDIUM),
1120
                    api_get_path(WEB_CODE_PATH).'admin/configure_plugin.php?name=zoom'
1121
                ).$back;
1122
        }
1123
1124
        return Display::toolbarAction('toolbar', [$actionsLeft]);
1125
    }
1126
1127
    /**
1128
     * Updates meeting registrants list. Adds the missing registrants and removes the extra.
1129
     *
1130
     * @param Meeting $meeting
1131
     * @param User[]  $users   list of users to be registered
1132
     *
1133
     * @throws Exception
1134
     */
1135
    private function updateRegistrantList($meeting, $users)
1136
    {
1137
        $usersToAdd = [];
1138
        foreach ($users as $user) {
1139
            $found = false;
1140
            foreach ($meeting->getRegistrants() as $registrant) {
1141
                if ($registrant->getUser() === $user) {
1142
                    $found = true;
1143
                    break;
1144
                }
1145
            }
1146
            if (!$found) {
1147
                $usersToAdd[] = $user;
1148
            }
1149
        }
1150
        $registrantsToRemove = [];
1151
        foreach ($meeting->getRegistrants() as $registrant) {
1152
            $found = false;
1153
            foreach ($users as $user) {
1154
                if ($registrant->getUser() === $user) {
1155
                    $found = true;
1156
                    break;
1157
                }
1158
            }
1159
            if (!$found) {
1160
                $registrantsToRemove[] = $registrant;
1161
            }
1162
        }
1163
        $this->registerUsers($meeting, $usersToAdd);
1164
        $this->unregister($meeting, $registrantsToRemove);
1165
    }
1166
1167
    /**
1168
     * Register users to a meeting.
1169
     *
1170
     * @param Meeting $meeting
1171
     * @param User[]  $users
1172
     *
1173
     * @throws OptimisticLockException
1174
     *
1175
     * @return User[] failed registrations [ user id => errorMessage ]
1176
     */
1177
    private function registerUsers($meeting, $users)
1178
    {
1179
        $failedUsers = [];
1180
        foreach ($users as $user) {
1181
            try {
1182
                $this->registerUser($meeting, $user, false);
1183
            } catch (Exception $exception) {
1184
                $failedUsers[$user->getId()] = $exception->getMessage();
1185
            }
1186
        }
1187
        Database::getManager()->flush();
1188
1189
        return $failedUsers;
1190
    }
1191
1192
    /**
1193
     * @throws Exception
1194
     * @throws OptimisticLockException
1195
     *
1196
     * @return Registrant
1197
     */
1198
    private function registerUser(Meeting $meeting, User $user, $andFlush = true)
1199
    {
1200
        if (empty($user->getEmail())) {
1201
            throw new Exception($this->get_lang('CannotRegisterWithoutEmailAddress'));
1202
        }
1203
1204
        $meetingRegistrant = MeetingRegistrant::fromEmailAndFirstName(
1205
            $user->getEmail(),
1206
            $user->getFirstname(),
1207
            $user->getLastname()
1208
        );
1209
1210
        $registrantEntity = (new Registrant())
1211
            ->setMeeting($meeting)
1212
            ->setUser($user)
1213
            ->setMeetingRegistrant($meetingRegistrant)
1214
            ->setCreatedRegistration($meeting->getMeetingInfoGet()->addRegistrant($meetingRegistrant));
1215
        Database::getManager()->persist($registrantEntity);
1216
1217
        if ($andFlush) {
1218
            Database::getManager()->flush($registrantEntity);
1219
        }
1220
1221
        return $registrantEntity;
1222
    }
1223
1224
    /**
1225
     * Removes registrants from a meeting.
1226
     *
1227
     * @param Meeting      $meeting
1228
     * @param Registrant[] $registrants
1229
     *
1230
     * @throws Exception
1231
     */
1232
    private function unregister($meeting, $registrants)
1233
    {
1234
        $meetingRegistrants = [];
1235
        foreach ($registrants as $registrant) {
1236
            $meetingRegistrants[] = $registrant->getMeetingRegistrant();
1237
        }
1238
        $meeting->getMeetingInfoGet()->removeRegistrants($meetingRegistrants);
1239
        $em = Database::getManager();
1240
        foreach ($registrants as $registrant) {
1241
            $em->remove($registrant);
1242
        }
1243
        $em->flush();
1244
    }
1245
1246
    /**
1247
     * Starts a new instant meeting and redirects to its start url.
1248
     *
1249
     * @param string          $topic
1250
     * @param User|null       $user
1251
     * @param Course|null     $course
1252
     * @param CGroupInfo|null $group
1253
     * @param Session|null    $session
1254
     *
1255
     * @throws Exception
1256
     */
1257
    private function startInstantMeeting($topic, $user = null, $course = null, $group = null, $session = null)
1258
    {
1259
        $meetingInfoGet = MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_INSTANT);
1260
        //$meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE;
1261
        $meeting = $this->createMeetingFromMeeting(
1262
            (new Meeting())
1263
                ->setMeetingInfoGet($meetingInfoGet)
1264
                ->setUser($user)
1265
                ->setGroup($group)
1266
                ->setCourse($course)
1267
                ->setSession($session)
1268
        );
1269
        api_location($meeting->getMeetingInfoGet()->start_url);
1270
    }
1271
1272
    /**
1273
     * Creates a meeting on Zoom servers and stores it in the local database.
1274
     *
1275
     * @param Meeting $meeting a new, unsaved meeting with at least a type and a topic
1276
     *
1277
     * @throws Exception
1278
     *
1279
     * @return Meeting
1280
     */
1281
    private function createMeetingFromMeeting($meeting)
1282
    {
1283
        $currentUser = api_get_user_entity(api_get_user_id());
1284
1285
        $meeting->getMeetingInfoGet()->settings->contact_email = $currentUser->getEmail();
1286
        $meeting->getMeetingInfoGet()->settings->contact_name = $currentUser->getFullname();
1287
        $meeting->getMeetingInfoGet()->settings->auto_recording = $this->getRecordingSetting();
1288
        $meeting->getMeetingInfoGet()->settings->registrants_email_notification = false;
1289
1290
        //$meeting->getMeetingInfoGet()->host_email = $currentUser->getEmail();
1291
        //$meeting->getMeetingInfoGet()->settings->alternative_hosts = $currentUser->getEmail();
1292
1293
        // Send create to Zoom.
1294
        $meeting->setMeetingInfoGet($meeting->getMeetingInfoGet()->create());
1295
1296
        Database::getManager()->persist($meeting);
1297
        Database::getManager()->flush();
1298
1299
        return $meeting;
1300
    }
1301
1302
    public function getRecordingSetting()
1303
    {
1304
        $recording = (string) $this->get('enableCloudRecording');
1305
1306
        if (in_array($recording, [self::RECORDING_TYPE_LOCAL, self::RECORDING_TYPE_CLOUD], true)) {
1307
1308
            return $recording;
1309
        }
1310
1311
        return self::RECORDING_TYPE_NONE;
1312
    }
1313
1314
    public function hasRecordingAvailable()
1315
    {
1316
        $recording = $this->getRecordingSetting();
1317
1318
        return self::RECORDING_TYPE_NONE !== $recording;
1319
    }
1320
1321
    /**
1322
     * @throws Exception
1323
     *
1324
     * @return Meeting
1325
     */
1326
    private function createGlobalMeeting()
1327
    {
1328
        $meetingInfoGet = MeetingInfoGet::fromTopicAndType(
1329
            $this->get_lang('GlobalMeeting'),
1330
            MeetingInfoGet::TYPE_SCHEDULED
1331
        );
1332
        $meetingInfoGet->start_time = (new DateTime())->format(DateTimeInterface::ISO8601);
1333
        $meetingInfoGet->duration = 60;
1334
        $meetingInfoGet->settings->approval_type =
1335
            ('true' === $this->get('enableParticipantRegistration'))
1336
                ? MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE
1337
                : MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED;
1338
        // $meetingInfoGet->settings->host_video = true;
1339
        $meetingInfoGet->settings->participant_video = true;
1340
        $meetingInfoGet->settings->join_before_host = true;
1341
        $meetingInfoGet->settings->registrants_email_notification = false;
1342
1343
        return $this->createMeetingFromMeeting((new Meeting())->setMeetingInfoGet($meetingInfoGet));
1344
    }
1345
1346
    /**
1347
     * Schedules a meeting and returns it.
1348
     * set $course, $session and $user to null in order to create a global meeting.
1349
     *
1350
     * @param DateTime $startTime meeting local start date-time (configure local timezone on your Zoom account)
1351
     * @param int      $duration  in minutes
1352
     * @param string   $topic     short title of the meeting, required
1353
     * @param string   $agenda    ordre du jour
1354
     * @param string   $password  meeting password
1355
     *
1356
     * @throws Exception
1357
     *
1358
     * @return Meeting meeting
1359
     */
1360
    private function createScheduleMeeting(
1361
        User $user = null,
1362
        Course $course = null,
1363
        CGroupInfo $group = null,
1364
        Session $session = null,
1365
        $startTime,
1366
        $duration,
1367
        $topic,
1368
        $agenda,
1369
        $password
1370
    ) {
1371
        $meetingInfoGet = MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_SCHEDULED);
1372
        $meetingInfoGet->duration = $duration;
1373
        $meetingInfoGet->start_time = $startTime->format(DateTimeInterface::ISO8601);
1374
        $meetingInfoGet->agenda = $agenda;
1375
        $meetingInfoGet->password = $password;
1376
        $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED;
1377
        if ('true' === $this->get('enableParticipantRegistration')) {
1378
            $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE;
1379
        }
1380
1381
        return $this->createMeetingFromMeeting(
1382
            (new Meeting())
1383
                ->setMeetingInfoGet($meetingInfoGet)
1384
                ->setUser($user)
1385
                ->setCourse($course)
1386
                ->setGroup($group)
1387
                ->setSession($session)
1388
        );
1389
    }
1390
1391
    /**
1392
     * Registers all the course users to a course meeting.
1393
     *
1394
     * @param Meeting $meeting
1395
     *
1396
     * @throws OptimisticLockException
1397
     */
1398
    private function registerAllCourseUsers($meeting)
1399
    {
1400
        $this->registerUsers($meeting, $meeting->getRegistrableUsers());
1401
    }
1402
}
1403