Resolves $ref property and validates resulted schema
@param $document_data
@param $data
@param array $data_pointer
@param array $parent_data_pointer
@param ISchema $document
@param stdClass $schema
@param ValidationResult $bag
@return bool
508568
protected function validateRef(&$document_data, &$data, array $data_pointer, array $parent_data_pointer, ISchema $document, stdClass $schema, ValidationResult $bag): bool
    {
        $ref = $schema->{'$ref'};

        // $vars
        if ($this->varsSupport) {
            $ref = URI::parseTemplate($ref, $this->getVars($document_data, $data_pointer, $schema));
        }

        $map_used = $this->mapSupport && property_exists($schema, Schema::MAP_PROP);

        // $map
        if ($map_used) {
            unset($data);
            $data = $this->deepClone($schema->{Schema::MAP_PROP});
            $this->resolveVars($data,$document_data, $data_pointer);

            unset($document_data);
            $document_data = &$data;

            if ($data_pointer) {
                $parent_data_pointer = array_merge($parent_data_pointer, $data_pointer);
                $data_pointer = [];
            }
        }

        // Check if is relative json pointer
        if ($relative = JsonPointer::parseRelativePointer($ref, true)) {
            if (!JsonPointer::isEscapedPointer($ref)) {
                throw new InvalidJsonPointerException($ref);
            }

            $schema = JsonPointer::getDataByRelativePointer(
                $document->resolve(),
                $relative,
                $schema->{Schema::PATH_PROP} ?? [],
                $this
            );
            if ($schema === $this) {
                throw new InvalidJsonPointerException($ref);
            }

            return $this->validateSchema($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
        }

        // Check if is a json pointer relative to this document
        if (isset($ref[0]) && $ref[0] === '#') {
            $pointer = substr($ref, 1);
            if (JsonPointer::isPointer($pointer)) {
                if (!JsonPointer::isEscapedPointer($pointer)) {
                    throw new InvalidJsonPointerException($pointer);
                }
                $schema = JsonPointer::getDataByPointer($document->resolve(), $pointer, $this);
                if ($schema === $this) {
                    throw new InvalidJsonPointerException($pointer);
                }

                return $this->validateSchema($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
            }
            unset($pointer);
        }

        // Merge uris
        $ref = URI::merge($ref, $schema->{Schema::BASE_ID_PROP} ?? '', true);

        list($base_ref, $fragment) = explode('#', $ref, 2);

        if (JsonPointer::isPointer($fragment)) {
            if (!JsonPointer::isEscapedPointer($fragment)) {
                throw new InvalidJsonPointerException($fragment);
            }

            // try to resolve locally
            $schema = $document->resolve($base_ref . '#');

            if ($schema === null) {
                if (!$this->loader) {
                    throw new SchemaNotFoundException($base_ref);
                }
                // use loader
                $document = $this->loader->loadSchema($base_ref);
                if (!($document instanceof ISchema)) {
                    throw new SchemaNotFoundException($base_ref);
                }

                if ($fragment === '' || $fragment === '/') {
                    $schema = $document->resolve();
                } else {
                    $schema = JsonPointer::getDataByPointer($document->resolve(), $fragment, $this);
                    if ($schema === $this) {
                        throw new InvalidJsonPointerException($fragment);
                    }
                }

                if (!$map_used) {
                    unset($document_data);
                    $document_data = &$data;
                    if ($data_pointer) {
                        $parent_data_pointer = array_merge($parent_data_pointer, $data_pointer);
                        $data_pointer = [];
                    }
                }
            } else {
                if ($fragment !== '' && $fragment !== '/') {
                    $schema = JsonPointer::getDataByPointer($schema, $fragment, $this);
                    if ($schema === $this) {
                        throw new InvalidJsonPointerException($fragment);
                    }
                }
            }

            return $this->validateSchema($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
        }

        // Not a json pointer
        $schema = $document->resolve($ref);
        if ($schema !== null) {
            return $this->validateSchema($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
        }

        if (!$this->loader) {
            throw new SchemaNotFoundException($base_ref);
        }
        // use loader
        $document = $this->loader->loadSchema($base_ref);
        if (!($document instanceof ISchema)) {
            throw new SchemaNotFoundException($base_ref);
        }

        $schema = $document->resolve($ref);

        if (!$map_used) {
            unset($document_data);
            $document_data = &$data;
            if ($data_pointer) {
                $parent_data_pointer = array_merge($parent_data_pointer, $data_pointer);
                $data_pointer = [];
            }
        }

        return $this->validateSchema($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
    }
575656
protected function validateObjectProperty($property, Schema $schema)
    {
        list($value, $pointer) = $this->currentContext();
        $this->pushContext(array(
            $value->get($property),
            $pointer->joinAtoms($property)
        ));
        $result = $schema->accept($this);
        $this->popContext();

        return $result;
    }
344344
function validation($data, $files) {
        global $COURSE, $DB, $CFG;

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

        $name = trim($data['name']);
        if (isset($data['idnumber'])) {
            $idnumber = trim($data['idnumber']);
        } else {
            $idnumber = '';
        }
        if ($data['id'] and $group = $DB->get_record('groups', array('id'=>$data['id']))) {
            if (core_text::strtolower($group->name) != core_text::strtolower($name)) {
                if (groups_get_group_by_name($COURSE->id,  $name)) {
                    $errors['name'] = get_string('groupnameexists', 'group', $name);
                }
            }
            if (!empty($idnumber) && $group->idnumber != $idnumber) {
                if (groups_get_group_by_idnumber($COURSE->id, $idnumber)) {
                    $errors['idnumber']= get_string('idnumbertaken');
                }
            }

            if ($data['enrolmentkey'] != '') {
                $errmsg = '';
                if (!empty($CFG->groupenrolmentkeypolicy) && $group->enrolmentkey !== $data['enrolmentkey']
                        && !check_password_policy($data['enrolmentkey'], $errmsg)) {
                    // Enforce password policy when the password is changed.
                    $errors['enrolmentkey'] = $errmsg;
                } else {
                    // Prevent twice the same enrolment key in course groups.
                    $sql = "SELECT id FROM {groups} WHERE id <> :groupid AND courseid = :courseid AND enrolmentkey = :key";
                    $params = array('groupid' => $data['id'], 'courseid' => $COURSE->id, 'key' => $data['enrolmentkey']);
                    if ($DB->record_exists_sql($sql, $params)) {
                        $errors['enrolmentkey'] = get_string('enrolmentkeyalreadyinuse', 'group');
                    }
                }
            }

        } else if (groups_get_group_by_name($COURSE->id, $name)) {
            $errors['name'] = get_string('groupnameexists', 'group', $name);
        } else if (!empty($idnumber) && groups_get_group_by_idnumber($COURSE->id, $idnumber)) {
            $errors['idnumber']= get_string('idnumbertaken');
        } else if ($data['enrolmentkey'] != '') {
            $errmsg = '';
            if (!empty($CFG->groupenrolmentkeypolicy) && !check_password_policy($data['enrolmentkey'], $errmsg)) {
                // Enforce password policy.
                $errors['enrolmentkey'] = $errmsg;
            } else if ($DB->record_exists('groups', array('courseid' => $COURSE->id, 'enrolmentkey' => $data['enrolmentkey']))) {
                // Prevent the same enrolment key from being used multiple times in course groups.
                $errors['enrolmentkey'] = get_string('enrolmentkeyalreadyinuse', 'group');
            }
        }

        return $errors;
    }
994672
protected function validateBySchema(DOMDocument $document, $schema)
    {
        if (!file_exists($schema) || !is_file($schema)) {
            throw new RuntimeException(
                "Validation of XML document cannot be performed, file '{$schema}' does not exist."
            );
        }

        $additionalErrors = array();
        $pathInfo = pathinfo($schema);
        switch ($pathInfo['extension']) {
            case 'xsd':
                $document->schemaValidate($schema);
                break;
            case 'rng':
                $document->relaxNGValidate($schema);
                break;
            case 'xsl':
                $additionalErrors = $this->schematronValidate($document, $schema);
                break;
            default:
                throw new RuntimeException(
                    'Validator is capable of handling ISO Schematron (as XSLT stylesheet), ' .
                    "XSD and RELAX NG schema files, ending in .xsl, .xsd or .rng.\n" .
                    "File '{$schema}' does not seem to be either of these."
                );
        }

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

        if (!array_key_exists('setting_root_filename', $errors)) {
            if (trim($data['setting_root_filename']) == '') {
                $errors['setting_root_filename'] = get_string('errorfilenamerequired', 'backup');
            } else if (strlen(trim($data['setting_root_filename'])) > 255) {
                $errors['setting_root_filename'] = get_string('errorfilenametoolong', 'backup');
            } else if (!preg_match('#\.mbz$#i', $data['setting_root_filename'])) {
                $errors['setting_root_filename'] = get_string('errorfilenamemustbezip', 'backup');
            }
        }

        return $errors;
    }
1130733
function resolveRef(schemaObj, resolvedValues) {
            // the array store referenced value
            var refVal = schemaObj.refVal;
            // the map store full ref id and index of the referenced value in refVal
            // example: { 'test#definitions/option' : 1, 'test#definitions/repo' : 2 }
            var refs = schemaObj.refs;
            // the map to store schema value with sub reference
            var subRefs = {};

            _.forEach(refs, function (index, refId) {
                // if reference id already resolved then continue the loop
                if (refId in resolvedValues) {
                    return true; // continue
                }

                var refValue = refVal[index];
                // if no further nested reference, add to resolved map
                if (_.isEmpty(refValue.refs)) {
                    resolvedValues[refId] = refValue;
                    return true;
                }

                // add schema value with sub reference to map to resolve later
                subRefs[refId] = refValue;
            });

            // resolve sub reference recursively
            _.forEach(subRefs, function (subRef, refId) {
                resolvedValues[refId] = 1;
                resolvedValues[refId] = resolveRef(subRef, resolvedValues);
            });

            return schemaObj.schema;
        }
179160
private function validateChildClass(NodeInterface $parentNode, ClassMetadata $class)
    {
        $parentClass = $this->documentClassMapper->getClassName($this->dm, $parentNode);

        if (null === $parentClass) {
            return;
        }

        $metadata = $this->dm->getClassMetadata($parentClass);
        $metadata->assertValidChildClass($class);
    }
832608
private function getSchemaValidationFile(\DOMDocument $document)
    {
        $firstChild = $this->getFirstChild($document);
        // @codeCoverageIgnoreStart
        if (false === $firstChild) {
            return false;
        }
        // @codeCoverageIgnoreEnd

        $attribute = $firstChild->getAttribute('xsi:noNamespaceSchemaLocation');

        if (empty($attribute)) {
            return false;
        }

        return $attribute;
    }
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;
    }
283045
public function resolve(Document $document, Uri $ref, $name, $depth, PropertyInterface $property = null)
    {
        $uri = $this->resolver->resolve($document->getBaseUri(), $ref);

        if (isset($this->objects[$uri->toString()])) {
            return $this->objects[$uri->toString()];
        }

        if ($property === null) {
            $property = new PropertyType();
            $property->setRef($uri->toString());
        }

        $this->objects[$uri->toString()] = $property;

        $doc  = $this->getDocument($uri, $document);
        $doc->getProperty($uri->getFragment(), $name, $depth, $property);

        return $property;
    }
904261
public function validation($data, $files) {
        global $USER;
        $errors = [];

        $validrequesttypes = [
            api::DATAREQUEST_TYPE_EXPORT,
            api::DATAREQUEST_TYPE_DELETE
        ];
        if (!in_array($data['type'], $validrequesttypes)) {
            $errors['type'] = get_string('errorinvalidrequesttype', 'tool_dataprivacy');
        }

        if (api::has_ongoing_request($data['userid'], $data['type'])) {
            $errors['type'] = get_string('errorrequestalreadyexists', 'tool_dataprivacy');
        }

        // Check if current user can create data deletion request.
        $userid = $data['userid'];
        if ($data['type'] == api::DATAREQUEST_TYPE_DELETE) {
            if ($userid == $USER->id) {
                if (!api::can_create_data_deletion_request_for_self()) {
                    $errors['type'] = get_string('errorcannotrequestdeleteforself', 'tool_dataprivacy');
                }
            } else if (!api::can_create_data_deletion_request_for_other()
                && !api::can_create_data_deletion_request_for_children($userid)) {
                $errors['type'] = get_string('errorcannotrequestdeleteforother', 'tool_dataprivacy');
            }
        }

        return $errors;
    }
985
function validation($data, $files) {
        global $COURSE;

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

        if (array_key_exists('idnumber', $data)) {
            if ($data['id']) {
                $grade_item = new grade_item(array('id'=>$data['id'], 'courseid'=>$data['courseid']));
            } else {
                $grade_item = null;
            }
            if (!grade_verify_idnumber($data['idnumber'], $COURSE->id, $grade_item, null)) {
                $errors['idnumber'] = get_string('idnumbertaken');
            }
        }

        return $errors;
    }
104360
public function validation($data, $files) {
        global $CFG, $DB, $USER;

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

        // Validate course association.
        if (!empty($data['courseassoc'])) {
            $coursecontext = context::instance_by_id($data['courseassoc']);

            if ($coursecontext->contextlevel != CONTEXT_COURSE) {
                $errors['courseassoc'] = get_string('error');
            }
        }

        // Validate mod association.
        if (!empty($data['modassoc'])) {
            $modcontextid = $data['modassoc'];
            $modcontext = context::instance_by_id($modcontextid);

            if ($modcontext->contextlevel == CONTEXT_MODULE) {
                // Get context of the mod's course.
                $coursecontext = $modcontext->get_course_context(true);

                // Ensure only one course is associated.
                if (!empty($data['courseassoc'])) {
                    if ($data['courseassoc'] != $coursecontext->id) {
                        $errors['modassoc'] = get_string('onlyassociateonecourse', 'blog');
                    }
                } else {
                    $data['courseassoc'] = $coursecontext->id;
                }
            } else {
                $errors['modassoc'] = get_string('error');
            }
        }

        if ($errors) {
            return $errors;
        }
        return true;
    }
126366
protected function validateProperties(&$document_data, &$data, array $data_pointer, array $parent_data_pointer, ISchema $document, $schema, ValidationResult $bag, array $defaults = null): bool
    {
        $type = $this->helper->type($data, true);
        if ($type === 'null' || $type === 'boolean') {
            return true;
        }

        $valid = false;

        switch ($type) {
            case 'string':
                $valid = $this->validateString($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
                break;
            case 'number':
            case 'integer':
                $valid = $this->validateNumber($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
                break;
            case 'array':
                $valid = $this->validateArray($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag);
                break;
            case 'object':
                $valid = $this->validateObject($document_data, $data, $data_pointer, $parent_data_pointer, $document, $schema, $bag, $defaults);
                // Setup unused defaults
                if (!$valid && $defaults) {
                    $this->setObjectDefaults($data, $defaults);
                }
                break;
        }

        if (!$valid && $bag->isFull()) {
            return false;
        }

        if (property_exists($schema, 'format') && $this->formats) {
            if (!is_string($schema->format)) {
                throw new SchemaKeywordException(
                    $schema,
                    'format',
                    $schema->format,
                    "'format' keyword must be a string, " . gettype($schema->format) . ", given"
                );
            }
            $formatObj = $this->formats->get($type, $schema->format);
            if ($formatObj === null && $type === 'integer') {
                $formatObj = $this->formats->get('number', $schema->format);
            }
            if ($formatObj !== null) {
                if (!$formatObj->validate($data)) {
                    $valid = false;
                    $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'format', [
                        'type' => $type,
                        'format' => $schema->format,
                    ]));
                    if ($bag->isFull()) {
                        return false;
                    }
                }
            }
            unset($formatObj);
        }

        return $valid;
    }
442735
private function parseRelationshipLinks(
        SchemaInterface $parentSchema,
        $parentData,
        string $name,
        array $description
    ): array {
        $addSelfLink    = $description[SchemaInterface::RELATIONSHIP_LINKS_SELF] ??
            $parentSchema->isAddSelfLinkInRelationshipByDefault($name);
        $addRelatedLink = $description[SchemaInterface::RELATIONSHIP_LINKS_RELATED] ??
            $parentSchema->isAddRelatedLinkInRelationshipByDefault($name);
        \assert(\is_bool($addSelfLink) === true || $addSelfLink instanceof LinkInterface);
        \assert(\is_bool($addRelatedLink) === true || $addRelatedLink instanceof LinkInterface);

        $schemaLinks = $description[SchemaInterface::RELATIONSHIP_LINKS] ?? [];
        \assert(\is_array($schemaLinks));

        // if `self` or `related` link was given as LinkInterface merge it with the other links
        $extraSchemaLinks = null;
        if (\is_bool($addSelfLink) === false) {
            $extraSchemaLinks[LinkInterface::SELF] = $addSelfLink;
            $addSelfLink                           = false;
        }
        if (\is_bool($addRelatedLink) === false) {
            $extraSchemaLinks[LinkInterface::RELATED] = $addRelatedLink;
            $addRelatedLink                           = false;
        }
        if (empty($extraSchemaLinks) === false) {
            // IDE do not understand it's defined without he line below
            \assert(isset($extraSchemaLinks));
            $schemaLinks = \array_merge($extraSchemaLinks, $schemaLinks);
            unset($extraSchemaLinks);
        }
        \assert(\is_bool($addSelfLink) === true && \is_bool($addRelatedLink) === true);

        $hasLinks = $addSelfLink === true || $addRelatedLink === true || empty($schemaLinks) === false;
        $links    = $hasLinks === true ?
            $this->parseLinks($parentSchema, $parentData, $name, $schemaLinks, $addSelfLink, $addRelatedLink) : null;

        return [$hasLinks, $links];
    }
442831
protected function validateNumber(/** @noinspection PhpUnusedParameterInspection */
        &$document_data, &$data, array $data_pointer, array $parent_data_pointer, ISchema $document, $schema, ValidationResult $bag): bool
    {
        $ok = true;

        // minimum, exclusiveMinimum
        if (property_exists($schema, 'minimum')) {
            if (!is_int($schema->minimum) && !is_float($schema->minimum)) {
                throw new SchemaKeywordException(
                    $schema,
                    'minimum',
                    $schema->minimum,
                    "'minimum' keyword must be an integer or a float, " . gettype($schema->minimum) . " given"
                );
            }

            $exclusive = false;
            if (property_exists($schema, 'exclusiveMinimum')) {
                if (!is_bool($schema->exclusiveMinimum)) {
                    throw new SchemaKeywordException(
                        $schema,
                        'exclusiveMinimum',
                        $schema->exclusiveMinimum,
                        "'exclusiveMinimum' keyword must be a boolean if 'minimum' keyword is present, " . gettype($schema->exclusiveMinimum) . " given"
                    );
                }
                $exclusive = $schema->exclusiveMinimum;
            }

            if ($exclusive && $data == $schema->minimum) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'exclusiveMinimum', [
                    'min' => $schema->minimum
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            } elseif ($data < $schema->minimum) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'minimum', [
                    'min' => $schema->minimum
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            }
        } elseif (property_exists($schema, 'exclusiveMinimum')) {
            if (!is_int($schema->exclusiveMinimum) && !is_float($schema->exclusiveMinimum)) {
                throw new SchemaKeywordException(
                    $schema,
                    'exclusiveMinimum',
                    $schema->exclusiveMinimum,
                    "'exclusiveMinimum' keyword must be an integer or a float if 'minimum' keyword is not present, " . gettype($schema->exclusiveMinimum) . " given"
                );
            }
            if ($data <= $schema->exclusiveMinimum) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'exclusiveMinimum', [
                    'min' => $schema->exclusiveMinimum
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            }
        }

        // maximum, exclusiveMaximum
        if (property_exists($schema, 'maximum')) {
            if (!is_int($schema->maximum) && !is_float($schema->maximum)) {
                throw new SchemaKeywordException(
                    $schema,
                    'maximum',
                    $schema->maximum,
                    "'maximum' keyword must be an integer or a float, " . gettype($schema->maximum) . " given"
                );
            }

            $exclusive = false;
            if (property_exists($schema, 'exclusiveMaximum')) {
                if (!is_bool($schema->exclusiveMaximum)) {
                    throw new SchemaKeywordException(
                        $schema,
                        'exclusiveMaximum',
                        $schema->exclusiveMaximum,
                        "'exclusiveMaximum' keyword must be a boolean is 'maximum' keyword is present, " . gettype($schema->exclusiveMaximum) . " given"
                    );
                }
                $exclusive = $schema->exclusiveMaximum;
            }

            if ($exclusive && $data == $schema->maximum) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'exclusiveMaximum', [
                    'max' => $schema->maximum
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            } elseif ($data > $schema->maximum) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'maximum', [
                    'max' => $schema->maximum
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            }
        } elseif (property_exists($schema, 'exclusiveMaximum')) {
            if (!is_int($schema->exclusiveMaximum) && !is_float($schema->exclusiveMaximum)) {
                throw new SchemaKeywordException(
                    $schema,
                    'exclusiveMaximum',
                    $schema->exclusiveMaximum,
                    "'exclusiveMaximum' keyword must be an integer or a float if 'maximum' keyword is not present, " . gettype($schema->exclusiveMaximum) . " given"
                );
            }
            if ($data >= $schema->exclusiveMaximum) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'exclusiveMaximum', [
                    'max' => $schema->exclusiveMaximum
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            }
        }

        // multipleOf
        if (property_exists($schema, 'multipleOf')) {
            if (!is_int($schema->multipleOf) && !is_float($schema->multipleOf)) {
                throw new SchemaKeywordException(
                    $schema,
                    'multipleOf',
                    $schema->multipleOf,
                    "'multipleOf' keyword must be an integer or a float, " . gettype($schema->multipleOf) . " given"
                );
            }
            if ($schema->multipleOf <= 0) {
                throw new SchemaKeywordException(
                    $schema,
                    'multipleOf',
                    $schema->multipleOf,
                    "'multipleOf' keyword must be greater than 0"
                );
            }
            if (!$this->helper->isMultipleOf($data, $schema->multipleOf)) {
                $ok = false;
                $bag->addError(new ValidationError($data, $data_pointer, $parent_data_pointer, $schema, 'multipleOf', [
                    'divisor' => $schema->multipleOf
                ]));
                if ($bag->isFull()) {
                    return false;
                }
            }
        }

        return $ok;
    }
1348168
public boolean canValidate(Document doc) {
        XsdSchema schema = schemaMappingStrategy.getSchema(schemas, doc);
        return schema != null;
    }