Completed
Push — master ( 77e4a4...d10009 )
by Gilles
03:09
created

Dom::parseTag()   D

Complexity

Conditions 21
Paths 20

Size

Total Lines 147
Code Lines 96

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 86
CRAP Score 21.0006

Importance

Changes 0
Metric Value
cc 21
eloc 96
c 0
b 0
f 0
nc 20
nop 0
dl 0
loc 147
ccs 86
cts 87
cp 0.9885
crap 21.0006
rs 4.1666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
namespace PHPHtmlParser;
3
4
use PHPHtmlParser\Dom\AbstractNode;
5
use PHPHtmlParser\Dom\Collection;
6
use PHPHtmlParser\Dom\HtmlNode;
7
use PHPHtmlParser\Dom\TextNode;
8
use PHPHtmlParser\Exceptions\ChildNotFoundException;
9
use PHPHtmlParser\Exceptions\CircularException;
10
use PHPHtmlParser\Exceptions\CurlException;
11
use PHPHtmlParser\Exceptions\NotLoadedException;
12
use PHPHtmlParser\Exceptions\ParentNotFoundException;
13
use PHPHtmlParser\Exceptions\StrictException;
14
use PHPHtmlParser\Exceptions\UnknownChildTypeException;
15
use stringEncode\Encode;
16
17
/**
18
 * Class Dom
19
 *
20
 * @package PHPHtmlParser
21
 */
