-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathXmlMatchesXsdForV9.php
More file actions
129 lines (106 loc) · 3.29 KB
/
XmlMatchesXsdForV9.php
File metadata and controls
129 lines (106 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
/*
* This file is part of PHP CS Fixer / PHPUnit Constraint XmlMatchesXsd.
*
* (c) SpacePossum
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\PhpunitConstraintXmlMatchesXsd\Constraint;
use PHPUnit\Framework\Constraint\Constraint;
/**
* @author SpacePossum
*
* @internal
*/
final class XmlMatchesXsdForV9 extends Constraint
{
/**
* @var string[]
*/
private $xmlConstraintErrors = [];
/**
* @var string
*/
private $xsd;
/**
* @param string $xsd
*/
public function __construct($xsd)
{
// replace first only
$needle = 'http://www.w3.org/2001/xml.xsd';
if (false !== $pos = strpos($xsd, $needle)) {
$xsd = substr_replace($xsd, 'file:///'.str_replace('\\', '/', __DIR__).'/xml.xsd', $pos, \strlen($needle));
}
$this->xsd = $xsd;
}
public function toString(): string
{
return 'matches XSD';
}
protected function failureDescription($other): string
{
if (\is_string($other)) {
return \sprintf("%s %s.\n%s", $other, $this->toString(), implode("\n", $this->xmlConstraintErrors));
}
if (\is_object($other)) {
$type = \sprintf('%s#%s', \get_class($other), method_exists($other, '__toString') ? $other->__toString() : '');
} elseif (null === $other) {
$type = 'null';
} else {
$type = \gettype($other).'#'.$other;
}
return $type.' '.$this->toString();
}
protected function matches($other): bool
{
return \is_string($other)
? $this->stringMatches($other)
: false;
}
/**
* @param string $other
*
* @return bool
*/
private function stringMatches($other)
{
$internalErrors = libxml_use_internal_errors(true);
libxml_clear_errors();
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->validateOnParse = true;
if (!@$dom->loadXML($other, LIBXML_NONET | (\defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
$this->setXMLConstraintErrors();
libxml_clear_errors();
libxml_use_internal_errors($internalErrors);
return false;
}
$dom->normalizeDocument();
libxml_clear_errors();
if (false === $result = @$dom->schemaValidateSource($this->xsd)) {
$this->setXMLConstraintErrors();
}
libxml_clear_errors();
libxml_use_internal_errors($internalErrors);
return $result;
}
private function setXMLConstraintErrors()
{
foreach (libxml_get_errors() as $error) {
if (LIBXML_ERR_WARNING === $error->level) {
$level = 'warning ';
} elseif (LIBXML_ERR_ERROR === $error->level) {
$level = 'error ';
} elseif (LIBXML_ERR_FATAL === $error->level) {
$level = 'fatal ';
} else {
$level = '';
}
$this->xmlConstraintErrors[] = \sprintf('[%s%s] %s (line %d, column %d).', $level, $error->code, trim($error->message), $error->line, $error->column);
}
}
}