Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of the Zoom plugin for Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * The main zoom configuration form
19
 *
20
 * It uses the standard core Moodle formslib. For more info about them, please
21
 * visit: http://docs.moodle.org/en/Development:lib/formslib.php
22
 *
23
 * @package    mod_zoom
24
 * @copyright  2015 UC Regents
25
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26
 */
27
 
28
defined('MOODLE_INTERNAL') || die();
29
 
30
require_once($CFG->dirroot . '/course/moodleform_mod.php');
31
require_once($CFG->dirroot . '/mod/zoom/lib.php');
32
require_once($CFG->dirroot . '/mod/zoom/locallib.php');
33
 
34
/**
35
 * Module instance settings form
36
 */
37
class mod_zoom_mod_form extends moodleform_mod {
38
    /**
39
     * Helper property for showing the scheduling privilege options.
40
     *
41
     * @var bool
42
     */
43
    private $showschedulingprivilege;
44
 
45
    /**
46
     * Defines forms elements
47
     */
48
    public function definition() {
49
        global $PAGE, $USER, $OUTPUT;
50
 
51
        // We don't do anything custom with completion data, so avoid doing any unnecessary work.
52
        $completionpagetypes = [
53
            'course-defaultcompletion' => 'Edit completion default settings (Moodle >= 4.3)',
54
            'course-editbulkcompletion' => 'Edit completion settings in bulk for a single course',
55
            'course-editdefaultcompletion' => 'Edit completion default settings (Moodle < 4.3)',
56
        ];
57
        if (isset($completionpagetypes[$PAGE->pagetype])) {
58
            return;
59
        }
60
 
61
        $config = get_config('zoom');
62
        $PAGE->requires->js_call_amd("mod_zoom/form", 'init');
63
 
64
        $isnew = empty($this->_cm);
65
 
66
        $zoomuserid = zoom_get_user_id(false);
67
 
68
        // If creating a new instance, but the Zoom user does not exist.
69
        if ($isnew && $zoomuserid === false) {
70
            // Assume user is using Zoom for the first time.
71
            $errstring = 'zoomerr_usernotfound';
72
            // After they set up their account, the user should continue to the page they were on.
73
            $nexturl = $PAGE->url;
74
            zoom_fatal_error($errstring, 'mod_zoom', $nexturl, $config->zoomurl);
75
        }
76
 
77
        // Array of emails and proper names of Moodle users in this course that
78
        // can add Zoom meetings, and the user can schedule.
79
        $scheduleusers = [];
80
 
81
        $canschedule = false;
82
        if ($zoomuserid !== false) {
83
            // Get the array of users they can schedule.
84
            $canschedule = zoom_webservice()->get_schedule_for_users($zoomuserid);
85
        }
86
 
87
        if (!empty($canschedule)) {
88
            // Add the current user.
89
            $canschedule[$zoomuserid] = new stdClass();
90
            $canschedule[$zoomuserid]->email = $USER->email;
91
 
92
            // If the activity exists and the current user is not the current host.
93
            if (!$isnew && $zoomuserid !== $this->current->host_id) {
94
                // Get intersection of current host's schedulers and $USER's schedulers to prevent zoom errors.
95
                $currenthostschedulers = zoom_webservice()->get_schedule_for_users($this->current->host_id);
96
                if (!empty($currenthostschedulers)) {
97
                    // Since this is the second argument to array_intersect_key,
98
                    // the entry from $canschedule will be used, so we can just
99
                    // use true to avoid a service call.
100
                    $currenthostschedulers[$this->current->host_id] = true;
101
                }
102
 
103
                $canschedule = array_intersect_key($canschedule, $currenthostschedulers);
104
            }
105
 
106
            // Get list of users who can add Zoom activities in this context.
107
            $moodleusers = get_enrolled_users($this->context, 'mod/zoom:addinstance', 0, 'u.*', 'lastname');
108
 
109
            // Check each potential host to see if they are a valid host.
110
            foreach ($canschedule as $zoomuserinfo) {
111
                $zoomemail = strtolower($zoomuserinfo->email);
112
                if (isset($scheduleusers[$zoomemail])) {
113
                    continue;
114
                }
115
 
116
                if ($zoomemail === strtolower($USER->email)) {
117
                    $scheduleusers[$zoomemail] = get_string('scheduleforself', 'zoom');
118
                    continue;
119
                }
120
 
121
                foreach ($moodleusers as $muser) {
122
                    if ($zoomemail === strtolower($muser->email)) {
123
                        $scheduleusers[$zoomemail] = fullname($muser);
124
                        break;
125
                    }
126
                }
127
            }
128
        }
129
 
130
        if (!$isnew) {
131
            try {
132
                zoom_webservice()->get_meeting_webinar_info($this->current->meeting_id, $this->current->webinar);
133
            } catch (\mod_zoom\webservice_exception $error) {
134
                // If the meeting can't be found, offer to recreate the meeting on Zoom.
135
                if (zoom_is_meeting_gone_error($error)) {
136
                    $errstring = 'zoomerr_meetingnotfound';
137
                    $param = zoom_meetingnotfound_param($this->_cm->id);
138
                    $nexturl = "/mod/zoom/view.php?id=" . $this->_cm->id;
139
                    zoom_fatal_error($errstring, 'mod_zoom', $nexturl, $param, "meeting/get : $error");
140
                } else {
141
                    throw $error;
142
                }
143
            }
144
        }
145
 
146
        // If the current editing user has the host saved in the db for this meeting on their list
147
        // of people that they can schedule for, allow them to change the host, otherwise don't.
148
        $allowschedule = false;
149
        if (!$isnew) {
150
            // Only need to check if there are scheduling options available.
151
            if (!empty($scheduleusers)) {
152
                try {
153
                    $founduser = zoom_get_user($this->current->host_id);
154
                    if ($founduser && array_key_exists($founduser->email, $scheduleusers)) {
155
                        $allowschedule = true;
156
                    }
157
                } catch (moodle_exception $error) {
158
                    // Don't need to throw an error, just leave allowschedule as false.
159
                    $allowschedule = false;
160
                }
161
            }
162
        } else {
163
            $allowschedule = true;
164
        }
165
 
166
        // Start of form definition.
167
        $mform = $this->_form;
168
 
169
        // Adding the "general" fieldset, where all the common settings are showed.
170
        $mform->addElement('header', 'general', get_string('general', 'form'));
171
 
172
        // Add title (stored in database as 'name').
173
        $mform->addElement('text', 'name', get_string('title', 'zoom'), ['size' => '64']);
174
        $mform->setType('name', PARAM_TEXT);
175
        $mform->addRule('name', null, 'required', null, 'client');
176
        $mform->addRule('name', get_string('maximumchars', '', 200), 'maxlength', 200, 'client');
177
 
178
        // Add description 'intro' and 'introformat'.
179
        $this->standard_intro_elements();
180
 
181
        // Adding the "schedule" fieldset, where all settings relating to date and time are shown.
182
        $mform->addElement('header', 'schedule', get_string('schedule', 'mod_zoom'));
183
        $mform->setExpanded('schedule');
184
 
185
        // Add date/time. Validation in validation().
186
        $starttimeoptions = [
187
            'step' => 5,
188
            'defaulttime' => time() + 3600,
189
        ];
190
        $mform->addElement('date_time_selector', 'start_time', get_string('start_time', 'zoom'), $starttimeoptions);
191
        // Start time needs to be enabled/disabled based on recurring checkbox as well recurrence_type.
192
        // Moved this control to javascript, rather than using disabledIf.
193
 
194
        // Add duration.
195
        $mform->addElement('duration', 'duration', get_string('duration', 'zoom'), ['optional' => false]);
196
        // Validation in validation(). Default to one hour.
197
        $mform->setDefault('duration', ['number' => 1, 'timeunit' => 3600]);
198
        // Duration needs to be enabled/disabled based on recurring checkbox as well recurrence_type.
199
        // Moved this control to javascript, rather than using disabledIf.
200
 
201
        // Add recurring widget.
202
        $mform->addElement(
203
            'advcheckbox',
204
            'recurring',
205
            get_string('recurringmeeting', 'zoom'),
206
            get_string('recurringmeetingthisis', 'zoom')
207
        );
208
        $mform->setDefault('recurring', $config->defaultrecurring);
209
        $mform->addHelpButton('recurring', 'recurringmeeting', 'zoom');
210
 
211
        // Add options for recurring meeting.
212
        $recurrencetype = [
213
            ZOOM_RECURRINGTYPE_DAILY => get_string('recurrence_option_daily', 'zoom'),
214
            ZOOM_RECURRINGTYPE_WEEKLY => get_string('recurrence_option_weekly', 'zoom'),
215
            ZOOM_RECURRINGTYPE_MONTHLY => get_string('recurrence_option_monthly', 'zoom'),
216
            ZOOM_RECURRINGTYPE_NOTIME => get_string('recurrence_option_no_time', 'zoom'),
217
        ];
218
        $mform->addElement('select', 'recurrence_type', get_string('recurrencetype', 'zoom'), $recurrencetype);
219
        // If the defaultrecurring option is active, set default recurrence_type to be No Fixed Time.
220
        if ($config->defaultrecurring == 1) {
221
            $mform->setDefault('recurrence_type', ZOOM_RECURRINGTYPE_NOTIME);
222
        }
223
        $mform->hideif('recurrence_type', 'recurring', 'notchecked');
224
 
225
        // Repeat Interval options.
226
        $options = [];
227
        for ($i = 1; $i <= 90; $i++) {
228
            $options[$i] = $i;
229
        }
230
 
231
        $group = [];
232
        $group[] = $mform->createElement('select', 'repeat_interval', '', $options);
233
        $htmlspantextstart = '<span class="repeat_interval" id="interval_';
234
        $htmlspantextend = '</span>';
235
        $group[] = $mform->createElement('html', $htmlspantextstart . 'daily">' . get_string('day', 'zoom') . $htmlspantextend);
236
        $group[] = $mform->createElement('html', $htmlspantextstart . 'weekly">' . get_string('week', 'zoom') . $htmlspantextend);
237
        $group[] = $mform->createElement('html', $htmlspantextstart . 'monthly">' . get_string('month', 'zoom') . $htmlspantextend);
238
        $mform->addGroup($group, 'repeat_group', get_string('repeatinterval', 'zoom'), null, false);
239
        $mform->hideif('repeat_group', 'recurrence_type', 'eq', ZOOM_RECURRINGTYPE_NOTIME);
240
        $mform->hideif('repeat_group', 'recurring', 'notchecked');
241
 
242
        // Weekly options.
243
        $weekdayoptions = zoom_get_weekday_options();
244
        $group = [];
245
        foreach ($weekdayoptions as $key => $weekday) {
246
            $weekdayid = 'weekly_days_' . $key;
247
            $attributes = [];
248
            $group[] = $mform->createElement('advcheckbox', $weekdayid, '', $weekday, null, [0, $key]);
249
        }
250
 
251
        $mform->addGroup($group, 'weekly_days_group', get_string('occurson', 'zoom'), ' ', false);
252
        $mform->hideif('weekly_days_group', 'recurrence_type', 'noteq', ZOOM_RECURRINGTYPE_WEEKLY);
253
        $mform->hideif('weekly_days_group', 'recurring', 'notchecked');
254
        if (!empty($this->current->weekly_days)) {
255
            $weekdaynumbers = explode(',', $this->current->weekly_days);
256
            foreach ($weekdaynumbers as $daynumber) {
257
                $weekdayid = 'weekly_days_' . $daynumber;
258
                $mform->setDefault($weekdayid, $daynumber);
259
            }
260
        }
261
 
262
        // Monthly options.
263
        $monthoptions = [];
264
        for ($i = 1; $i <= 31; $i++) {
265
            $monthoptions[$i] = $i;
266
        }
267
 
268
        $monthlyweekoptions = zoom_get_monthweek_options();
269
 
270
        $group = [];
271
        $group[] = $mform->createElement(
272
            'radio',
273
            'monthly_repeat_option',
274
            '',
275
            get_string('day', 'calendar'),
276
            ZOOM_MONTHLY_REPEAT_OPTION_DAY
277
        );
278
        $group[] = $mform->createElement('select', 'monthly_day', '', $monthoptions);
279
        $group[] = $mform->createElement('static', 'month_day_text', '', get_string('month_day_text', 'zoom'));
280
        $group[] = $mform->createElement('radio', 'monthly_repeat_option', '', '', ZOOM_MONTHLY_REPEAT_OPTION_WEEK);
281
        $group[] = $mform->createElement('select', 'monthly_week', '', $monthlyweekoptions);
282
        $group[] = $mform->createElement('select', 'monthly_week_day', '', $weekdayoptions);
283
        $group[] = $mform->createElement('static', 'month_week_day_text', '', get_string('month_day_text', 'zoom'));
284
        $mform->addGroup($group, 'monthly_day_group', get_string('occurson', 'zoom'), null, false);
285
        $mform->hideif('monthly_day_group', 'recurrence_type', 'noteq', ZOOM_RECURRINGTYPE_MONTHLY);
286
        $mform->hideif('monthly_day_group', 'recurring', 'notchecked');
287
        $mform->setDefault('monthly_repeat_option', ZOOM_MONTHLY_REPEAT_OPTION_DAY);
288
 
289
        // End date option.
290
        $maxoptions = [];
291
        for ($i = 1; $i <= 50; $i++) {
292
            $maxoptions[$i] = $i;
293
        }
294
 
295
        $group = [];
296
        $group[] = $mform->createElement(
297
            'radio',
298
            'end_date_option',
299
            '',
300
            get_string('end_date_option_by', 'zoom'),
301
            ZOOM_END_DATE_OPTION_BY
302
        );
303
        $group[] = $mform->createElement('date_selector', 'end_date_time', '');
304
        $group[] = $mform->createElement(
305
            'radio',
306
            'end_date_option',
307
            '',
308
            get_string('end_date_option_after', 'zoom'),
309
            ZOOM_END_DATE_OPTION_AFTER
310
        );
311
        $group[] = $mform->createElement('select', 'end_times', '', $maxoptions);
312
        $group[] = $mform->createElement('static', 'end_times_text', '', get_string('end_date_option_occurrences', 'zoom'));
313
        $mform->addGroup($group, 'radioenddate', get_string('enddate', 'zoom'), null, false);
314
        $mform->hideif('radioenddate', 'recurring', 'notchecked');
315
        $mform->hideif('radioenddate', 'recurrence_type', 'eq', ZOOM_RECURRINGTYPE_NOTIME);
316
        // Set default option for end date to be "By".
317
        $mform->setDefault('end_date_option', ZOOM_END_DATE_OPTION_BY);
318
        // Set default end_date_time to be 1 week in the future.
319
        $mform->setDefault('end_date_time', strtotime('+1 week'));
320
 
321
        // Supplementary feature: Webinars.
322
        // Only show if the admin did not disable this feature completely.
323
        if ($config->showwebinars != ZOOM_WEBINAR_DISABLE) {
324
            // If we are creating a new instance.
325
            if ($isnew) {
326
                // Check if the user has a webinar license.
327
                $userfeatures = zoom_get_user_settings($zoomuserid)->feature;
328
                $haswebinarlicense = !empty($userfeatures->webinar) || !empty($userfeatures->zoom_events);
329
 
330
                // Only show if the admin always wants to show this widget or
331
                // if the admin wants to show this widget conditionally and the user has a valid license.
332
                if (
333
                    $config->showwebinars == ZOOM_WEBINAR_ALWAYSSHOW ||
334
                    ($config->showwebinars == ZOOM_WEBINAR_SHOWONLYIFLICENSE && $haswebinarlicense)
335
                ) {
336
                    // Add webinar option, disabled if the user cannot create webinars.
337
                    $webinarattr = null;
338
                    if (!$haswebinarlicense) {
339
                        $webinarattr = ['disabled' => true, 'group' => null];
340
                    }
341
 
342
                    $mform->addElement(
343
                        'advcheckbox',
344
                        'webinar',
345
                        get_string('webinar', 'zoom'),
346
                        get_string('webinarthisis', 'zoom'),
347
                        $webinarattr
348
                    );
349
                    $mform->setDefault('webinar', $config->webinardefault);
350
                    $mform->addHelpButton('webinar', 'webinar', 'zoom');
351
                }
352
            } else if ($this->current->webinar) {
353
                $mform->addElement(
354
                    'static',
355
                    'webinaralreadyset',
356
                    get_string('webinar', 'zoom'),
357
                    get_string('webinar_already_true', 'zoom')
358
                );
359
            } else {
360
                $mform->addElement(
361
                    'static',
362
                    'webinaralreadyset',
363
                    get_string('webinar', 'zoom'),
364
                    get_string('webinar_already_false', 'zoom')
365
                );
366
            }
367
        }
368
 
369
        // Add tracking fields, if configured in Moodle AND Zoom.
370
        $defaulttrackingfields = zoom_clean_tracking_fields();
371
        foreach ($defaulttrackingfields as $key => $defaulttrackingfield) {
372
            $configname = 'tf_' . $key . '_field';
373
            if (!empty($config->$configname)) {
374
                $mform->addElement('text', $key, $defaulttrackingfield);
375
                $mform->setType($key, PARAM_TEXT);
376
                $rvprop = 'tf_' . $key . '_recommended_values';
377
                if (!empty($config->$rvprop)) {
378
                    $mform->addElement(
379
                        'static',
380
                        $key . '_recommended_values',
381
                        null,
382
                        get_string('trackingfields_recommendedvalues', 'mod_zoom') . $config->$rvprop
383
                    );
384
                }
385
 
386
                $requiredproperty = 'tf_' . $key . '_required';
387
                if (!empty($config->$requiredproperty)) {
388
                    $mform->addRule($key, null, 'required', null, 'client');
389
                }
390
            }
391
        }
392
 
393
        // Add show widget.
394
        $mform->addElement(
395
            'advcheckbox',
396
            'show_schedule',
397
            get_string('showschedule', 'zoom'),
398
            get_string('showscheduleonview', 'zoom')
399
        );
400
        $mform->setDefault('show_schedule', $config->defaultshowschedule);
401
        $mform->addHelpButton('show_schedule', 'showschedule', 'zoom');
402
 
403
        // Add registration widget.
404
        $registrationoptions = [
405
            ZOOM_REGISTRATION_OFF => get_string('no'),
406
            ZOOM_REGISTRATION_AUTOMATIC => get_string('registration_text', 'mod_zoom'),
407
        ];
408
        $mform->addElement('select', 'registration', get_string('registration', 'mod_zoom'), $registrationoptions);
409
        $mform->setDefault('registration', $config->defaultregistration);
410
        $mform->addHelpButton('registration', 'registration', 'mod_zoom');
411
        $mform->hideIf('registration', 'recurrence_type', 'eq', ZOOM_RECURRINGTYPE_NOTIME);
412
 
413
        // Adding the "breakout rooms" fieldset.
414
        $mform->addElement('header', 'breakoutrooms', get_string('breakoutrooms', 'mod_zoom'));
415
        $mform->setExpanded('breakoutrooms');
416
 
417
        $courseid = $this->current->course;
418
        $context = context_course::instance($courseid);
419
 
420
        $groups = groups_get_all_groups($courseid);
421
        $participants = get_enrolled_users($context);
422
 
423
        // Getting Course participants.
424
        $courseparticipants = [];
425
        foreach ($participants as $participant) {
426
            $courseparticipants[] = [
427
                'participantid' => $participant->id,
428
                'participantname' => fullname($participant) . ' <' . $participant->email . '>',
429
            ];
430
        }
431
 
432
        // Getting Course groups.
433
        $coursegroups = [];
434
        foreach ($groups as $group) {
435
            $coursegroups[] = ['groupid' => $group->id, 'groupname' => $group->name];
436
        }
437
 
438
        // Building meeting breakout rooms template data.
439
        $templatedata = [
440
            'rooms' => [],
441
            'roomscount' => 0,
442
            'roomtoclone' => [
443
                'toclone' => 'toclone',
444
                'courseparticipants' => $courseparticipants,
445
                'coursegroups' => $coursegroups,
446
            ],
447
        ];
448
 
449
        $currentinstance = $this->current->instance;
450
        if ($currentinstance) {
451
            $rooms = zoom_build_instance_breakout_rooms_array_for_view($currentinstance, $courseparticipants, $coursegroups);
452
 
453
            $templatedata['rooms'] = $rooms;
454
            $templatedata['roomscount'] = count($rooms);
455
        }
456
 
457
        $mform->addElement('html', $OUTPUT->render_from_template('zoom/breakoutrooms_rooms', $templatedata));
458
 
459
        $mform->addElement('hidden', 'rooms', '');
460
        $mform->setType('rooms', PARAM_RAW);
461
 
462
        $mform->addElement('hidden', 'roomsparticipants', '');
463
        $mform->setType('roomsparticipants', PARAM_RAW);
464
 
465
        $mform->addElement('hidden', 'roomsgroups', '');
466
        $mform->setType('roomsgroups', PARAM_RAW);
467
 
468
        // Adding the "security" fieldset, where all settings relating to securing and protecting the meeting are shown.
469
        $mform->addElement('header', 'security', get_string('security', 'mod_zoom'));
470
        $mform->setExpanded('security');
471
 
472
        // Deals with password manager issues.
473
        if (isset($this->current->password)) {
474
            $this->current->meetingcode = $this->current->password;
475
            unset($this->current->password);
476
        }
477
 
478
        // Add password requirement prompt.
479
        $mform->addElement(
480
            'advcheckbox',
481
            'requirepasscode',
482
            get_string('password', 'zoom'),
483
            get_string('requirepasscode', 'zoom')
484
        );
485
        if (isset($this->current->meetingcode) && strval($this->current->meetingcode) === "") {
486
            $mform->setDefault('requirepasscode', 0);
487
        } else {
488
            $mform->setDefault('requirepasscode', 1);
489
        }
490
 
491
        $mform->addHelpButton('requirepasscode', 'requirepasscode', 'zoom');
492
 
493
        // Set default passcode and description from Zoom security settings.
494
        $securitysettings = zoom_get_meeting_security_settings($this->current->host_id ?? $zoomuserid);
495
        // Add password.
496
        $mform->addElement('text', 'meetingcode', get_string('setpasscode', 'zoom'), ['maxlength' => '10']);
497
        $mform->setType('meetingcode', PARAM_TEXT);
498
        // Check password uses valid characters.
499
        $regex = '/^[a-zA-Z0-9@_*-]{1,10}$/';
500
        $mform->addRule('meetingcode', get_string('err_invalid_password', 'mod_zoom'), 'regex', $regex, 'client');
501
        $mform->setDefault('meetingcode', zoom_create_default_passcode($securitysettings->meeting_password_requirement));
502
        $mform->hideIf('meetingcode', 'requirepasscode', 'notchecked');
503
        // Add passcode requirements note (use mform group trick from MDL-66251 to be able to conditionally hide this).
504
        $passwordrequirementsgroup = [];
505
        $passwordrequirementsgroup[] =& $mform->createElement(
506
            'static',
507
            'passwordrequirements',
508
            '',
509
            zoom_create_passcode_description($securitysettings->meeting_password_requirement)
510
        );
511
        $mform->addGroup($passwordrequirementsgroup, 'passwordrequirementsgroup', '', '', false);
512
        $mform->hideIf('passwordrequirementsgroup', 'requirepasscode', 'notchecked');
513
 
514
        // Supplementary feature: Encryption type.
515
        // Only show if the admin did not disable this feature completely.
516
        if ($config->showencryptiontype != ZOOM_ENCRYPTION_DISABLE) {
517
            // Check if the user can use e2e encryption.
518
            $e2eispossible = $securitysettings->end_to_end_encrypted_meetings;
519
 
520
            if ($config->showencryptiontype == ZOOM_ENCRYPTION_SHOWONLYIFPOSSIBLE && !$e2eispossible) {
521
                // If user cannot use e2e and option is not shown to user,
522
                // default to enhanced encryption.
523
                $mform->addElement('hidden', 'option_encryption_type', ZOOM_ENCRYPTION_TYPE_ENHANCED);
524
            } else if (
525
                $config->showencryptiontype == ZOOM_ENCRYPTION_ALWAYSSHOW ||
526
                ($config->showencryptiontype == ZOOM_ENCRYPTION_SHOWONLYIFPOSSIBLE && $e2eispossible)
527
            ) {
528
                // Only show if the admin always wants to show this widget or
529
                // if the admin wants to show this widget conditionally and the user can use e2e encryption.
530
 
531
                // Add encryption type option, disabled if the user can't use e2e encryption.
532
                $encryptionattr = null;
533
                $defaultencryptiontype = $config->defaultencryptiontypeoption;
534
                if (!$e2eispossible) {
535
                    $encryptionattr = ['disabled' => true];
536
                    $defaultencryptiontype = ZOOM_ENCRYPTION_TYPE_ENHANCED;
537
                }
538
 
539
                $mform->addGroup([
540
                    $mform->createElement(
541
                        'radio',
542
                        'option_encryption_type',
543
                        '',
544
                        get_string('option_encryption_type_enhancedencryption', 'zoom'),
545
                        ZOOM_ENCRYPTION_TYPE_ENHANCED,
546
                        $encryptionattr
547
                    ),
548
                    $mform->createElement(
549
                        'radio',
550
                        'option_encryption_type',
551
                        '',
552
                        get_string('option_encryption_type_endtoendencryption', 'zoom'),
553
                        ZOOM_ENCRYPTION_TYPE_E2EE,
554
                        $encryptionattr
555
                    ),
556
                ], 'option_encryption_type_group', get_string('option_encryption_type', 'zoom'), null, false);
557
                $mform->setDefault('option_encryption_type', $defaultencryptiontype);
558
                $mform->addHelpButton('option_encryption_type_group', 'option_encryption_type', 'zoom');
559
                $mform->disabledIf('option_encryption_type_group', 'webinar', 'checked');
560
            }
561
 
562
            $mform->setType('option_encryption_type', PARAM_ALPHANUMEXT);
563
        }
564
 
565
        // Add waiting room widget.
566
        $mform->addElement(
567
            'advcheckbox',
568
            'option_waiting_room',
569
            get_string('option_waiting_room', 'zoom'),
570
            get_string('waitingroomenable', 'zoom')
571
        );
572
        $mform->addHelpButton('option_waiting_room', 'option_waiting_room', 'zoom');
573
        $mform->setDefault('option_waiting_room', $config->defaultwaitingroomoption);
574
        $mform->disabledIf('option_waiting_room', 'webinar', 'checked');
575
 
576
        // Add join before host widget.
577
        $mform->addElement(
578
            'advcheckbox',
579
            'option_jbh',
580
            get_string('option_jbh', 'zoom'),
581
            get_string('joinbeforehostenable', 'zoom')
582
        );
583
        $mform->setDefault('option_jbh', $config->defaultjoinbeforehost);
584
        $mform->addHelpButton('option_jbh', 'option_jbh', 'zoom');
585
        $mform->disabledIf('option_jbh', 'webinar', 'checked');
586
 
587
        // Add authenticated users widget.
588
        $mform->addElement(
589
            'advcheckbox',
590
            'option_authenticated_users',
591
            get_string('authentication', 'zoom'),
592
            get_string('option_authenticated_users', 'zoom')
593
        );
594
        $mform->setDefault('option_authenticated_users', $config->defaultauthusersoption);
595
        $mform->addHelpButton('option_authenticated_users', 'option_authenticated_users', 'zoom');
596
 
597
        // Add show widget.
598
        $mform->addElement(
599
            'advcheckbox',
600
            'show_security',
601
            get_string('showsecurity', 'zoom'),
602
            get_string('showsecurityonview', 'zoom')
603
        );
604
        $mform->setDefault('show_security', $config->defaultshowsecurity);
605
        $mform->addHelpButton('show_security', 'showsecurity', 'zoom');
606
 
607
        // Adding the "media" fieldset, where all settings relating to media streams in the meeting are shown.
608
        $mform->addElement('header', 'media', get_string('media', 'mod_zoom'));
609
        $mform->setExpanded('media');
610
 
611
        // Add host/participants video options.
612
        $mform->addGroup([
613
            $mform->createElement('radio', 'option_host_video', '', get_string('on', 'zoom'), true),
614
            $mform->createElement('radio', 'option_host_video', '', get_string('off', 'zoom'), false),
615
        ], 'option_host_video_group', get_string('option_host_video', 'zoom'), null, false);
616
        $mform->setDefault('option_host_video', $config->defaulthostvideo);
617
        $mform->addHelpButton('option_host_video_group', 'option_host_video', 'zoom');
618
        $mform->disabledIf('option_host_video_group', 'webinar', 'checked');
619
 
620
        $mform->addGroup([
621
            $mform->createElement('radio', 'option_participants_video', '', get_string('on', 'zoom'), true),
622
            $mform->createElement('radio', 'option_participants_video', '', get_string('off', 'zoom'), false),
623
        ], 'option_participants_video_group', get_string('option_participants_video', 'zoom'), null, false);
624
        $mform->setDefault('option_participants_video', $config->defaultparticipantsvideo);
625
        $mform->addHelpButton('option_participants_video_group', 'option_participants_video', 'zoom');
626
        $mform->disabledIf('option_participants_video_group', 'webinar', 'checked');
627
 
628
        // Add audio options.
629
        $mform->addGroup([
630
            $mform->createElement('radio', 'option_audio', '', get_string('audio_telephony', 'zoom'), ZOOM_AUDIO_TELEPHONY),
631
            $mform->createElement('radio', 'option_audio', '', get_string('audio_voip', 'zoom'), ZOOM_AUDIO_VOIP),
632
            $mform->createElement('radio', 'option_audio', '', get_string('audio_both', 'zoom'), ZOOM_AUDIO_BOTH),
633
        ], 'option_audio_group', get_string('option_audio', 'zoom'), null, false);
634
        $mform->addHelpButton('option_audio_group', 'option_audio', 'zoom');
635
        $mform->setDefault('option_audio', $config->defaultaudiooption);
636
 
637
        // Add mute participants upon entry widget.
638
        $mform->addElement(
639
            'advcheckbox',
640
            'option_mute_upon_entry',
641
            get_string('audiodefault', 'mod_zoom'),
642
            get_string('option_mute_upon_entry', 'mod_zoom')
643
        );
644
        $mform->setDefault('option_mute_upon_entry', $config->defaultmuteuponentryoption);
645
        $mform->addHelpButton('option_mute_upon_entry', 'option_mute_upon_entry', 'mod_zoom');
646
 
647
        // Add autorecording option if enabled.
648
        $allowrecordingchangeoption = $config->allowrecordingchangeoption;
649
        if ($allowrecordingchangeoption) {
650
            // Add auto recording options according to user settings.
651
            $options = [
652
                ZOOM_AUTORECORDING_NONE => get_string('autorecording_none', 'mod_zoom'),
653
            ];
654
 
655
            $hostuserid = $zoomuserid;
656
            if (!empty($this->current->host_id)) {
657
                $hostuserid = $this->current->host_id;
658
            }
659
 
660
            if (!empty($hostuserid)) {
661
                $recordingsettings = zoom_get_user_settings($hostuserid)->recording;
662
            }
663
 
664
            if (!empty($recordingsettings->local_recording)) {
665
                $options[ZOOM_AUTORECORDING_LOCAL] = get_string('autorecording_local', 'mod_zoom');
666
            }
667
 
668
            if (!empty($recordingsettings->cloud_recording)) {
669
                $options[ZOOM_AUTORECORDING_CLOUD] = get_string('autorecording_cloud', 'mod_zoom');
670
            }
671
 
672
            if ($config->recordingoption === ZOOM_AUTORECORDING_USERDEFAULT) {
673
                $defaultsetting = $recordingsettings->auto_recording;
674
            } else {
675
                $defaultsetting = $config->recordingoption;
676
            }
677
 
678
            $mform->addElement('select', 'option_auto_recording', get_string('option_auto_recording', 'mod_zoom'), $options);
679
            $mform->setDefault('option_auto_recording', $defaultsetting);
680
            $mform->addHelpButton('option_auto_recording', 'option_auto_recording', 'mod_zoom');
681
        }
682
 
683
        // Add show widget.
684
        $mform->addElement(
685
            'advcheckbox',
686
            'show_media',
687
            get_string('showmedia', 'zoom'),
688
            get_string('showmediaonview', 'zoom')
689
        );
690
        $mform->setDefault('show_media', $config->defaultshowmedia);
691
        $mform->addHelpButton('show_media', 'showmedia', 'zoom');
692
 
693
        // Check if there is any setting to be shown in the "host" fieldset.
694
        $showschedulingprivilege = ($config->showschedulingprivilege != ZOOM_SCHEDULINGPRIVILEGE_DISABLE) &&
695
                count($scheduleusers) > 1 && $allowschedule; // Check if the size is greater than 1 because
696
                                                             // we add the editing/creating user by default.
697
        $this->showschedulingprivilege = $showschedulingprivilege;
698
        $showalternativehosts = ($config->showalternativehosts != ZOOM_ALTERNATIVEHOSTS_DISABLE);
699
        if ($showschedulingprivilege || $showalternativehosts) {
700
            // Adding the "host" fieldset, where all settings relating to defining the meeting host are shown.
701
            $mform->addElement('header', 'host', get_string('host', 'mod_zoom'));
702
            $mform->setExpanded('host');
703
 
704
            // Supplementary feature: Alternative hosts.
705
            // Only show if the admin did not disable this feature completely.
706
            if ($showalternativehosts) {
707
                // Explain alternativehosts.
708
                $mform->addElement('static', 'hostintro', '', get_string('hostintro', 'zoom'));
709
 
710
                // If the admin wants to show the plain input field.
711
                if ($config->showalternativehosts == ZOOM_ALTERNATIVEHOSTS_INPUTFIELD) {
712
                    // Add alternative hosts.
713
                    $mform->addElement('text', 'alternative_hosts', get_string('alternative_hosts', 'zoom'), ['size' => '64']);
714
                    $mform->setType('alternative_hosts', PARAM_TEXT);
715
                    $mform->addHelpButton('alternative_hosts', 'alternative_hosts', 'zoom');
716
 
717
                    // If the admin wants to show the user picker.
718
                } else if ($config->showalternativehosts == ZOOM_ALTERNATIVEHOSTS_PICKER) {
719
                    // Get selectable alternative host users based on the capability.
720
                    $alternativehostschoices = zoom_get_selectable_alternative_hosts_list($this->context);
721
                    // Create autocomplete widget.
722
                    $alternativehostsoptions = [
723
                        'multiple' => true,
724
                        'showsuggestions' => true,
725
                        'placeholder' => get_string('alternative_hosts_picker_placeholder', 'zoom'),
726
                        'noselectionstring' => get_string('alternative_hosts_picker_noneselected', 'zoom'),
727
                    ];
728
                    $mform->addElement(
729
                        'autocomplete',
730
                        'alternative_hosts_picker',
731
                        get_string('alternative_hosts', 'zoom'),
732
                        $alternativehostschoices,
733
                        $alternativehostsoptions
734
                    );
735
                    $mform->setType('alternative_hosts_picker', PARAM_EMAIL);
736
                    $mform->addHelpButton('alternative_hosts_picker', 'alternative_hosts_picker', 'zoom');
737
                }
738
            }
739
 
740
            // Supplementary feature: Scheduling privilege.
741
            // Only show if the admin did not disable this feature completely and if current user is able to use it.
742
            if ($showschedulingprivilege) {
743
                if ($allowrecordingchangeoption) {
744
                    $PAGE->requires->js_call_amd('mod_zoom/scheduleforchooser', 'init');
745
                    $mform->addElement('select', 'schedule_for', get_string('schedulefor', 'mod_zoom'), $scheduleusers, [
746
                        'data-scheduleforchooser-field' => 'selector',
747
                    ]);
748
                } else {
749
                    $mform->addElement('select', 'schedule_for', get_string('schedulefor', 'mod_zoom'), $scheduleusers);
750
                }
751
 
752
                $mform->setType('schedule_for', PARAM_EMAIL);
753
                if (!$isnew) {
754
                    $mform->disabledIf('schedule_for', 'change_schedule_for');
755
                    $mform->addElement('checkbox', 'change_schedule_for', get_string('changehost', 'zoom'));
756
                    $mform->setDefault('schedule_for', strtolower(zoom_get_user($this->current->host_id)->email));
757
                } else {
758
                    $mform->setDefault('schedule_for', strtolower(zoom_get_api_identifier($USER)));
759
                }
760
 
761
                $mform->addHelpButton('schedule_for', 'schedulefor', 'zoom');
762
 
763
                if ($allowrecordingchangeoption) {
764
                    // Button to update auto recording options based on the user permissions in Zoom (will be hidden by JavaScript).
765
                    $mform->registerNoSubmitButton('updateautorecordingoptions');
766
                    $mform->addElement(
767
                        'submit',
768
                        'updateautorecordingoptions',
769
                        get_string('autorecordingoptionsupdate', 'mod_zoom'),
770
                        [
771
                            'data-scheduleforchooser-field' => 'updateButton',
772
                            'class' => 'd-none',
773
                        ]
774
                    );
775
                }
776
            }
777
        }
778
 
779
        // Adding option for Recording Visiblity by default.
780
        if (!empty($config->viewrecordings)) {
781
            $mform->addElement('header', 'recording', get_string('recording', 'mod_zoom'));
782
            $mform->addElement(
783
                'advcheckbox',
784
                'recordings_visible_default',
785
                get_string('recordingvisibility', 'mod_zoom'),
786
                get_string('yes')
787
            );
788
            $mform->setDefault('recordings_visible_default', 1);
789
            $mform->addHelpButton('recordings_visible_default', 'recordingvisibility', 'mod_zoom');
790
        }
791
 
792
        // Add meeting id.
793
        $mform->addElement('hidden', 'meeting_id', -1);
794
        $mform->setType('meeting_id', PARAM_ALPHANUMEXT);
795
 
796
        // Add host id (will error if user does not have an account on Zoom).
797
        $mform->addElement('hidden', 'host_id', zoom_get_user_id());
798
        $mform->setType('host_id', PARAM_ALPHANUMEXT);
799
 
800
        // Add standard grading elements.
801
        $this->standard_grading_coursemodule_elements();
802
        $mform->setDefault('grade', false);
803
 
804
        // Add standard elements, common to all modules.
805
        $this->standard_coursemodule_elements();
806
        $this->apply_admin_defaults();
807
 
808
        // Add standard buttons, common to all modules.
809
        $this->add_action_buttons();
810
    }
811
 
812
    /**
813
     * Add standard_grading_coursemodule_elements with grading for field.
814
     * @return void
815
     */
816
    public function standard_grading_coursemodule_elements() {
817
        parent::standard_grading_coursemodule_elements();
818
        $mform = $this->_form;
819
        $itemnumber = 0;
820
        $component = "mod_{$this->_modname}";
821
        $gradefieldname = \core_grades\component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'grade');
822
        $options = [
823
            'entry' => get_string('gradingentry', 'mod_zoom'), // All credit upon entry.
824
            'period' => get_string('gradingperiod', 'mod_zoom'), // Credit according to attend duration.
825
        ];
826
        $mform->addElement('select', 'grading_method', get_string('gradingmethod', 'mod_zoom'), $options);
827
        $mform->setDefault('grading_method', get_config('zoom', 'gradingmethod'));
828
        $mform->addHelpButton('grading_method', 'gradingmethod', 'zoom');
829
        $mform->hideIf('grading_method', "{$gradefieldname}[modgrade_type]", 'eq', 'none');
830
    }
