A bit of custom validation for this form

@param array $data An assoc array of field=>value
@param array $files An array of files
@return array
482887
public function validation($data, $files) {
        global $DB;

        $errors = parent::validation($data, $files);
        $eventtype = isset($data['eventtype']) ? $data['eventtype'] : null;
        $coursekey = ($eventtype == 'group') ? 'groupcourseid' : 'courseid';
        $courseid = (!empty($data[$coursekey])) ? $data[$coursekey] : null;
        $eventtypes = calendar_get_allowed_event_types($courseid);

        if (empty($eventtype) || !isset($eventtypes[$eventtype]) || $eventtypes[$eventtype] == false) {
            $errors['eventtype'] = get_string('invalideventtype', 'calendar');
        }

        if ($courseid && $courseid > 0) {
            if ($course = $DB->get_record('course', ['id' => $courseid])) {
                if ($data['timestart'] < $course->startdate) {
                    $errors['timestart'] = get_string('errorbeforecoursestart', 'calendar');
                }
            } else {
                $errors[$coursekey] = get_string('invalidcourse', 'error');
            }
        }

        if ($eventtype == 'course' && empty($courseid)) {
            $errors['courseid'] = get_string('selectacourse');
        }

        if ($eventtype == 'group' && (!empty($courseid) && empty($data['groupid']))) {
            $errors['groupcourseid'] = get_string('nogroups', 'core_group');
        }

        if ($eventtype == 'group' && empty($courseid)) {
            $errors['groupcourseid'] = get_string('selectacourse');
        }

        if ($data['duration'] == 1 && $data['timestart'] > $data['timedurationuntil']) {
            $errors['durationgroup'] = get_string('invalidtimedurationuntil', 'calendar');
        } else if ($data['duration'] == 2 && (trim($data['timedurationminutes']) == '' || $data['timedurationminutes'] < 1)) {
            $errors['durationgroup'] = get_string('invalidtimedurationminutes', 'calendar');
        }

        return $errors;
    }
1196557
private function isValidFileList(array $files)
    {
        Assertion::notEmpty($files, 'Files array can\'t be empty');

        $valid = false;

        foreach ($files as $file) {
            if ($this->isFileExisting($file)) {
                $valid = true;
            }
        }

        return $valid;
    }
358136
public function update(array $data, array $files = [])
    {
        if ($data) {
            $blueprint = $this->getBlueprint();

            // Process updated data through the object filters.
            $this->filterElements($data);

            // Get currently stored data.
            $elements = $this->getElements();

            // Merge existing object to the test data to be validated.
            $test = $blueprint->mergeData($elements, $data);

            // Validate and filter elements and throw an error if any issues were found.
            $blueprint->validate($test + ['storage_key' => $this->getStorageKey(), 'timestamp' => $this->getTimestamp()]);
            $data = $blueprint->filter($data, false, true);

            // Finally update the object.
            foreach ($blueprint->flattenData($data) as $key => $value) {
                if ($value === null) {
                    $this->unsetNestedProperty($key);
                } else {
                    $this->setNestedProperty($key, $value);
                }
            }

            // Store the changes
            $this->_changes = Utils::arrayDiffMultidimensional($this->getElements(), $elements);
        }

        if ($files && method_exists($this, 'setUpdatedMedia')) {
            $this->setUpdatedMedia($files);
        }

        return $this;
    }
588673
public function validation($data, $files) {
        global $DB;

        $errors = parent::validation($data, $files);

        // Add field validation check for duplicate idnumber.
        list($parentid, $contextid) = explode(',', $data['parent']);
        if (((string) $data['idnumber'] !== '') && !empty($contextid)) {
            $conditions = 'contextid = ? AND idnumber = ?';
            $params = [$contextid, $data['idnumber']];
            if (!empty($data['id'])) {
                $conditions .= ' AND id <> ?';
                $params[] = $data['id'];
            }
            if ($DB->record_exists_select('question_categories', $conditions, $params)) {
                $errors['idnumber'] = get_string('idnumbertaken', 'error');
            }
        }

        return $errors;
    }
943628
public function validation($data, $files) {

        $errors = array();

        if (array_key_exists('plugin', $this->_customdata) && is_object($this->_customdata['plugin'])) {
            $pluginerrors = $this->_customdata['plugin']->export_config_validation($data);
            if (is_array($pluginerrors)) {
                $errors = $pluginerrors;
            }
        }
        if (array_key_exists('caller', $this->_customdata) && is_object($this->_customdata['caller'])) {
            $callererrors = $this->_customdata['caller']->export_config_validation($data);
            if (is_array($callererrors)) {
                $errors = array_merge($errors, $callererrors);
            }
        }
        return $errors;
    }
