Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
BeforeHead
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
4 / 4
8
100.00% covered (success)
100.00%
1 / 1
 characters
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 startTag
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 endTag
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 endDocument
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Wikimedia\RemexHtml\TreeBuilder;
4
5use Wikimedia\RemexHtml\Tokenizer\Attributes;
6use Wikimedia\RemexHtml\Tokenizer\PlainAttributes;
7
8/**
9 * The "before head" insertion mode
10 */
11class BeforeHead extends InsertionMode {
12    public function characters( $text, $start, $length, $sourceStart, $sourceLength ) {
13        // Ignore whitespace
14        [ $part1, $part2 ] = $this->splitInitialMatch(
15            true, "\t\n\f\r ", $text, $start, $length, $sourceStart, $sourceLength );
16        [ $start, $length, $sourceStart, $sourceLength ] = $part2;
17        if ( !$length ) {
18            return;
19        }
20        // Handle non-whitespace
21        $this->builder->headElement = $this->builder->insertElement(
22            'head', new PlainAttributes, false, $sourceStart, 0 );
23        $this->dispatcher->switchMode( Dispatcher::IN_HEAD )
24            ->characters( $text, $start, $length, $sourceStart, $sourceLength );
25    }
26
27    public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) {
28        if ( $name === 'html' ) {
29            $this->dispatcher->inBody->startTag( $name, $attrs, $selfClose,
30                $sourceStart, $sourceLength );
31        } elseif ( $name === 'head' ) {
32            $this->builder->headElement = $this->builder->insertElement(
33                $name, $attrs, false, $sourceStart, $sourceLength );
34            $this->dispatcher->switchMode( Dispatcher::IN_HEAD );
35        } else {
36            $this->builder->headElement = $this->builder->insertElement(
37                'head', new PlainAttributes, false, $sourceStart, 0 );
38            $this->dispatcher->switchMode( Dispatcher::IN_HEAD )
39                ->startTag( $name, $attrs, $selfClose, $sourceStart, $sourceLength );
40        }
41    }
42
43    public function endTag( $name, $sourceStart, $sourceLength ) {
44        $allowed = [ "head" => true, "body" => true, "html" => true, "br" => true ];
45        if ( !isset( $allowed[$name] ) ) {
46            $this->builder->error( 'end tag not allowed before head', $sourceStart );
47            return;
48        }
49        $this->builder->headElement = $this->builder->insertElement(
50            'head', new PlainAttributes, false, $sourceStart, 0 );
51        $this->dispatcher->switchMode( Dispatcher::IN_HEAD )
52            ->endTag( $name, $sourceStart, $sourceLength );
53    }
54
55    public function endDocument( $pos ) {
56        $this->builder->headElement = $this->builder->insertElement(
57            'head', new PlainAttributes, false, $pos, 0 );
58        $this->dispatcher->switchMode( Dispatcher::IN_HEAD )
59            ->endDocument( $pos );
60    }
61}