Skip to content

Commit 8f43f08

Browse files
committed
Fixed #215 - Added support for <? tags
1 parent 7bba8ad commit 8f43f08

File tree

9 files changed

+116
-68
lines changed

9 files changed

+116
-68
lines changed

src/PHPHtmlParser/Content.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public function char(?int $char = null): string
7575
/**
7676
* Moves the current position forward.
7777
*
78-
* @chainable
78+
*
7979
*
8080
* @throws ContentLengthException
8181
*/
@@ -101,7 +101,7 @@ public function canFastForward(int $count): bool
101101
/**
102102
* Moves the current position backward.
103103
*
104-
* @chainable
104+
*
105105
*/
106106
public function rewind(int $count): Content
107107
{

src/PHPHtmlParser/Dom.php

+22-18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPHtmlParser\Dom\AbstractNode;
1010
use PHPHtmlParser\Dom\Collection;
1111
use PHPHtmlParser\Dom\HtmlNode;
12+
use PHPHtmlParser\Dom\Tag;
1213
use PHPHtmlParser\Dom\TextNode;
1314
use PHPHtmlParser\DTO\TagDTO;
1415
use PHPHtmlParser\Enum\StringToken;
@@ -171,10 +172,10 @@ public function loadStr(string $str, ?Options $options = null): Dom
171172
{
172173
$this->options = new Options();
173174
if ($this->globalOptions !== null) {
174-
$this->options->setFromOptions($this->globalOptions);
175+
$this->options = $this->options->setFromOptions($this->globalOptions);
175176
}
176177
if ($options !== null) {
177-
$this->options->setFromOptions($options);
178+
$this->options = $this->options->setFromOptions($options);
178179
}
179180

180181
$this->rawSize = \strlen($str);
@@ -194,7 +195,7 @@ public function loadStr(string $str, ?Options $options = null): Dom
194195
/**
195196
* Sets a global options array to be used by all load calls.
196197
*
197-
* @chainable
198+
*
198199
*/
199200
public function setOptions(Options $options): Dom
200201
{
@@ -512,11 +513,7 @@ private function parse(): void
512513
*/
513514
private function parseTag(): TagDTO
514515
{
515-
$return = [
516-
'status' => false,
517-
'closing' => false,
518-
'node' => null,
519-
];
516+
$return = [];
520517
if ($this->content->char() != '<') {
521518
// we are not at the beginning of a tag
522519
return new TagDTO();
@@ -549,12 +546,20 @@ private function parseTag(): TagDTO
549546
$return['tag'] = \strtolower($tag);
550547

551548
return new TagDTO($return);
552-
}
553-
554-
$tag = \strtolower($this->content->copyByToken(StringToken::SLASH(), true));
555-
if (\trim($tag) == '') {
556-
// no tag found, invalid < found
557-
return new TagDTO();
549+
} elseif ($this->content->char() == '?') {
550+
// special setting tag
551+
$tag = $this->content->fastForward(1)
552+
->copyByToken(StringToken::SLASH(), true);
553+
$tag = (new Tag($tag))
554+
->setOpening('<?')
555+
->setClosing(' ?>')
556+
->selfClosing();
557+
} else {
558+
$tag = \strtolower($this->content->copyByToken(StringToken::SLASH(), true));
559+
if (\trim($tag) == '') {
560+
// no tag found, invalid < found
561+
return new TagDTO();
562+
}
558563
}
559564
$node = new HtmlNode($tag);
560565
$node->setHtmlSpecialCharsDecode($this->options->isHtmlSpecialCharsDecode());
@@ -631,23 +636,22 @@ private function parseTag(): TagDTO
631636
}
632637

633638
$this->content->skipByToken(StringToken::BLANK());
634-
$tag = \strtolower($tag);
635639
if ($this->content->char() == '/') {
636640
// self closing tag
637641
$node->getTag()->selfClosing();
638642
$this->content->fastForward(1);
639-
} elseif (\in_array($tag, $this->options->getSelfClosing(), true)) {
643+
} elseif (\in_array($node->getTag()->name(), $this->options->getSelfClosing(), true)) {
640644
// Should be a self closing tag, check if we are strict
641645
if ($this->options->isStrict()) {
642646
$character = $this->content->getPosition();
643-
throw new StrictException("Tag '$tag' is not self closing! (character #$character)");
647+
throw new StrictException("Tag '".$node->getTag()->name()."' is not self closing! (character #$character)");
644648
}
645649

646650
// We force self closing on this tag.
647651
$node->getTag()->selfClosing();
648652

649653
// Should this tag use a trailing slash?
650-
if (\in_array($tag, $this->options->getNoSlash(), true)) {
654+
if (\in_array($node->getTag()->name(), $this->options->getNoSlash(), true)) {
651655
$node->getTag()->noTrailingSlash();
652656
}
653657
}

src/PHPHtmlParser/Dom/AbstractNode.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ public function getTag(): Tag
304304
* Replaces the tag for this node.
305305
*
306306
* @param string|Tag $tag
307-
* @chainable
307+
*
308308
*/
309309
public function setTag($tag): AbstractNode
310310
{
@@ -365,7 +365,7 @@ public function hasAttribute(string $key): bool
365365
* A wrapper method that simply calls the setAttribute method
366366
* on the tag of this node.
367367
*
368-
* @chainable
368+
*
369369
*/
370370
public function setAttribute(string $key, ?string $value, bool $doubleQuote = true): AbstractNode
371371
{

src/PHPHtmlParser/Dom/InnerNode.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public function insertAfter(AbstractNode $child, int $id): bool
205205
/**
206206
* Removes the child by id.
207207
*
208-
* @chainable
208+
*
209209
*/
210210
public function removeChild(int $id): InnerNode
211211
{

src/PHPHtmlParser/Dom/Tag.php

+33-8
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ class Tag
5858
*/
5959
private $HtmlSpecialCharsDecode = false;
6060

61+
/**
62+
* What the opening of this tag will be.
63+
*
64+
* @var string
65+
*/
66+
private $opening = '<';
67+
68+
/**
69+
* What the closing tag for self-closing elements should be.
70+
* @var string
71+
*/
72+
private $closing = ' />';
73+
6174
/**
6275
* Sets up the tag with a name.
6376
*
@@ -79,25 +92,37 @@ public function name(): string
7992
/**
8093
* Sets the tag to be self closing.
8194
*
82-
* @chainable
95+
*
8396
*/
8497
public function selfClosing(): Tag
8598
{
8699
$this->selfClosing = true;
87100

88-
return $this;
101+
return clone $this;
102+
}
103+
104+
public function setOpening(string $opening): Tag
105+
{
106+
$this->opening = $opening;
107+
return clone $this;
108+
}
109+
110+
public function setClosing(string $closing): Tag
111+
{
112+
$this->closing = $closing;
113+
return clone $this;
89114
}
90115

91116
/**
92117
* Sets the tag to not use a trailing slash.
93118
*
94-
* @chainable
119+
*
95120
*/
96121
public function noTrailingSlash(): Tag
97122
{
98123
$this->trailingSlash = false;
99124

100-
return $this;
125+
return clone $this;
101126
}
102127

103128
/**
@@ -131,7 +156,7 @@ public function noise(string $noise): Tag
131156
{
132157
$this->noise = $noise;
133158

134-
return $this;
159+
return clone $this;
135160
}
136161

137162
/**
@@ -148,7 +173,7 @@ public function setAttribute(string $key, ?string $attributeValue, bool $doubleQ
148173
}
149174
$this->attr[\strtolower($key)] = $attributeDTO;
150175

151-
return $this;
176+
return clone $this;
152177
}
153178

154179
/**
@@ -296,7 +321,7 @@ public function hasAttribute(string $key)
296321
*/
297322
public function makeOpeningTag()
298323
{
299-
$return = '<' . $this->name;
324+
$return = $this->opening . $this->name;
300325

301326
// add the attributes
302327
foreach (\array_keys($this->attr) as $key) {
@@ -317,7 +342,7 @@ public function makeOpeningTag()
317342
}
318343

319344
if ($this->selfClosing && $this->trailingSlash) {
320-
return $return . ' />';
345+
return $return . $this->closing;
321346
}
322347

323348
return $return . '>';

0 commit comments

Comments
 (0)