1333378
public function define_validate_specific($data, $files) {
        $err = array();

        $data->param1 = str_replace("\r", '', $data->param1);

        // Check that we have at least 2 options.
        if (($options = explode("\n", $data->param1)) === false) {
            $err['param1'] = get_string('profilemenunooptions', 'admin');
        } else if (count($options) < 2) {
            $err['param1'] = get_string('profilemenutoofewoptions', 'admin');
        } else if (!empty($data->defaultdata) and !in_array($data->defaultdata, $options)) {
            // Check the default data exists in the options.
            $err['defaultdata'] = get_string('profilemenudefaultnotinoptions', 'admin');
        }
        return $err;
    }
1244925
public function validation($data, $files) {
        $errors = parent::validation($data, $files);
        if ($data['issueremail'] && !validate_email($data['issueremail'])) {
            $errors['issueremail'] = get_string('invalidemail');
        }
        if ($data['issuerurl'] && !preg_match('@^https?://.+@', $data['issuerurl'])) {
            $errors['issuerurl'] = get_string('invalidurl', 'badges');
        }
        if ($data['claimid'] && !preg_match('@^https?://.+@', $data['claimid'])) {
            $errors['claimid'] = get_string('invalidurl', 'badges');
        }
        return $errors;
    }
59404
public function validation($data, $files) {
        $errors = parent::validation($data, $files);

        if (!eventlist::validate_event_plugin($data['plugin'], $data['eventname'])) {
            $errors['eventname'] = get_string('errorincorrectevent', 'tool_monitor');
        }

        return $errors;
    }
347858
public function validation($data, $files) {
        $errors = parent::validation($data, $files);

        if (isset($data['rawname'])) {
            $newname = core_text::strtolower($data['rawname']);
            $tag = $this->_customdata['tag'];
            if ($tag->name != $newname) {
                // The name has changed, let's make sure it's not another existing tag.
                if (core_tag_tag::get_by_name($tag->tagcollid, $newname)) {
                    // Something exists already, so flag an error.
                    $errors['rawname'] = get_string('namesalreadybeeingused', 'tag');
                }
            }
        }

        return $errors;
    }
1209678
protected function validation_inner($data, $files) {

        $errors = array();

        // Iterate over all submitted dimensions (criteria).
        for ($i = 0; isset($data['dimensionid__idx_'.$i]); $i++) {

            $dimgrades = array();

            if (0 == strlen(trim($data['description__idx_'.$i.'_editor']['text']))) {
                // The description text is empty and this criterion will be deleted.
                continue;
            }

            // Make sure the levels grades are unique within the criterion.
            $atleastonelevel = false;
            for ($j = 0; isset($data['levelid__idx_'.$i.'__idy_'.$j]); $j++) {
                if (0 == strlen(trim($data['definition__idx_'.$i.'__idy_'.$j]))) {
                    // The level definition is empty and will not be saved.
                    continue;
                }
                $atleastonelevel = true;

                $levelgrade = $data['grade__idx_'.$i.'__idy_'.$j];

                if (isset($dimgrades[$levelgrade])) {
                    // This grade has already been set for another level.
                    $k = $dimgrades[$levelgrade];
                    $errors['level__idx_'.$i.'__idy_'.$j] = $errors['level__idx_'.$i.'__idy_'.$k] = get_string('mustbeunique',
                        'workshopform_rubric');
                } else {
                    $dimgrades[$levelgrade] = $j;
                }
            }
            if (!$atleastonelevel) {
                $errors['level__idx_'.$i.'__idy_0'] = get_string('mustdefinelevel', 'workshopform_rubric');
            }
        }

        return $errors;
    }
598873
public function validate(?array $data): array
    {
        $errorMsgs = [];
        foreach ($this->fieldsRuleProperties as $fieldName => $ruleProperties) {
            // Get value to validate
            if (isset($data[$fieldName])) {
                $value = $data[$fieldName];

                // Trim all values unless explicitly set to not
                if (is_string($value) && (!isset($ruleProperties['trim']) || $ruleProperties['trim'] === true)) {
                    $value = trim($value);
                }
                // allow a nullable value to be added as validated data
            } elseif (!empty($ruleProperties['nullable']) && array_key_exists($fieldName, $data)) {
                $value = null;
                // Don't validate empty values that are not set and not required
            } elseif (empty($ruleProperties['required']) && empty($ruleProperties['nonEmpty'])) {
                continue;
            } else {
                // Empty string as default (not null because that adds complexity to checks)
                $value = '';
            }

            // Validate value against each of the fields' rules
            $errorMsg = $this->validateValue($value, $ruleProperties);

            // If field has any error messages, add to error array, otherwise add value to validated data
            if ($errorMsg) {
                $errorMsgs[$fieldName] = $errorMsg;
            } else {
                $this->validatedData[$fieldName] = $value;
            }
        }

        return $errorMsgs;
    }