831
 
832
    /**
833
     * Fill in the current page data for this course.
834
     */
835
    public function definition_after_data() {
836
        parent::definition_after_data();
837
 
838
        // Get config.
839
        $config = get_config('zoom');
840
 
841
        if (!$config->allowrecordingchangeoption) {
842
            return;
843
        }
844
 
845
        $mform = $this->_form;
846
 
847
        if ($this->showschedulingprivilege) {
848
            $scheduleelement =& $mform->getElement('schedule_for');
849
            $values = $scheduleelement->getValue();
850
 
851
            if (empty($values)) {
852
                return;
853
            }
854
 
855
            $scheduleforuser = current($values);
856
            $zoomuser = zoom_get_user($scheduleforuser);
857
            $zoomuserid = $zoomuser->id;
858
        } else if (!empty($this->current->host_id)) {
859
            $zoomuserid = $this->current->host_id;
860
        } else {
861
            $zoomuserid = zoom_get_user_id(false);
862
        }
863
 
864
        $recordingelement =& $mform->getElement('option_auto_recording');
865
        $recordingelement->removeOptions();
866
 
867
        // Add auto recording options according to user settings.
868
        $options = [
869
            ZOOM_AUTORECORDING_NONE => get_string('autorecording_none', 'mod_zoom'),
870
        ];
871
 
872
        if ($zoomuserid !== false) {
873
            $recordingsettings = zoom_get_user_settings($zoomuserid)->recording;
874
        }
875
 
876
        if (!empty($recordingsettings->local_recording)) {
877
            $options[ZOOM_AUTORECORDING_LOCAL] = get_string('autorecording_local', 'mod_zoom');
878
        }
879
 
880
        if (!empty($recordingsettings->cloud_recording)) {
881
            $options[ZOOM_AUTORECORDING_CLOUD] = get_string('autorecording_cloud', 'mod_zoom');
882
        }
883
 
884
        $recordingelement->load($options);
885
    }
