Skip to content

Commit 479a577

Browse files
authored
Merge pull request tgalopin#12 from tgalopin/type-safety
Introduce Psalm, fix type issues and improve Travis config
2 parents 5a14699 + fba1ee8 commit 479a577

28 files changed

+69
-61
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
vendor
22
composer.lock
3+
.php_cs.cache

.php_cs.dist

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
$finder = PhpCsFixer\Finder::create()
4+
->in(__DIR__)
5+
;
6+
7+
return PhpCsFixer\Config::create()
8+
->setRules(array(
9+
'@Symfony' => true,
10+
'phpdoc_annotation_without_dot' => false,
11+
))
12+
->setFinder($finder)
13+
;

.travis.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ language: php
22
dist: trusty
33
sudo: false
44

5-
php:
6-
- 7.1
7-
- 7.2
8-
95
matrix:
6+
include:
7+
- php: 7.1
8+
env: COMPOSER_FLAGS="--prefer-lowest"
9+
- php: 7.2
10+
env: CS_FIXER=1
11+
- php: 7.3
1012
fast_finish: true
1113

1214
cache:
@@ -18,7 +20,9 @@ before_install:
1820

1921
before_script:
2022
- composer self-update
21-
- composer install
23+
- composer update $COMPOSER_FLAGS --prefer-dist
2224

2325
script:
26+
- stty cols 120
27+
- if [ "$CS_FIXER" == 1 ]; then wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v2.13.1/php-cs-fixer.phar && php php-cs-fixer.phar fix --dry-run --diff; fi
2428
- php vendor/bin/phpunit

benchmark/run.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
echo "Running...\n";
1212

13-
for ($i = 0; $i < $times; $i++) {
13+
for ($i = 0; $i < $times; ++$i) {
1414
$output = $sanitizer->sanitize($input);
1515
}
1616

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"ext-dom": "*",
2525
"masterminds/html5": "^2.4",
2626
"psr/log": "^1.0",
27-
"league/uri-parser": "^1.4"
27+
"league/uri-parser": "^1.4.1"
2828
},
2929
"require-dev": {
3030
"phpunit/phpunit": "^7.4",

src/DomVisitor.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class DomVisitor implements DomVisitorInterface
3333
*/
3434
private $reversedVisitors;
3535

36+
/**
37+
* @param NodeVisitorInterface[] $visitors
38+
*/
3639
public function __construct(array $visitors = [])
3740
{
3841
$this->visitors = $visitors;
@@ -60,6 +63,7 @@ private function visitNode(\DOMNode $node, Cursor $cursor)
6063
}
6164
}
6265

66+
/** @var \DOMNode $child */
6367
foreach ($node->childNodes ?? [] as $k => $child) {
6468
if ('#text' === $child->nodeName) {
6569
// Add text in the safe tree without a visitor for performance

src/Extension/Basic/NodeVisitor/ANodeVisitor.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ class ANodeVisitor extends AbstractNodeVisitor
2727
{
2828
use HasChildrenNodeVisitorTrait;
2929

30+
/**
31+
* @var AHrefSanitizer
32+
*/
3033
private $sanitizer;
3134

3235
public function __construct(array $config = [])

src/Extension/Basic/Sanitizer/AHrefSanitizer.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ public function sanitize(?string $input): ?string
4444
}
4545
}
4646

47-
$sanitized = $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps);
47+
if (!$sanitized = $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps)) {
48+
return null;
49+
}
4850