275233
public function config_form_validation(array $data, $files = array()) : array {
        $options = preg_split("/\s*\n\s*/", trim($data['configdata']['options']));
        $errors = [];
        if (!$options || count($options) < 2) {
            $errors['configdata[options]'] = get_string('errornotenoughoptions', 'customfield_select');
        } else if (!empty($data['configdata']['defaultvalue'])) {
            $defaultkey = array_search($data['configdata']['defaultvalue'], $options);
            if ($defaultkey === false) {
                $errors['configdata[defaultvalue]'] = get_string('errordefaultvaluenotinlist', 'customfield_select');
            }
        }
        return $errors;
    }
866920
protected function extra_validation($data, $files, array &$errors) {
        $overrides = $this->get_role_overrides_from_data($data);

        // Check role overrides to ensure that:
        // - roles are unique; and
        // - specifeid retention periods are numeric.
        $seenroleids = [];
        foreach ($overrides as $id => $override) {
            $override->purposeid = 0;
            $persistent = new \tool_dataprivacy\purpose_override($override->id, $override);

            if (isset($seenroleids[$persistent->get('roleid')])) {
                $errors["roleoverride_roleid[{$id}]"] = get_string('duplicaterole');
            }
            $seenroleids[$persistent->get('roleid')] = true;

            $errors = array_merge($errors, $persistent->get_errors());
        }

        return $errors;
    }
1277337
public function define_validate_specific($data, $files) {
        $errors = array();

        // Make sure the start year is not greater than the end year.
        if ($data->param1 > $data->param2) {
            $errors['param1'] = get_string('startyearafterend', 'profilefield_datetime');
        }

        return $errors;
    }
308720
public function validate(array $data)
    {
        $errors = [];

        if (empty($data['name'])) {
            $errors[] = ['path' => '/name', 'message' => 'name can not be empty.'];
        }

        if (empty($data['type'])) {
            $errors[] = ['path' => '/type', 'message' => 'type can not be empty.'];
        }

        if (empty($data['scheduledDate'])) {
            $errors[] = ['path' => '/scheduledDate', 'message' => 'scheduledDate can not be empty.'];
        }

        return $errors;
    }
749600
function validation($data, $files) {
        $errors = parent::validation($data, $files);

        if ($data['scaleid'] < 1) {
            $errors['scaleid'] = get_string('required');
        }

        if (!empty($data['standard']) and $scale = grade_scale::fetch(array('id'=>$data['scaleid']))) {
            if (!empty($scale->courseid)) {
                //TODO: localize
                $errors['scaleid'] = 'Can not use custom scale in global outcome!';
            }
        }

        return $errors;
    }
1347317
function validation($data, $files) {
        global $DB;

        $errors = parent::validation($data, $files);

        // Add field validation check for duplicate shortname.
        if ($course = $DB->get_record('course', array('shortname' => $data['shortname']), '*', IGNORE_MULTIPLE)) {
            if (empty($data['id']) || $course->id != $data['id']) {
                $errors['shortname'] = get_string('shortnametaken', '', $course->fullname);
            }
        }

        // Add field validation check for duplicate idnumber.
        if (!empty($data['idnumber']) && (empty($data['id']) || $this->course->idnumber != $data['idnumber'])) {
            if ($course = $DB->get_record('course', array('idnumber' => $data['idnumber']), '*', IGNORE_MULTIPLE)) {
                if (empty($data['id']) || $course->id != $data['id']) {
                    $errors['idnumber'] = get_string('courseidnumbertaken', 'error', $course->fullname);
                }
            }
        }

        if ($errorcode = course_validate_dates($data)) {
            $errors['enddate'] = get_string($errorcode, 'error');
        }

        $errors = array_merge($errors, enrol_course_edit_validation($data, $this->context));

        $courseformat = course_get_format((object)array('format' => $data['format']));
        $formaterrors = $courseformat->edit_form_validation($data, $files, $errors);
        if (!empty($formaterrors) && is_array($formaterrors)) {
            $errors = array_merge($errors, $formaterrors);
        }

        // Add the custom fields validation.
        $handler = core_course\customfield\course_handler::create();
        $errors  = array_merge($errors, $handler->instance_form_validation($data, $files));

        return $errors;
    }