886
 
887
    /**
888
     * Allows module to modify the data returned by form get_data().
889
     * This method is also called in the bulk activity completion form.
890
     *
891
     * Only available on moodleform_mod.
892
     *
893
     * @param stdClass $data the form data to be modified.
894
     */
895
    public function data_postprocessing($data) {
896
        global $DB;
897
 
898
        parent::data_postprocessing($data);
899
 
900
        // Get config.
901
        $config = get_config('zoom');
902
 
903
        // If the admin did show the alternative hosts user picker.
904
        if ($config->showalternativehosts == ZOOM_ALTERNATIVEHOSTS_PICKER) {
905
            // If there was at least one alternative host selected, process these users.
906
            if (count($data->alternative_hosts_picker) > 0) {
907
                // Populate the alternative_hosts field with a concatenated string of email addresses.
908
                // This is done as this is the format which Zoom expects and alternative_hosts is the field to store the data
909
                // in mod_zoom.
910
                // The alternative host user picker is just an add-on to help teachers to fill this field.
911
                $data->alternative_hosts = implode(',', $data->alternative_hosts_picker);
912
 
913
                // If there wasn't any alternative host selected.
914
            } else {
915
                $data->alternative_hosts = '';
916
            }
917
 
918
            // Unfortunately, the host is not only able to add alternative hosts in Moodle with the user picker.
919
            // He is also able to add any alternative host with an email address in Zoom directly.
920
            // Thus, we have to get the latest list of alternative hosts from the DB again now,
921
            // identify the users who were not selectable at all in this form and append them to the list
922
            // of selected alternative hosts.
923
 
924
            // Get latest list of alternative hosts from the DB.
925
            $result = $DB->get_field('zoom', 'alternative_hosts', ['meeting_id' => $data->meeting_id], IGNORE_MISSING);
926
 
927
            // Proceed only if there is a field of alternative hosts already.
928
            if ($result !== false) {
929
                $alternativehostsdb = zoom_get_alternative_host_array_from_string($result);
930
 
931
                // Get selectable alternative host users based on the capability.
932
                $alternativehostschoices = zoom_get_selectable_alternative_hosts_list($this->context);
933
 
934
                // Iterate over the latest list of alternative hosts from the DB.
935
                foreach ($alternativehostsdb as $ah) {
936
                    // If the existing alternative host would not have been selectable.
937
                    if (!array_key_exists($ah, $alternativehostschoices)) {
938
                        // Add the alternative host to the alternative_hosts field.
939
                        if ($data->alternative_hosts == '') {
940
                            $data->alternative_hosts = $ah;
941
                        } else {
942
                            $data->alternative_hosts .= ',' . $ah;
943
                        }
944
                    }
945
                }
946
            }
947
        }
948
 
949
        // Add some postprocessing around the recurrence settings.
950
        if ($data->recurring) {
951
            // If "No fixed time" meeting selected, dont need repeat_interval and other options.
952
            if ($data->recurrence_type == ZOOM_RECURRINGTYPE_NOTIME) {
953
                unset($data->repeat_interval);
954
                // Unset end_times and end_date.
955
                unset($data->end_date_option);
956
                unset($data->end_times);
957
                unset($data->end_date_time);
958
            }
959
 
960
            // If weekly recurring is not selected, unset weekly options.
961
            if ($data->recurrence_type != ZOOM_RECURRINGTYPE_WEEKLY) {
962
                // Unset the weekly fields.
963
                $data = zoom_remove_weekly_options($data);
964
            }
965
 
966
            // If monthly recurring is not selected, unset monthly options.
967
            if ($data->recurrence_type != ZOOM_RECURRINGTYPE_MONTHLY) {
968
                // Unset the weekly fields.
969
                $data = zoom_remove_monthly_options($data);
970
            }
971
        }
972
 
973
        // Make sure registration is not enabled for No Fixed Time recurring meetings.
974
        if ($data->recurring && $data->recurrence_type == ZOOM_RECURRINGTYPE_NOTIME) {
975
            if (isset($data->registration) && $data->registration == ZOOM_REGISTRATION_AUTOMATIC) {
976
                $data->registration = ZOOM_REGISTRATION_OFF;
977
            }
978
        }
979
    }