22
class Dom
23
{
24
25
    /**
26
     * The charset we would like the output to be in.
27
     *
28
     * @var string
29
     */
30
    protected $defaultCharset = 'UTF-8';
31
32
    /**
33
     * Contains the root node of this dom tree.
34
     *
35
     * @var HtmlNode
36
     */
37
    public $root;
38
39
    /**
40
     * The raw version of the document string.
41
     *
42
     * @var string
43
     */
44
    protected $raw;
45
46
    /**
47
     * The document string.
48
     *
49
     * @var Content
50
     */
51
    protected $content = null;
52
53
    /**
54
     * The original file size of the document.
55
     *
56
     * @var int
57
     */
58
    protected $rawSize;
59
60
    /**
61
     * The size of the document after it is cleaned.
62
     *
63
     * @var int
64
     */
65
    protected $size;
66
67
    /**
68
     * A global options array to be used by all load calls.
69
     *
70
     * @var array
71
     */
72
    protected $globalOptions = [];
73
74
    /**
75
     * A persistent option object to be used for all options in the
76
     * parsing of the file.
77
     *
78
     * @var Options
79
     */
80
    protected $options;
81
82
    /**
83
     * A list of tags which will always be self closing
84
     *
85
     * @var array
86
     */
87
    protected $selfClosing = [
88
        'area',
89
        'base',
90
        'basefont',
91
        'br',
92
        'col',
93
        'embed',
94
        'hr',
95
        'img',
96
        'input',
97
        'keygen',
98
        'link',
99
        'meta',
100
        'param',
101
        'source',
102
        'spacer',
103
        'track',
104
        'wbr'
105
    ];
106
107
    /**
108
     * A list of tags where there should be no /> at the end (html5 style)
109
     *
110
     * @var array
111
     */
112
    protected $noSlash = [];
113
114
    /**
115
     * Returns the inner html of the root node.
116
     *
117
     * @return string
118
     * @throws ChildNotFoundException
119
     * @throws UnknownChildTypeException
120
     */
121 24
    public function __toString(): string
122
    {
123 24
        return $this->root->innerHtml();
124
    }
125
126
    /**
127
     * A simple wrapper around the root node.
128
     *
129
     * @param string $name
130
     * @return mixed
131
     */
132 15
    public function __get($name)
133
    {
134 15
        return $this->root->$name;
135
    }
136
137
    /**
138
     * Attempts to load the dom from any resource, string, file, or URL.
139
     * @param string $str
140
     * @param array  $options
141
     * @return Dom
142
     * @throws ChildNotFoundException
143
     * @throws CircularException
144
     * @throws CurlException
145
     * @throws StrictException
146
     */
147 168
    public function load(string $str, array $options = []): Dom
148
    {
149 168
        AbstractNode::resetCount();
150
        // check if it's a file
151 168
        if (strpos($str, "\n") === false && is_file($str)) {
152 6
            return $this->loadFromFile($str, $options);
153
        }
154
        // check if it's a url
155 162
        if (preg_match("/^https?:\/\//i", $str)) {
156
            return $this->loadFromUrl($str, $options);
157
        }
158
159 162
        return $this->loadStr($str, $options);
160
    }
161
162
    /**
163
     * Loads the dom from a document file/url
164
     * @param string $file
165
     * @param array  $options
166
     * @return Dom
167
     * @throws ChildNotFoundException
168
     * @throws CircularException
169
     * @throws StrictException
170
     */
171 48
    public function loadFromFile(string $file, array $options = []): Dom
172
    {
173 48
        return $this->loadStr(file_get_contents($file), $options);
174
    }
175
176
    /**
177
     * Use a curl interface implementation to attempt to load
178
     * the content from a url.
179
     * @param string                            $url
180
     * @param array                             $options
181
     * @param CurlInterface|null $curl
182
     * @return Dom
183
     * @throws ChildNotFoundException
184
     * @throws CircularException
185
     * @throws CurlException
186
     * @throws StrictException
187
     */
188 6
    public function loadFromUrl(string $url, array $options = [], CurlInterface $curl = null): Dom
189
    {
190 6
        if (is_null($curl)) {
191
            // use the default curl interface
192
            $curl = new Curl;
193
        }
194 6
        $content = $curl->get($url);
195
196 6
        return $this->loadStr($content, $options);
197
    }
198
199
    /**
200
     * Parsers the html of the given string. Used for load(), loadFromFile(),
201
     * and loadFromUrl().
202
     * @param string $str
203
     * @param array  $option
204
     * @return Dom
205
     * @throws ChildNotFoundException
206
     * @throws CircularException
207
     * @throws StrictException
208
     */
209 228
    public function loadStr(string $str, array $option = []): Dom
210
    {
211 228
        $this->options = new Options;
212 228
        $this->options->setOptions($this->globalOptions)
213 228
                      ->setOptions($option);
214
215 228
        $this->rawSize = strlen($str);
216 228
        $this->raw     = $str;
217
218 228
        $html = $this->clean($str);
219
220 228
        $this->size    = strlen($str);
221 228
        $this->content = new Content($html);
222
223 228
        $this->parse();
224 222
        $this->detectCharset();
225
226 222
        return $this;
227
    }
228
229
    /**
230
     * Sets a global options array to be used by all load calls.
231
     *
232
     * @param array $options
233
     * @return Dom
234
     * @chainable
235
     */
236 48
    public function setOptions(array $options): Dom
237
    {
238 48
        $this->globalOptions = $options;
239
240 48
        return $this;
241
    }
242
243
    /**
244
     * Find elements by css selector on the root node.
245
     * @param string   $selector
246
     * @param int|null $nth
247
     * @return mixed|Collection|null
248
     * @throws ChildNotFoundException
249
     * @throws NotLoadedException
250
     */
251 168
    public function find(string $selector, int $nth = null)
252
    {
253 168
        $this->isLoaded();
254
255 165
        return $this->root->find($selector, $nth, $this->options->get('depthFirstSearch'));
0 ignored issues
show
Bug introduced by
It seems like $this->options->get('depthFirstSearch') can also be of type null; however, parameter $depthFirst of PHPHtmlParser\Dom\AbstractNode::find() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

255
        return $this->root->find($selector, $nth, /** @scrutinizer ignore-type */ $this->options->get('depthFirstSearch'));
Loading history...
256
    }
257
258
    /**
259
     * Find element by Id on the root node
260
     * @param int $id
261
     * @return bool|AbstractNode
262
     * @throws ChildNotFoundException
263
     * @throws NotLoadedException
264
     * @throws ParentNotFoundException
265
     */
266 9
    public function findById(int $id)
267
    {
268 9
        $this->isLoaded();
269
270 9
        return $this->root->findById($id);
271
    }
272
273
    /**
274
     * Adds the tag (or tags in an array) to the list of tags that will always
275
     * be self closing.
276
     *
277
     * @param string|array $tag
278
     * @return Dom
279
     * @chainable
280
     */
281 6
    public function addSelfClosingTag($tag): Dom
282
    {
283 6
        if ( ! is_array($tag)) {
284 3
            $tag = [$tag];
285
        }
286 6
        foreach ($tag as $value) {
287 6
            $this->selfClosing[] = $value;
288
        }
289
290 6
        return $this;
291
    }
292
293
    /**
294
     * Removes the tag (or tags in an array) from the list of tags that will
295
     * always be self closing.
296
     *
297
     * @param string|array $tag
298
     * @return Dom
299
     * @chainable
300
     */
301 3
    public function removeSelfClosingTag($tag): Dom
302
    {
303 3
        if ( ! is_array($tag)) {
304 3
            $tag = [$tag];
305
        }
306 3
        $this->selfClosing = array_diff($this->selfClosing, $tag);
307
308 3
        return $this;
309
    }
310
311
    /**
312
     * Sets the list of self closing tags to empty.
313
     *
314
     * @return Dom
315
     * @chainable
316
     */
317 3
    public function clearSelfClosingTags(): Dom
318
    {
319 3
        $this->selfClosing = [];
320
321 3
        return $this;
322
    }
323
324
325
    /**
326
     * Adds a tag to the list of self closing tags that should not have a trailing slash
327
     *
328
     * @param $tag
329
     * @return Dom
330
     * @chainable
331
     */
332 3
    public function addNoSlashTag($tag): Dom
333
    {
334 3
        if ( ! is_array($tag)) {
335 3
            $tag = [$tag];
336
        }
337 3
        foreach ($tag as $value) {
338 3
            $this->noSlash[] = $value;
339
        }
340
341 3
        return $this;
342
    }
343
344
    /**
345
     * Removes a tag from the list of no-slash tags.
346
     *
347
     * @param $tag
348
     * @return Dom
349
     * @chainable
350
     */
351
    public function removeNoSlashTag($tag): Dom
352
    {
353
        if ( ! is_array($tag)) {
354
            $tag = [$tag];
355
        }
356
        $this->noSlash = array_diff($this->noSlash, $tag);
357
358
        return $this;
359
    }
360
361
    /**
362
     * Empties the list of no-slash tags.
363
     *
364
     * @return Dom
365
     * @chainable
366
     */
367
    public function clearNoSlashTags(): Dom
368
    {
369
        $this->noSlash = [];
370
371
        return $this;
372
    }
373
374
    /**
375
     * Simple wrapper function that returns the first child.
376
     * @return AbstractNode
377
     * @throws ChildNotFoundException
378
     * @throws NotLoadedException
379
     */
380 3
    public function firstChild(): AbstractNode
381
    {
382 3
        $this->isLoaded();
383
384 3
        return $this->root->firstChild();
385
    }
386
387
    /**
388
     * Simple wrapper function that returns the last child.
389
     * @return AbstractNode
390
     * @throws ChildNotFoundException
391
     * @throws NotLoadedException
392
     */
393 3
    public function lastChild(): AbstractNode
394
    {
395 3
        $this->isLoaded();
396
397 3
        return $this->root->lastChild();
398
    }
399
400
    /**
401
     * Simple wrapper function that returns count of child elements
402
     *
403
     * @return int
404
     * @throws NotLoadedException
405
     */
406 3
    public function countChildren(): int
407
    {
408 3
        $this->isLoaded();
409
410 3
        return $this->root->countChildren();
411
    }
412
413
    /**
414
     * Get array of children
415
     *
416
     * @return array
417
     * @throws NotLoadedException
418
     */
419 3
    public function getChildren(): array
420
    {
421 3
        $this->isLoaded();
422
423 3
        return $this->root->getChildren();
424
    }
425
426
    /**
427
     * Check if node have children nodes
428
     *
429
     * @return bool
430
     * @throws NotLoadedException
431
     */
432 3
    public function hasChildren(): bool
433
    {
434 3
        $this->isLoaded();
435
436 3
        return $this->root->hasChildren();
437
    }
438
439
    /**
440
     * Simple wrapper function that returns an element by the
441
     * id.
442
     * @param $id
443
     * @return mixed|Collection|null
444
     * @throws ChildNotFoundException
445
     * @throws NotLoadedException
446
     */
447 12
    public function getElementById($id)
448
    {
449 12
        $this->isLoaded();
450
451 12
        return $this->find('#'.$id, 0);
452
    }
453
454
    /**
455
     * Simple wrapper function that returns all elements by
456
     * tag name.
457
     * @param string $name
458
     * @return mixed|Collection|null
459
     * @throws ChildNotFoundException
460
     * @throws NotLoadedException
461
     */
462 15
    public function getElementsByTag(string $name)
463
    {
464 15
        $this->isLoaded();
465
466 15
        return $this->find($name);
467
    }
468
469
    /**
470
     * Simple wrapper function that returns all elements by
471
     * class name.
472
     * @param string $class
473
     * @return mixed|Collection|null
474
     * @throws ChildNotFoundException
475
     * @throws NotLoadedException
476
     */
477 3
    public function getElementsByClass(string $class)
478
    {
479 3
        $this->isLoaded();
480
481 3
        return $this->find('.'.$class);
482
    }
483
484
    /**
485
     * Checks if the load methods have been called.
486
     *
487
     * @throws NotLoadedException
488
     */
489 192
    protected function isLoaded(): void
490
    {
491 192
        if (is_null($this->content)) {
492 3
            throw new NotLoadedException('Content is not loaded!');
493
        }
494 189
    }
495
496
    /**
497
     * Cleans the html of any none-html information.
498
     *
499
     * @param string $str
500
     * @return string
501
     */
502 228
    protected function clean(string $str): string
503
    {
504 228
        if ($this->options->get('cleanupInput') != true) {
505
            // skip entire cleanup step
506 6
            return $str;
507
        }
508
509
        // remove white space before closing tags
510 222
        $str = mb_eregi_replace("'\s+>", "'>", $str);
511 222
        $str = mb_eregi_replace('"\s+>', '">', $str);
512
513
        // clean out the \n\r
514 222
        $replace = ' ';
515 222
        if ($this->options->get('preserveLineBreaks')) {
516 3
            $replace = '&#10;';
517
        }
518 222
        $str = str_replace(["\r\n", "\r", "\n"], $replace, $str);
519
520
        // strip the doctype
521 222
        $str = mb_eregi_replace("<!doctype(.*?)>", '', $str);
522
523
        // strip out comments
524 222
        $str = mb_eregi_replace("<!--(.*?)-->", '', $str);
525
526
        // strip out cdata
527 222
        $str = mb_eregi_replace("<!\[CDATA\[(.*?)\]\]>", '', $str);
528
529
        // strip out <script> tags
530 222
        if ($this->options->get('removeScripts')) {
531 219
            $str = mb_eregi_replace("<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>", '', $str);
532 219
            $str = mb_eregi_replace("<\s*script\s*>(.*?)<\s*/\s*script\s*>", '', $str);
533
        }
534
535
        // strip out <style> tags
536 222
        if ($this->options->get('removeStyles')) {
537 219
            $str = mb_eregi_replace("<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>", '', $str);
538 219
            $str = mb_eregi_replace("<\s*style\s*>(.*?)<\s*/\s*style\s*>", '', $str);
539
        }
540
541
        // strip out server side scripts
542 222
        if ($this->options->get('serverSideScripts')) {
543
            $str = mb_eregi_replace("(<\?)(.*?)(\?>)", '', $str);
544
        }
545
546
        // strip smarty scripts
547 222
        if ($this->options->get('removeSmartyScripts')) {
548 219
            $str = mb_eregi_replace("(\{\w)(.*?)(\})", '', $str);
549
        }
550
551 222
        return $str;
552
    }
553
554
    /**
555
     * Attempts to parse the html in content.
556
     *
557
     * @return void
558
     * @throws ChildNotFoundException
559
     * @throws CircularException
560
     * @throws StrictException
561
     */
562 228
    protected function parse(): void
563
    {
564
        // add the root node
565 228
        $this->root = new HtmlNode('root');
566 228
        $this->root->setHtmlSpecialCharsDecode($this->options->htmlSpecialCharsDecode);
567 228
        $activeNode = $this->root;
568 228
        while ( ! is_null($activeNode)) {
569 228
            $str = $this->content->copyUntil('<');
570 228
            if ($str == '') {
571 228
                $info = $this->parseTag();
572 228
                if ( ! $info['status']) {
573
                    // we are done here
574 222
                    $activeNode = null;
575 222
                    continue;
576
                }
577
578
                // check if it was a closing tag
579 222
                if ($info['closing']) {
580 219
                    $foundOpeningTag  = true;
581 219
                    $originalNode     = $activeNode;
582 219
                    while ($activeNode->getTag()->name() != $info['tag']) {
583 78
                        $activeNode = $activeNode->getParent();
584 78
                        if (is_null($activeNode)) {
585
                            // we could not find opening tag
586 36
                            $activeNode = $originalNode;
587 36
                            $foundOpeningTag = false;
588 36
                            break;
589
                        }
590
                    }
591 219
                    if ($foundOpeningTag) {
592 219
                        $activeNode = $activeNode->getParent();
593
                    }
594 219
                    continue;
595
                }
596
597 222
                if ( ! isset($info['node'])) {
598 12
                    continue;
599
                }
600
601
                /** @var AbstractNode $node */
602 222
                $node = $info['node'];
603 222
                $activeNode->addChild($node);
604
605
                // check if node is self closing
606 222
                if ( ! $node->getTag()->isSelfClosing()) {
607 222
                    $activeNode = $node;
608
                }
609 216
            } else if ($this->options->whitespaceTextNode ||
610 216
                trim($str) != ''
611
            ) {
612
                // we found text we care about
613 216
                $textNode = new TextNode($str, $this->options->removeDoubleSpace);
614 216
                $textNode->setHtmlSpecialCharsDecode($this->options->htmlSpecialCharsDecode);
615 216
                $activeNode->addChild($textNode);
616
            }
617
        }
618 222
    }
619
620
    /**
621
     * Attempt to parse a tag out of the content.
622
     *
623
     * @return array
624
     * @throws StrictException
625
     */
626 228
    protected function parseTag(): array
627
    {
628
        $return = [
629 228
            'status'  => false,
630
            'closing' => false,
631
            'node'    => null,
632
        ];
633 228
        if ($this->content->char() != '<') {
634
            // we are not at the beginning of a tag
635 219
            return $return;
636
        }
637
638
        // check if this is a closing tag
639 222
        if ($this->content->fastForward(1)->char() == '/') {
640
            // end tag
641 219
            $tag = $this->content->fastForward(1)
642 219
                                 ->copyByToken('slash', true);
643
            // move to end of tag
644 219
            $this->content->copyUntil('>');
645 219
            $this->content->fastForward(1);
646
647
            // check if this closing tag counts
648 219
            $tag = strtolower($tag);
649 219
            if (in_array($tag, $this->selfClosing)) {
650 12
                $return['status'] = true;
651
652 12
                return $return;
653
            } else {
654 219
                $return['status']  = true;
655 219
                $return['closing'] = true;
656 219
                $return['tag']     = strtolower($tag);
657
            }
658
659 219
            return $return;
660
        }
661
662 222
        $tag  = strtolower($this->content->copyByToken('slash', true));
663 222
        if (trim($tag) == '')
664
        {
665
            // no tag found, invalid < found
666 3
            return $return;
667
        }
668 222
        $node = new HtmlNode($tag);
669 222
        $node->setHtmlSpecialCharsDecode($this->options->htmlSpecialCharsDecode);
670
671
        // attributes
672 222
        while ($this->content->char() != '>' &&
673 222
            $this->content->char() != '/') {
674 213
            $space = $this->content->skipByToken('blank', true);
675 213
            if (empty($space)) {
676 6
                $this->content->fastForward(1);
677 6
                continue;
678
            }
679
680 213
            $name = $this->content->copyByToken('equal', true);
681 213
            if ($name == '/') {
682
                break;
683
            }
684
685 213
            if (empty($name)) {
686 117
				$this->content->skipByToken('blank');
687 117
				continue;
688
            }
689
690 213
            $this->content->skipByToken('blank');
691 213
            if ($this->content->char() == '=') {
692 213
                $attr = [];
693 213
                $this->content->fastForward(1)
694 213
                              ->skipByToken('blank');
695 213
                switch ($this->content->char()) {
696 213
                    case '"':
697 198
                        $attr['doubleQuote'] = true;
698 198
                        $this->content->fastForward(1);
699 198
                        $string = $this->content->copyUntil('"', true, true);
700
                        do {
701 198
                            $moreString = $this->content->copyUntilUnless('"', '=>');
702 198
                            $string .= $moreString;
703 198
                        } while ( ! empty($moreString));
704 198
                        $attr['value'] = $string;
705 198
                        $this->content->fastForward(1);
706 198
                        $node->getTag()->$name = $attr;
707 198
                        break;
708 21
                    case "'":
709 18
                        $attr['doubleQuote'] = false;
710 18
                        $this->content->fastForward(1);
711 18
                        $string = $this->content->copyUntil("'", true, true);
712
                        do {
713 18
                            $moreString = $this->content->copyUntilUnless("'", '=>');
714 18
                            $string .= $moreString;
715 18
                        } while ( ! empty($moreString));
716 18
                        $attr['value'] = $string;
717 18
                        $this->content->fastForward(1);
718 18
                        $node->getTag()->$name = $attr;
719 18
                        break;
720
                    default:
721 3
                        $attr['doubleQuote']   = true;
722 3
                        $attr['value']         = $this->content->copyByToken('attr', true);
723 3
                        $node->getTag()->$name = $attr;
724 213
                        break;
725
                }
726
            } else {
727
                // no value attribute
728 66
                if ($this->options->strict) {
729
                    // can't have this in strict html
730 3
                    $character = $this->content->getPosition();
731 3
                    throw new StrictException("Tag '$tag' has an attribute '$name' with out a value! (character #$character)");
732
                }
733 63
                $node->getTag()->$name = [
734
                    'value'       => null,
735
                    'doubleQuote' => true,
736
                ];
737 63
                if ($this->content->char() != '>') {
738 12
                    $this->content->rewind(1);
739
                }
740
            }
741
        }
742
743 222
        $this->content->skipByToken('blank');
744 222
        if ($this->content->char() == '/') {
745
            // self closing tag
746 114
            $node->getTag()->selfClosing();
747 114
            $this->content->fastForward(1);
748 222
        } elseif (in_array($tag, $this->selfClosing)) {
749
750
            // Should be a self closing tag, check if we are strict
751 81
            if ($this->options->strict) {
752 3
                $character = $this->content->getPosition();
753 3
                throw new StrictException("Tag '$tag' is not self closing! (character #$character)");
754
            }
755
756
            // We force self closing on this tag.
757 78
            $node->getTag()->selfClosing();
758
759
            // Should this tag use a trailing slash?
760 78
            if(in_array($tag, $this->noSlash))
761
            {
762 3
                $node->getTag()->noTrailingSlash();
763
            }
764
765
        }
766
767 222
        $this->content->fastForward(1);
768
769 222
        $return['status'] = true;
770 222
        $return['node']   = $node;
771
772 222
        return $return;
773
    }
774
775
    /**
776
     * Attempts to detect the charset that the html was sent in.
777
     *
778
     * @return bool
779
     * @throws ChildNotFoundException
780
     */
781 222
    protected function detectCharset(): bool
782
    {
783
        // set the default
784 222
        $encode = new Encode;
785 222
        $encode->from($this->defaultCharset);
786 222
        $encode->to($this->defaultCharset);
787
788 222
        if ( ! is_null($this->options->enforceEncoding)) {
789
            //  they want to enforce the given encoding
790
            $encode->from($this->options->enforceEncoding);
791
            $encode->to($this->options->enforceEncoding);
792
793
            return false;
794
        }
795
796 222
        $meta = $this->root->find('meta[http-equiv=Content-Type]', 0);
797 222
        if (is_null($meta)) {
798
            // could not find meta tag
799 192
            $this->root->propagateEncoding($encode);
800
801 192
            return false;
802
        }
803 30
        $content = $meta->content;
0 ignored issues
show
Bug Best Practice introduced by
The property content does not exist on PHPHtmlParser\Dom\Collection. Since you implemented __get, consider adding a @property annotation.
Loading history...
804 30
        if (empty($content)) {
805
            // could not find content
806
            $this->root->propagateEncoding($encode);
807
808
            return false;
809
        }
810 30
        $matches = [];
811 30
        if (preg_match('/charset=(.+)/', $content, $matches)) {
812 30
            $encode->from(trim($matches[1]));
813 30
            $this->root->propagateEncoding($encode);
814
815 30
            return true;
816
        }
817
818
        // no charset found
819
        $this->root->propagateEncoding($encode);
820
821
        return false;
822
    }
823
}
824