4951
// Basic validation that it's an e-mail
50-
if (strpos($sanitized, 'mailto:') === 0 && (strpos($sanitized, '@') === false || strpos($sanitized, '.') === false)) {
52+
if (0 === strpos($sanitized, 'mailto:') && (false === strpos($sanitized, '@') || false === strpos($sanitized, '.'))) {
5153
return null;
5254
}
5355

src/Extension/ExtensionInterface.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ public function getName(): string;
2727

2828
/**
2929
* Return a list of node visitors to register in the sanitizer following the format tagName => visitor.
30-
* For instance:
31-
*
32-
* 'strong' => new StrongVisitor($config,
30+
* For instance: 'strong' => new StrongVisitor($config).
3331
*
3432
* @param array $config The configuration given by the user of the library.
3533
*

src/Extension/Image/Sanitizer/ImgSrcSanitizer.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ public function sanitize(?string $input): ?string
4141
$allowedHosts[] = null;
4242
}
4343

44-
$sanitized = $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps);
44+
if (!$sanitized = $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps)) {
45+
return null;
46+
}
4547

4648
// Allow only images in data URIs
47-
if (strpos($sanitized, 'data:') === 0 && strpos($sanitized, 'data:image/') !== 0) {
49+
if (0 === strpos($sanitized, 'data:') && 0 !== strpos($sanitized, 'data:image/')) {
4850
return null;
4951
}
5052

src/Node/AbstractNode.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
*/
1717
abstract class AbstractNode implements NodeInterface
1818
{
19+
/**
20+
* @var NodeInterface
21+
*/
1922
private $parent;
2023

2124
public function __construct(NodeInterface $parent)

src/Node/AbstractTagNode.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ protected function renderAttributes(): string
5959
{
6060
$rendered = [];
6161
foreach ($this->attributes as $name => $value) {
62-
if ($value === null) {
62+
if (null === $value) {
6363
// Tag should be removed as a sanitizer found suspect data inside
6464
continue;
6565
}
6666

6767
$attr = $this->encodeHtmlEntities($name);
68-
if ($value !== '') {
68+
if ('' !== $value) {
6969
// In quirks mode, IE8 does a poor job producing innerHTML values.
7070
// If JavaScript does:
7171
// nodeA.innerHTML = nodeB.innerHTML;

src/Node/TagNodeInterface.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ public function getAttribute(string $name): ?string;
3333
*
3434
* @param string $name
3535
* @param string $value
36-
*
37-
* @return void
3836
*/
3937
public function setAttribute(string $name, string $value);
4038
}

src/Node/TextNode.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class TextNode extends AbstractNode
2323
use IsChildlessTrait;
2424
use StringSanitizerTrait;
2525

26-
private $text = '';
26+
private $text;
2727

2828
public function __construct(NodeInterface $parent, string $text)
2929
{

src/Sanitizer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,6 @@ public function sanitize(string $html): string
106106
private function isValidUtf8(string $html): bool
107107
{
108108
// preg_match() fails silently on strings containing invalid UTF-8.
109-
return $html === '' || preg_match('/^./us', $html) === 1;
109+
return '' === $html || 1 === preg_match('/^./us', $html);
110110
}
111111
}

src/Sanitizer/UrlSanitizerTrait.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ private function sanitizeUrl(?string $input, array $allowedSchemes, ?array $allo
4747
}
4848

4949
// Invalid host
50-
if ($allowedHosts !== null && !$this->isAllowedHost($url['host'], $allowedHosts)) {
50+
if (null !== $allowedHosts && !$this->isAllowedHost($url['host'], $allowedHosts)) {
5151
return null;
5252
}
5353

5454
// Force HTTPS
55-
if ($forceHttps && $url['scheme'] === 'http') {
55+
if ($forceHttps && 'http' === $url['scheme']) {
5656
$url['scheme'] = 'https';
5757
}
5858

@@ -61,8 +61,8 @@ private function sanitizeUrl(?string $input, array $allowedSchemes, ?array $allo
6161

6262
private function isAllowedHost(?string $host, array $allowedHosts): bool
6363
{
64-
if ($host === null && \in_array(null, $allowedHosts, true)) {
65-
return true;
64+
if (null === $host) {
65+
return \in_array(null, $allowedHosts, true);
6666
}
6767

6868
$parts = array_reverse(explode('.', $host));

src/SanitizerBuilderInterface.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ interface SanitizerBuilderInterface
2424
* Register an extension to use in the sanitizer being built.
2525
*
2626
* @param ExtensionInterface $extension
27-
*
28-
* @return void
2927
*/
3028
public function registerExtension(ExtensionInterface $extension);
3129

src/Util/Dumper.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,14 @@ public static function dumpDomTree(\DOMNode $tree)
3030
echo "}\n";
3131
}
3232

33-
private static function dumpDomNode(\DOMNode $node)
33+
private static function dumpDomNode(\DOMNode $node): string
3434
{
35-
self::$id++;
35+
++self::$id;
3636

3737
$name = self::$id.'-'.$node->nodeName;
3838
echo ' "'.$name."\";\n";
3939

40+
/** @var \DOMNode $child */
4041
foreach ($node->childNodes ?: [] as $child) {
4142
$childName = self::dumpDomNode($child);
4243
echo ' "'.$name.'" -> "'.$childName."\";\n";

src/Visitor/ScriptNodeVisitor.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ public function supports(\DOMNode $domNode, Cursor $cursor): bool
2626
return 'script' === $domNode->nodeName || 'noscript' === $domNode->nodeName;
2727
}
2828

29-
public function getDefaultAllowedAttributes(): array
30-
{
31-
return [];
32-
}
33-
3429
public function enterNode(\DOMNode $domNode, Cursor $cursor)
3530
{
3631
$node = new ScriptNode($cursor->node);

src/Visitor/StyleNodeVisitor.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ public function supports(\DOMNode $domNode, Cursor $cursor): bool
2626
return 'style' === $domNode->nodeName;
2727
}
2828

29-
public function getDefaultAllowedAttributes(): array
30-
{
31-
return [];
32-
}
33-
3429
public function enterNode(\DOMNode $domNode, Cursor $cursor)
3530
{
3631
$node = new StyleNode($cursor->node);

src/Visitor/TagVisitorTrait.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,21 @@ public function supports(\DOMNode $domNode, Cursor $cursor): bool
3131
/**
3232
* Set attributes from a DOM node to a sanitized node.
3333
*
34-
* @param \DOMNode $domNode
34+
* @param \DOMNode $domNode
3535
* @param TagNodeInterface $node
36-
* @param array $allowedAttributes
36+
* @param array $allowedAttributes
3737
*/
3838
private function setAttributes(\DOMNode $domNode, TagNodeInterface $node, array $allowedAttributes = [])
3939
{
40-
if (!count($domNode->attributes)) {
40+
if (!\count($domNode->attributes)) {
4141
return;
4242
}
4343

4444
/** @var \DOMAttr $attribute */
4545
foreach ($domNode->attributes as $attribute) {
4646
$name = strtolower($attribute->name);
4747

48-
if (in_array($name, $allowedAttributes)) {
48+
if (\in_array($name, $allowedAttributes, true)) {
4949
$node->setAttribute($name, $attribute->value);
5050
}
5151
}
@@ -55,13 +55,13 @@ private function setAttributes(\DOMNode $domNode, TagNodeInterface $node, array
5555
* Read the value of a DOMNode attribute.
5656
*
5757
* @param \DOMNode $domNode
58-
* @param string $name
58+
* @param string $name
5959
*
6060
* @return null|string
6161
*/
6262
private function getAttribute(\DOMNode $domNode, string $name): ?string
6363
{
64-
if (!count($domNode->attributes)) {
64+
if (!\count($domNode->attributes)) {
6565
return null;
6666
}
6767

tests/AbstractSanitizerTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public function provideFixtures(): array
2323
{
2424
// Fixtures shared by all sanitizers
2525
return [
26-
2726
[
2827
'hello world',
2928
'hello world',
@@ -72,7 +71,6 @@ public function provideFixtures(): array
7271
'Lorem ipsum<![CDATA[ <!-- ]]> <script>alert(1337)</script> <!-- -->',
7372
'Lorem ipsum ',
7473
],
75-
7674
];
7775
}
7876

@@ -94,7 +92,7 @@ public function testSanitize($input, $expectedOutput)
9492
public function testRemoveNullByte()
9593
{
9694
$this->assertSame('Null byte', $this->createSanitizer()->sanitize("Null byte\0"));
97-
$this->assertSame('Null byte', $this->createSanitizer()->sanitize("Null byte&#0;"));
95+
$this->assertSame('Null byte', $this->createSanitizer()->sanitize('Null byte&#0;'));
9896
}
9997

10098
public function testDeeplyNestedTagDos()

tests/EmptySanitizerTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ public function createSanitizer(): SanitizerInterface
2424
public function provideFixtures(): array
2525
{
2626
return array_merge(parent::provideFixtures(), [
27-
2827
/*
2928
* Normal tags
3029
*/
@@ -243,7 +242,6 @@ public function provideFixtures(): array
243242
'<a style="font-size: 40px; color: red;">Lorem ipsum dolor sit amet, consectetur.</a>',
244243
'Lorem ipsum dolor sit amet, consectetur.',
245244
],
246-
247245
]);
248246
}
249247
}

tests/Extension/NodeVisitor/CustomNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ protected function getDomNodeName(): string
3232
public function getDefaultAllowedAttributes(): array
3333
{
3434
return [
35-
'class', 'width', 'height'
35+
'class', 'width', 'height',
3636
];
3737
}
3838

tests/FullSanitizerTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public function createSanitizer(): SanitizerInterface
3939
public function provideFixtures(): array
4040
{
4141
return array_merge(parent::provideFixtures(), [
42-
4342
/*
4443
* Normal tags
4544
*/
@@ -383,7 +382,6 @@ public function provideFixtures(): array
383382
'<a style="font-size: 40px; color: red;">Lorem ipsum dolor sit amet, consectetur.</a>',
384383
'<a>Lorem ipsum dolor sit amet, consectetur.</a>',
385384
],
386-
387385
]);
388386
}
389387
}

tests/Sanitizer/StringSanitizerTraitTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ public function provideEncodeHtmlEntites()
2525
'"' => '&#34;',
2626
'\'' => '&#039;',
2727
'&' => '&amp;',
28-
"<" => "&lt;",
29-
">" => "&gt;",
30-
"&lt;" => "&amp;lt;",
31-
"&gt;" => "&amp;gt;",
28+
'<' => '&lt;',
29+
'>' => '&gt;',
30+
'&lt;' => '&amp;lt;',
31+
'&gt;' => '&amp;gt;',
3232
'+' => '&#43;',
3333
'=' => '&#61;',
3434
'@' => '&#64;',

0 commit comments

Comments
 (0)