Skip to content

Commit c8e2b6d

Browse files
committed
Added phan level 1 and updated docs according to recommendation
1 parent 8e57359 commit c8e2b6d

17 files changed

+588
-83
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
/phpunit.php export-ignore
1010
/phpunit.xml export-ignore
1111
/infection.json.dist export-ignore
12+
/.phan export-ignore

.phan/config.php

Lines changed: 382 additions & 0 deletions
Large diffs are not rendered by default.

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"phpunit/phpunit": "^7.5.1",
2424
"mockery/mockery": "^1.2",
2525
"php-coveralls/php-coveralls": "^2.1",
26-
"infection/infection": "^0.13.4"
26+
"infection/infection": "^0.13.4",
27+
"phan/phan": "^2.4"
2728
},
2829
"autoload": {
2930
"psr-4": {

src/PHPHtmlParser/Content.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
<?php declare(strict_types=1);
1+
<?php
2+
3+
declare(strict_types=1);
4+
25
namespace PHPHtmlParser;
36

7+
8+
use PHPHtmlParser\Exceptions\LogicalException;
9+
410
/**
511
* Class Content
612
*
@@ -65,10 +71,10 @@ public function getPosition(): int
6571
/**
6672
* Gets the current character we are at.
6773
*
68-
* @param int $char
74+
* @param ?int $char
6975
* @return string
7076
*/
71-
public function char(int $char = null): string
77+
public function char(?int $char = null): string
7278
{
7379
$pos = $this->pos;
7480
if ( ! is_null($char)) {
@@ -135,8 +141,7 @@ public function copyUntil(string $string, bool $char = false, bool $escape = fal
135141
$position = strpos($this->content, $string, $position);
136142
if ($position === false) {
137143
// reached the end
138-
$found = true;
139-
continue;
144+
break;
140145
}
141146

142147
if ($this->char($position - 1) == '\\') {
@@ -157,6 +162,9 @@ public function copyUntil(string $string, bool $char = false, bool $escape = fal
157162
if ($position === false) {
158163
// could not find character, just return the remaining of the content
159164
$return = substr($this->content, $this->pos, $this->size - $this->pos);
165+
if ($return === false) {
166+
throw new LogicalException('Substr returned false with position '.$this->pos.'.');
167+
}
160168
$this->pos = $this->size;
161169

162170
return $return;
@@ -168,6 +176,9 @@ public function copyUntil(string $string, bool $char = false, bool $escape = fal
168176
}
169177

170178
$return = substr($this->content, $this->pos, $position - $this->pos);
179+
if ($return === false) {
180+
throw new LogicalException('Substr returned false with position '.$this->pos.'.');
181+
}
171182
// set the new position
172183
$this->pos = $position;
173184

@@ -229,6 +240,9 @@ public function skip(string $string, bool $copy = false)
229240
$return = $this;
230241
if ($copy) {
231242
$return = substr($this->content, $this->pos, $len);
243+
if ($return === false) {
244+
throw new LogicalException('Substr returned false with position '.$this->pos.'.');
245+
}
232246
}
233247

234248
// update the position

src/PHPHtmlParser/Dom.php

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPHtmlParser\Exceptions\ParentNotFoundException;
1313
use PHPHtmlParser\Exceptions\StrictException;
1414
use PHPHtmlParser\Exceptions\UnknownChildTypeException;
15+
use PHPHtmlParser\Exceptions\LogicalException;
1516
use stringEncode\Encode;
1617

1718
/**
@@ -167,10 +168,15 @@ public function load(string $str, array $options = []): Dom
167168
* @throws ChildNotFoundException
168169
* @throws CircularException
169170
* @throws StrictException
171+
* @throws LogicalException
170172
*/
171173
public function loadFromFile(string $file, array $options = []): Dom
172174
{
173-
return $this->loadStr(file_get_contents($file), $options);
175+
$content = file_get_contents($file);
176+
if ($content === false) {
177+
throw new LogicalException('file_get_contents failed and returned false when trying to read "'.$file.'".');
178+
}
179+
return $this->loadStr($content, $options);
174180
}
175181

176182
/**
@@ -516,48 +522,87 @@ protected function clean(string $str): string
516522
$is_gzip = 0 === mb_strpos($str, "\x1f" . "\x8b" . "\x08", 0, "US-ASCII");
517523
if ($is_gzip) {
518524
$str = gzdecode($str);
525+
if ($str === false) {
526+
throw new LogicalException('gzdecode returned false. Error when trying to decode the string.');
527+
}
519528
}
520529

521530
// remove white space before closing tags
522531
$str = mb_eregi_replace("'\s+>", "'>", $str);
532+
if ($str === false) {
533+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to clean single quotes.');
534+
}
523535
$str = mb_eregi_replace('"\s+>', '">', $str);
536+
if ($str === false) {
537+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to clean double quotes.');
538+
}
524539

525540
// clean out the \n\r
526541
$replace = ' ';
527542
if ($this->options->get('preserveLineBreaks')) {
528543
$replace = '&#10;';
529544
}
530545
$str = str_replace(["\r\n", "\r", "\n"], $replace, $str);
546+
if ($str === false) {
547+
throw new LogicalException('str_replace returned false instead of a string. Error when attempting to clean input string.');
548+
}
531549

532550
// strip the doctype
533551
$str = mb_eregi_replace("<!doctype(.*?)>", '', $str);
552+
if ($str === false) {
553+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to strip the doctype.');
554+
}
534555

535556
// strip out comments
536557
$str = mb_eregi_replace("<!--(.*?)-->", '', $str);
558+
if ($str === false) {
559+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to strip comments.');
560+
}
537561

538562
// strip out cdata
539563
$str = mb_eregi_replace("<!\[CDATA\[(.*?)\]\]>", '', $str);
564+
if ($str === false) {
565+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to strip out cdata.');
566+
}
540567

541568
// strip out <script> tags
542569
if ($this->options->get('removeScripts')) {
543570
$str = mb_eregi_replace("<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>", '', $str);
571+
if ($str === false) {
572+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to remove scripts 1.');
573+
}
544574
$str = mb_eregi_replace("<\s*script\s*>(.*?)<\s*/\s*script\s*>", '', $str);
575+
if ($str === false) {
576+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to remove scripts 2.');
577+
}
545578
}
546579

547580
// strip out <style> tags
548581
if ($this->options->get('removeStyles')) {
549582
$str = mb_eregi_replace("<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>", '', $str);
583+
if ($str === false) {
584+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to strip out style tags 1.');
585+
}
550586
$str = mb_eregi_replace("<\s*style\s*>(.*?)<\s*/\s*style\s*>", '', $str);
587+
if ($str === false) {
588+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to strip out style tags 2.');
589+
}
551590
}
552591

553592
// strip out server side scripts
554593
if ($this->options->get('serverSideScripts')) {
555594
$str = mb_eregi_replace("(<\?)(.*?)(\?>)", '', $str);
595+
if ($str === false) {
596+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to strip out service side scripts.');
597+
}
556598
}
557599

558600
// strip smarty scripts
559601
if ($this->options->get('removeSmartyScripts')) {
560602
$str = mb_eregi_replace("(\{\w)(.*?)(\})", '', $str);
603+
if ($str === false) {
604+
throw new LogicalException('mb_eregi_replace returned false instead of a string. Error when attempting to remove smarty scripts.');
605+
}
561606
}
562607

563608
return $str;
@@ -658,7 +703,7 @@ protected function parseTag(): array
658703

659704
// check if this closing tag counts
660705
$tag = strtolower($tag);
661-
if (in_array($tag, $this->selfClosing)) {
706+
if (in_array($tag, $this->selfClosing, true)) {
662707
$return['status'] = true;
663708

664709
return $return;
@@ -758,7 +803,7 @@ protected function parseTag(): array
758803
// self closing tag
759804
$node->getTag()->selfClosing();
760805
$this->content->fastForward(1);
761-
} elseif (in_array($tag, $this->selfClosing)) {
806+
} elseif (in_array($tag, $this->selfClosing, true)) {
762807

763808
// Should be a self closing tag, check if we are strict
764809
if ($this->options->strict) {
@@ -770,7 +815,7 @@ protected function parseTag(): array
770815
$node->getTag()->selfClosing();
771816

772817
// Should this tag use a trailing slash?
773-
if(in_array($tag, $this->noSlash))
818+
if(in_array($tag, $this->noSlash, true))
774819
{
775820
$node->getTag()->noTrailingSlash();
776821
}
@@ -798,10 +843,11 @@ protected function detectCharset(): bool
798843
$encode->from($this->defaultCharset);
799844
$encode->to($this->defaultCharset);
800845

801-
if ( ! is_null($this->options->enforceEncoding)) {
846+
$enforceEncoding = $this->options->enforceEncoding;
847+
if ( ! is_null($enforceEncoding)) {
802848
// they want to enforce the given encoding
803-
$encode->from($this->options->enforceEncoding);
804-
$encode->to($this->options->enforceEncoding);
849+
$encode->from($enforceEncoding);
850+
$encode->to($enforceEncoding);
805851

806852
return false;
807853
}

src/PHPHtmlParser/Dom/AbstractNode.php

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,27 @@
1111

1212
/**
1313
* Dom node object.
14-
* @property string outerhtml
15-
* @property string innerhtml
16-
* @property string text
17-
* @property int prev
18-
* @property int next
19-
* @property Tag tag
20-
* @property InnerNode parent
14+
* @property string $outerhtml
15+
* @property string $innerhtml
16+
* @property string $text
17+
* @property int $prev
18+
* @property int $next
19+
* @property Tag $tag
20+
* @property InnerNode $parent
2121
*/
2222
abstract class AbstractNode
2323
{
24+
/**
25+
* @var int
26+
*/
2427
private static $count = 0;
28+
2529
/**
2630
* Contains the tag name/type
27-
* @var Tag
31+
*
32+
* @var ?Tag
2833
*/
29-
protected $tag;
34+
protected $tag = null;
3035

3136
/**
3237
* Contains a list of attributes on this tag.
@@ -38,7 +43,7 @@ abstract class AbstractNode
3843
/**
3944
* Contains the parent Node.
4045
*
41-
* @var InnerNode
46+
* @var ?InnerNode
4247
*/
4348
protected $parent = null;
4449

@@ -111,8 +116,8 @@ public function __get(string $key)
111116
public function __destruct()
112117
{
113118
$this->tag = null;
114-
$this->attr = [];
115119
$this->parent = null;
120+
$this->attr = [];
116121
$this->children = [];
117122
}
118123

@@ -272,11 +277,13 @@ public function hasNextSibling(): bool
272277
catch (ParentNotFoundException $e)
273278
{
274279
// no parent, no next sibling
280+
unset($e);
275281
return false;
276282
}
277283
catch (ChildNotFoundException $e)
278284
{
279285
// no sibling found
286+
unset($e);
280287
return false;
281288
}
282289
}
@@ -347,11 +354,9 @@ public function getAttributes(): array
347354
public function getAttribute(string $key): ?string
348355
{
349356
$attribute = $this->tag->getAttribute($key);
350-
if ( ! is_null($attribute)) {
351-
$attribute = $attribute['value'];
352-
}
357+
$attributeValue = $attribute['value'];
353358

354-
return $attribute;
359+
return $attributeValue;
355360
}
356361

357362
/**
@@ -371,7 +376,7 @@ public function hasAttribute(string $key): bool
371376
* on the tag of this node.
372377
*
373378
* @param string $key
374-
* @param string|null $value
379+
* @param string|array $value
375380
* @return AbstractNode
376381
* @chainable
377382
*/

src/PHPHtmlParser/Dom/Collection.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Collection implements IteratorAggregate, ArrayAccess, Countable
1818
/**
1919
* The collection of Nodes.
2020
*
21-
* @param array
21+
* @var array
2222
*/
2323
protected $collection = [];
2424

@@ -139,7 +139,7 @@ public function offsetUnset($offset): void
139139
*/
140140
public function offsetGet($offset)
141141
{
142-
return isset($this->collection[$offset]) ? $this->collection[$offset] : null;
142+
return $this->collection[$offset] ?? null;
143143
}
144144

145145
/**

src/PHPHtmlParser/Dom/HtmlNode.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,29 @@ class HtmlNode extends InnerNode
1515
/**
1616
* Remembers what the innerHtml was if it was scanned previously.
1717
*
18-
* @var string
18+
* @var ?string
1919
*/
2020
protected $innerHtml = null;
2121

2222
/**
2323
* Remembers what the outerHtml was if it was scanned previously.
2424
*
25-
* @var string
25+
* @var ?string
2626
*/
2727
protected $outerHtml = null;
2828

2929
/**
3030
* Remembers what the text was if it was scanned previously.
3131
*
32-
* @var string
32+
* @var ?string
3333
*/
3434
protected $text = null;
3535

3636
/**
3737
* Remembers what the text was when we looked into all our
3838
* children nodes.
3939
*
40-
* @var string
40+
* @var ?string
4141
*/
4242
protected $textWithChildren = null;
4343

@@ -100,6 +100,7 @@ public function innerHtml(): string
100100
$child = $this->nextChild($child->id());
101101
} catch (ChildNotFoundException $e) {
102102
// no more children
103+
unset($e);
103104
$child = null;
104105
}
105106
}

0 commit comments

Comments
 (0)