Passed
Push — master ( 0aaddc...edae55 )
by Tim
01:50
created

SchemaValidatableElementTrait::getSchemaFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XML;
6
7
use DOMDocument;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\XML\Exception\IOException;
10
use SimpleSAML\XML\Exception\SchemaViolationException;
11
12
use function array_unique;
13
use function defined;
14
use function file_exists;
15
use function implode;
16
use function libxml_get_errors;
17
use function restore_error_handler;
18
use function set_error_handler;
19
use function sprintf;
20
use function trim;
21
22
/**
23
 * trait class to be used by all the classes that implement the SchemaValidatableElementInterface
24
 *
25
 * @package simplesamlphp/xml-common
26
 */
27
trait SchemaValidatableElementTrait
28
{
29
    /**
30
     * Validate the given DOMDocument against the schema set for this element
31
     *
32
     * @return \DOMDocument
33
     * @throws \SimpleSAML\XML\Exception\SchemaViolationException
34
     */
35
    public static function schemaValidate(DOMDocument $document): DOMDocument
36
    {
37
        $schemaFile = self::getSchemaFile();
38
39
        // Dirty trick to catch the warnings emitted by XML-DOMs schemaValidate
40
        // This will turn the warning into an exception
41
        set_error_handler(static function (int $errno, string $errstr): never {
42
            throw new SchemaViolationException($errstr, $errno);
43
        }, E_WARNING);
44
45
        try {
46
            $result = $document->schemaValidate($schemaFile);
47
        } finally {
48
            // Restore the error handler, whether we throw an exception or not
49
            restore_error_handler();
50
        }
51
52
        $msgs = [];
53
        if ($result === false) {
54
            foreach (libxml_get_errors() as $err) {
55
                $msgs[] = trim($err->message) . ' on line ' . $err->line;
56
            }
57
58
            throw new SchemaViolationException(sprintf(
59
                "XML schema validation errors:\n - %s",
60
                implode("\n - ", array_unique($msgs)),
61
            ));
62
        }
63
64
        return $document;
65
    }
66
67
68
    /**
69
     * Get the schema file that can validate this element.
70
     * The path must be relative to the project's base directory.
71
     *
72
     * @return string
73
     */
74
    public static function getSchemaFile(): string
75
    {
76
        if (defined('static::SCHEMA')) {
77
            $schemaFile = static::SCHEMA;
1 ignored issue
show
Bug introduced by
The constant SimpleSAML\XML\SchemaVal...bleElementTrait::SCHEMA was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
78
        }
79
80
        Assert::true(file_exists($schemaFile), sprintf("File not found: %s", $schemaFile), IOException::class);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $schemaFile does not seem to be defined for all execution paths leading up to this point.
Loading history...
81
        return $schemaFile;
82
    }
83
}
84