Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
65 / 65
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
InCaption
100.00% covered (success)
100.00%
65 / 65
100.00% covered (success)
100.00%
4 / 4
32
100.00% covered (success)
100.00%
1 / 1
 characters
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 startTag
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
12
 endTag
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
1 / 1
18
 endDocument
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Wikimedia\RemexHtml\TreeBuilder;
4
5use Wikimedia\RemexHtml\Tokenizer\Attributes;
6
7/**
8 * The "in caption" insertion mode
9 */
10class InCaption extends InsertionMode {
11    public function characters( $text, $start, $length, $sourceStart, $sourceLength ) {
12        $this->dispatcher->inBody->characters( $text, $start, $length,
13            $sourceStart, $sourceLength );
14    }
15
16    public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) {
17        $builder = $this->builder;
18        $stack = $builder->stack;
19        switch ( $name ) {
20            case 'caption':
21            case 'col':
22            case 'colgroup':
23            case 'tbody':
24            case 'td':
25            case 'tfoot':
26            case 'th':
27            case 'thead':
28            case 'tr':
29                $builder->error( "start tag <$name> not allowed in caption", $sourceStart );
30                if ( !$stack->isInTableScope( 'caption' ) ) {
31                    // Ignore
32                    return;
33                }
34                $builder->popAllUpToName( 'caption', $sourceStart, 0 );
35                $builder->afe->clearToMarker();
36                $this->dispatcher->switchMode( Dispatcher::IN_TABLE )
37                    ->startTag( $name, $attrs, $selfClose, $sourceStart, $sourceLength );
38                break;
39
40            default:
41                $this->dispatcher->inBody->startTag( $name, $attrs, $selfClose,
42                    $sourceStart, $sourceLength );
43        }
44    }
45
46    public function endTag( $name, $sourceStart, $sourceLength ) {
47        $dispatcher = $this->dispatcher;
48        $builder = $this->builder;
49        $stack = $builder->stack;
50
51        switch ( $name ) {
52            case 'caption':
53                if ( !$stack->isInTableScope( 'caption' ) ) {
54                    $builder->error( "</caption> matches a start tag which is not in scope, ignoring",
55                        $sourceStart );
56                    return;
57                }
58
59                $builder->generateImpliedEndTags( false, $sourceStart );
60                if ( $stack->current->htmlName !== 'caption' ) {
61                    $builder->error( "</caption> found but another element is open", $sourceStart );
62                }
63                $builder->popAllUpToName( 'caption', $sourceStart, $sourceLength );
64                $builder->afe->clearToMarker();
65                $dispatcher->switchMode( Dispatcher::IN_TABLE );
66                break;
67
68            case 'table':
69                if ( !$stack->isInTableScope( 'caption' ) ) {
70                    $builder->error( '</table> found in caption, but there is no ' .
71                        'caption in scope, ignoring', $sourceStart );
72                    return;
73                }
74                $builder->generateImpliedEndTags( false, $sourceStart );
75                if ( $stack->current->htmlName !== 'caption' ) {
76                    $builder->error( '</table> found in caption, closing caption', $sourceStart );
77                }
78                $builder->popAllUpToName( 'caption', $sourceStart, 0 );
79                $builder->afe->clearToMarker();
80                $dispatcher->switchMode( Dispatcher::IN_TABLE )
81                    ->endTag( $name, $sourceStart, $sourceLength );
82                break;
83
84            case 'body':
85            case 'col':
86            case 'colgroup':
87            case 'html':
88            case 'tbody':
89            case 'td':
90            case 'tfoot':
91            case 'th':
92            case 'thead':
93            case 'tr':
94                $this->builder->error( "end tag </$name> ignored in caption mode", $sourceStart );
95                break;
96
97            default:
98                $this->dispatcher->inBody->endTag( $name, $sourceStart, $sourceLength );
99        }
100    }
101
102    public function endDocument( $pos ) {
103        $this->dispatcher->inBody->endDocument( $pos );
104    }
105}