Skip to content

Commit 7b9bb4b

Browse files
authored
Initial implementation (#1)
1 parent 7f4bacc commit 7b9bb4b

File tree

10 files changed

+3033
-12
lines changed

10 files changed

+3033
-12
lines changed

.travis.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ cache:
1010
language: php
1111

1212
php:
13-
- 5.5
1413
- 5.6
1514
- 7.0
1615
- 7.1
@@ -35,6 +34,7 @@ before_install:
3534

3635
install:
3736
- composer update $DEFAULT_COMPOSER_FLAGS $COMPOSER_FLAGS
37+
- composer info -D | sort
3838

3939
script:
4040
- vendor/bin/phpunit
@@ -44,8 +44,11 @@ jobs:
4444
-
4545
stage: Static Code Analysis
4646
php: 7.2
47+
install:
48+
- travis_retry composer update -d dev-tools $DEFAULT_COMPOSER_FLAGS
49+
- composer info -d dev-tools -D | sort
4750
script:
4851
- composer validate --strict || travis_terminate 1
49-
- composer normalize --dry-run || travis_terminate 1
50-
- vendor/bin/phpmd src,tests text phpmd.xml || travis_terminate 1
51-
- vendor/bin/php-cs-fixer fix --diff --dry-run -v || travis_terminate 1
52+
- composer normalize -d ./dev-tools ./../composer.json --dry-run || travis_terminate 1
53+
- dev-tools/vendor/bin/phpmd src,tests text phpmd.xml || travis_terminate 1
54+
- dev-tools/vendor/bin/php-cs-fixer fix --diff --dry-run -v || travis_terminate 1

composer.json

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,18 @@
1515
"require": {
1616
"php": "^5.5 || ^7.0",
1717
"phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0",
18-
"phpunitgoodpractices/polyfill": "^1.0",
19-
"phpunitgoodpractices/traits": "^1.3.2",
20-
"symfony/phpunit-bridge": "^3.2.2 || ^4.0"
18+
"phpunitgoodpractices/polyfill": "^1.0"
2119
},
2220
"conflict": {
2321
"hhvm": "*"
2422
},
2523
"require-dev": {
26-
"friendsofphp/php-cs-fixer": "^2.11",
2724
"johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0",
28-
"localheinz/composer-normalize": "^0.6.0",
29-
"maglnet/composer-require-checker": "^0.1.6",
30-
"mi-schi/phpmd-extension": "^4.2.1",
31-
"phpmd/phpmd": "^2.6.0"
25+
"phpunitgoodpractices/traits": "^1.3.2",
26+
"symfony/phpunit-bridge": "^3.2.2 || ^4.0"
3227
},
3328
"config": {
29+
"optimize-autoloader": true,
3430
"sort-packages": true
3531
},
3632
"autoload": {

dev-tools/composer.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"require": {
3+
"php": "^7.2"
4+
},
5+
"conflict": {
6+
"hhvm": "*"
7+
},
8+
"require-dev": {
9+
"friendsofphp/php-cs-fixer": "^2.11",
10+
"localheinz/composer-normalize": "^0.6.0",
11+
"maglnet/composer-require-checker": "^0.1.6",
12+
"mi-schi/phpmd-extension": "^4.2.1",
13+
"phpmd/phpmd": "^2.6.0"
14+
},
15+
"config": {
16+
"optimize-autoloader": true,
17+
"sort-packages": true
18+
}
19+
}

src/Constraint/XmlMatchesXsd.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of PHP CS Fixer.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
* Dariusz Rumiński <[email protected]>
8+
*
9+
* This source file is subject to the MIT license that is bundled
10+
* with this source code in the file LICENSE.
11+
*/
12+
13+
namespace PhpCsFixer\PhpunitConstraintXmlMatchesXsd\Constraint;
14+
15+
if (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0') < 0) {
16+
class_alias(XmlMatchesXsdForV5::class, XmlMatchesXsd::class);
17+
} else {
18+
class_alias(XmlMatchesXsdForV7::class, XmlMatchesXsd::class);
19+
}

src/Constraint/XmlMatchesXsdForV5.php

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

src/Constraint/XmlMatchesXsdForV7.php

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

0 commit comments

Comments
 (0)