Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.59% |
65 / 68 |
|
80.00% |
4 / 5 |
CRAP | |
0.00% |
0 / 1 |
InCell | |
95.59% |
65 / 68 |
|
80.00% |
4 / 5 |
34 | |
0.00% |
0 / 1 |
characters | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
startTag | |
84.21% |
16 / 19 |
|
0.00% |
0 / 1 |
13.67 | |||
endTag | |
100.00% |
37 / 37 |
|
100.00% |
1 / 1 |
17 | |||
endDocument | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
closeTheCell | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Wikimedia\RemexHtml\TreeBuilder; |
4 | |
5 | use Wikimedia\RemexHtml\Tokenizer\Attributes; |
6 | |
7 | /** |
8 | * The "in cell" insertion mode |
9 | */ |
10 | class InCell 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 | switch ( $name ) { |
18 | case 'caption': |
19 | case 'col': |
20 | case 'colgroup': |
21 | case 'tbody': |
22 | case 'td': |
23 | case 'tfoot': |
24 | case 'th': |
25 | case 'thead': |
26 | case 'tr': |
27 | if ( !$this->builder->stack->isInTableScope( 'td' ) |
28 | && !$this->builder->stack->isInTableScope( 'th' ) |
29 | ) { |
30 | $this->builder->error( "<$name> tag should close the cell but none is in scope", |
31 | $sourceStart ); |
32 | return; |
33 | } |
34 | $this->closeTheCell( $sourceStart ) |
35 | ->startTag( $name, $attrs, $selfClose, $sourceStart, $sourceLength ); |
36 | break; |
37 | |
38 | default: |
39 | $this->dispatcher->inBody->startTag( |
40 | $name, $attrs, $selfClose, $sourceStart, $sourceLength ); |
41 | } |
42 | } |
43 | |
44 | public function endTag( $name, $sourceStart, $sourceLength ) { |
45 | $builder = $this->builder; |
46 | $stack = $builder->stack; |
47 | $dispatcher = $this->dispatcher; |
48 | |
49 | switch ( $name ) { |
50 | case 'td': |
51 | case 'th': |
52 | if ( !$stack->isInTableScope( $name ) ) { |
53 | $builder->error( "</$name> encountered but there is no $name in scope, ignoring", |
54 | $sourceStart ); |
55 | return; |
56 | } |
57 | $builder->generateImpliedEndTags( false, $sourceStart ); |
58 | if ( $stack->current->htmlName !== $name ) { |
59 | $builder->error( "</$name> encountered when there are tags open " . |
60 | "which can't be closed automatically", $sourceStart ); |
61 | } |
62 | $builder->popAllUpToName( $name, $sourceStart, $sourceLength ); |
63 | $builder->afe->clearToMarker(); |
64 | $dispatcher->switchMode( Dispatcher::IN_ROW ); |
65 | break; |
66 | |
67 | case 'body': |
68 | case 'caption': |
69 | case 'col': |
70 | case 'colgroup': |
71 | case 'html': |
72 | $builder->error( "unexpected </$name> in cell, ignoring", $sourceStart ); |
73 | return; |
74 | |
75 | case 'table': |
76 | case 'tbody': |
77 | case 'tfoot': |
78 | case 'thead': |
79 | case 'tr': |
80 | if ( !$stack->isInTableScope( $name ) ) { |
81 | $builder->error( "</$name> encountered but there is no $name in scope, ignoring", |
82 | $sourceStart ); |
83 | return; |
84 | } |
85 | $this->closeTheCell( $sourceStart ) |
86 | ->endTag( $name, $sourceStart, $sourceLength ); |
87 | break; |
88 | |
89 | default: |
90 | $dispatcher->inBody->endTag( $name, $sourceStart, $sourceLength ); |
91 | } |
92 | } |
93 | |
94 | public function endDocument( $pos ) { |
95 | $this->dispatcher->inBody->endDocument( $pos ); |
96 | } |
97 | |
98 | private function closeTheCell( $sourceStart ) { |
99 | $tdth = [ 'td' => true, 'th' => true ]; |
100 | $builder = $this->builder; |
101 | $stack = $builder->stack; |
102 | $builder->generateImpliedEndTags( false, $sourceStart ); |
103 | if ( !isset( $tdth[$stack->current->htmlName] ) ) { |
104 | $builder->error( "closing the cell but there are tags open " . |
105 | "which can't be closed automatically", $sourceStart ); |
106 | } |
107 | $builder->afe->clearToMarker(); |
108 | return $this->dispatcher->switchMode( Dispatcher::IN_ROW ); |
109 | } |
110 | } |