980
 
981
    /**
982
     * Allows module to modify data returned by get_moduleinfo_data() or prepare_new_moduleinfo_data() before calling set_data()
983
     * This method is also called in the bulk activity completion form.
984
     *
985
     * Only available on moodleform_mod.
986
     *
987
     * @param array $defaultvalues passed by reference
988
     */
989
    public function data_preprocessing(&$defaultvalues) {
990
        global $DB;
991
 
992
        parent::data_preprocessing($defaultvalues);
993
 
994
        // Get config.
995
        $config = get_config('zoom');
996
 
997
        // If the admin wants to show the alternative hosts user picker.
998
        if ($config->showalternativehosts == ZOOM_ALTERNATIVEHOSTS_PICKER) {
999
            // If there is at least one alternative host set.
1000
            if (isset($defaultvalues['alternative_hosts']) && strlen($defaultvalues['alternative_hosts']) > 0) {
1001
                // Populate the alternative_hosts_picker field with an exploded array of email addresses.
1002
                // This is done as alternative_hosts is the field to store the data in mod_zoom and
1003
                // the alternative host user picker is just an add-on to help teachers to fill this field.
1004
 
1005
                // At this point, the alternative_hosts field might also contain users who are not selectable in the user picker
1006
                // as they aren't a member of the course or do not have a Moodle account.
1007
                // This does not matter as user picker default values which don't have a corresponding autocomplete suggestion
1008
                // will be simply ignored.
1009
                // When the form is submitted, these non-selectable alternative hosts will be added again in data_postprocessing().
1010
 
1011
                // According to the documentation, the Zoom API separates the email addresses with commas,
1012
                // but we also want to deal with semicolon-separated lists just in case.
1013
                $defaultvalues['alternative_hosts_picker'] = zoom_get_alternative_host_array_from_string(
1014
                    $defaultvalues['alternative_hosts']
1015
                );
1016
            }
1017
        }
1018
 
1019
        if ($config->defaulttrackingfields !== '') {
1020
            // Populate modedit form fields with previously saved values.
1021
            $defaulttrackingfields = zoom_clean_tracking_fields();
1022
            $tfrows = $DB->get_records('zoom_meeting_tracking_fields', ['meeting_id' => $defaultvalues['id']]);
1023
            foreach ($tfrows as $tfrow) {
1024
                $tfkey = $tfrow->tracking_field;
1025
                if (!empty($defaulttrackingfields[$tfkey])) {
1026
                    $defaultvalues[$tfkey] = $tfrow->value;
1027
                }
1028
            }
1029
        }
1030
    }
1031
 
1032
    /**
1033
     * More validation on form data.
1034
     * See documentation in lib/formslib.php.
1035
     *
1036
     * @param array $data
1037
     * @param array $files
1038
     * @return array
1039
     */
1040
    public function validation($data, $files) {
1041
        global $CFG, $USER;
1042
 
1043
        $errors = parent::validation($data, $files);
1044
 
1045
        $config = get_config('zoom');
1046
 
1047
        // Only check for scheduled meetings.
1048
        if (empty($data['recurring'])) {
1049
            // Make sure start date is in the future.
1050
            if ($data['start_time'] < time() && $data['meeting_id'] < 0) {
1051
                $errors['start_time'] = get_string('err_start_time_past', 'zoom');
1052
            }
1053
 
1054
            // Make sure duration is positive and no more than 150 hours.
1055
            if ($data['duration'] <= 0) {
1056
                $errors['duration'] = get_string('err_duration_nonpositive', 'zoom');
1057
            } else if ($data['duration'] > 150 * 60 * 60) {
1058
                $errors['duration'] = get_string('err_duration_too_long', 'zoom');
1059
            }
1060
        } else if ($data['recurring'] == 1 && $data['recurrence_type'] != ZOOM_RECURRINGTYPE_NOTIME) {
1061
            // Make sure start date time (first potential date of next meeting) is in the future.
1062
            if ($data['start_time'] < time() && $data['meeting_id'] < 0) {
1063
                $errors['start_time'] = get_string('err_start_time_past_recurring', 'zoom');
1064
            }
1065
 
1066
            // Make sure duration is positive and no more than 150 hours.
1067
            if ($data['duration'] <= 0) {
1068
                $errors['duration'] = get_string('err_duration_nonpositive', 'zoom');
1069
            } else if ($data['duration'] > 150 * 60 * 60) {
1070
                $errors['duration'] = get_string('err_duration_too_long', 'zoom');
1071
            }
1072
        }
1073
 
1074
        if (!empty($data['requirepasscode']) && empty($data['meetingcode'])) {
1075
            $errors['meetingcode'] = get_string('err_password_required', 'mod_zoom');
1076
        }
1077
 
1078
        if (isset($data['schedule_for']) && strtolower($data['schedule_for']) !== strtolower(zoom_get_api_identifier($USER))) {
1079
            $zoomuserid = zoom_get_user_id();
1080
            $scheduleusers = zoom_webservice()->get_schedule_for_users($zoomuserid);
1081
            $scheduleok = false;
1082
            foreach ($scheduleusers as $zuser) {
1083
                if (strtolower($zuser->email) === strtolower($data['schedule_for'])) {
1084
                    // Found a matching email address in the Zoom users list.
1085
                    $scheduleok = true;
1086
                    break;
1087
                }
1088
            }
1089
 
1090
            if (!$scheduleok) {
1091
                $errors['schedule_for'] = get_string('invalidscheduleuser', 'mod_zoom');
1092
            }
1093
        }
1094
 
1095
        // Supplementary feature: Alternative hosts.
1096
        // Only validate if the admin did not disable this feature completely.
1097
        if ($config->showalternativehosts != ZOOM_ALTERNATIVEHOSTS_DISABLE) {
1098
            // If the admin did show the plain input field.
1099
            if ($config->showalternativehosts == ZOOM_ALTERNATIVEHOSTS_INPUTFIELD) {
1100
                // Check if the listed alternative hosts are valid users on Zoom.
1101
                $alternativehosts = zoom_get_alternative_host_array_from_string($data['alternative_hosts']);
1102
                foreach ($alternativehosts as $alternativehost) {
1103
                    if (!(zoom_get_user($alternativehost))) {
1104
                        $errors['alternative_hosts'] = get_string('zoomerr_alternativehostusernotfound', 'zoom', $alternativehost);
1105
                        break;
1106
                    }
1107
                }
1108
 
1109
                // If the admin did show the user picker.
1110
            } else if ($config->showalternativehosts == ZOOM_ALTERNATIVEHOSTS_PICKER) {
1111
                // Check if the picked alternative hosts are valid users on Zoom.
1112
                foreach ($data['alternative_hosts_picker'] as $alternativehost) {
1113
                    if (!(zoom_get_user($alternativehost))) {
1114
                        $errors['alternative_hosts_picker'] =
1115
                                get_string('zoomerr_alternativehostusernotfound', 'zoom', $alternativehost);
1116
                        break;
1117
                    }
1118
                }
1119
            }
1120
        }
1121
 
1122
        // Supplementary feature: Encryption type.
1123
        // Only validate if the admin did not disable this feature completely.
1124
        if ($config->showencryptiontype != ZOOM_ENCRYPTION_DISABLE) {
1125
            // Check if given encryption type is valid.
1126
            if (
1127
                $data['option_encryption_type'] !== ZOOM_ENCRYPTION_TYPE_ENHANCED &&
1128
                $data['option_encryption_type'] !== ZOOM_ENCRYPTION_TYPE_E2EE
1129
            ) {
1130
                // This will not happen unless the user tampered with the form.
1131
                // Because of this, we skip adding this string to the language pack.
1132
                $errors['option_encryption_type_group'] = 'The submitted encryption type is not valid.';
1133
            }
1134
        }
1135
 
1136
        // Add validation for recurring meeting.
1137
        if ($data['recurring'] == 1) {
1138
            if ($data['recurrence_type'] == ZOOM_RECURRINGTYPE_WEEKLY) {
1139
                $weekdaynumbers = [];
1140
                for ($i = 1; $i <= 7; $i++) {
1141
                    $key = 'weekly_days_' . $i;
1142
                    if (!empty($data[$key])) {
1143
                        $weekdaynumbers[] = $i;
1144
                    }
1145
                }
1146
 
1147
                if (empty($weekdaynumbers)) {
1148
                    $errors['weekly_days_group'] = get_string('err_weekly_days', 'zoom');
1149
                }
1150
 
1151
                // For weekly, maximum is 12 weeks.
1152
                if ($data['repeat_interval'] > 12) {
1153
                    $errors['repeat_group'] = get_string('err_repeat_weekly_interval', 'zoom');
1154
                }
1155
            }
1156
 
1157
            if ($data['recurrence_type'] == ZOOM_RECURRINGTYPE_MONTHLY) {
1158
                // For monthly, max is 3 months.
1159
                if ($data['repeat_interval'] > 3) {
1160
                    $errors['repeat_group'] = get_string('err_repeat_monthly_interval', 'zoom');
1161
                }
1162
            }
1163
 
1164
            if ($data['recurrence_type'] != ZOOM_RECURRINGTYPE_NOTIME && $data['end_date_option'] == ZOOM_END_DATE_OPTION_BY) {
1165
                if ($data['end_date_time'] < time()) {
1166
                    $errors['radioenddate'] = get_string('err_end_date', 'zoom');
1167
                }
1168
 
1169
                if ($data['end_date_time'] < $data['start_time']) {
1170
                    $errors['radioenddate'] = get_string('err_end_date_before_start', 'zoom');
1171
                }
1172
            }
1173
        }
1174
 
1175
        return $errors;
1176
    }
1177
}