Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
92.59% |
25 / 27 |
|
60.00% |
3 / 5 |
CRAP | |
0.00% |
0 / 1 |
Element | |
92.59% |
25 / 27 |
|
60.00% |
3 / 5 |
14.08 | |
0.00% |
0 / 1 |
__construct | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
4.01 | |||
isMathmlTextIntegration | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
isHtmlIntegration | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
5.05 | |||
getNoahKey | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
getDebugTag | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Wikimedia\RemexHtml\TreeBuilder; |
4 | |
5 | use Wikimedia\RemexHtml\HTMLData; |
6 | use Wikimedia\RemexHtml\PropGuard; |
7 | use Wikimedia\RemexHtml\Tokenizer\Attributes; |
8 | |
9 | /** |
10 | * Storage for all the state that TreeBuilder needs to associate with each |
11 | * element. These objects should be freed once they fall out of TreeBuilder's |
12 | * data structures (the stack etc.). |
13 | * |
14 | * These objects are also used to communicate information about elements with |
15 | * downstream clients. |
16 | */ |
17 | class Element implements FormattingElement { |
18 | use PropGuard; |
19 | |
20 | /** |
21 | * The namespace. This will be the HTML namespace for elements that are not |
22 | * in foreign content, even if there is a prefix. |
23 | * @var string |
24 | */ |
25 | public $namespace; |
26 | |
27 | /** |
28 | * The tag name, usually exactly as it appeared in the source document. |
29 | * This is not strictly a local name, since it still contains a colon for |
30 | * prefixed elements. In foreign content, it is effectively a local name. |
31 | * It is suitable for use as a serialized tag name. |
32 | * @var string |
33 | */ |
34 | public $name; |
35 | |
36 | /** |
37 | * This is an internal designation of the type of the element, which is |
38 | * equal to the tag name when the element is in the HTML namespace, and is |
39 | * some other string when the element is not in the HTML namespace. |
40 | * @var string |
41 | */ |
42 | public $htmlName; |
43 | |
44 | /** |
45 | * @var Attributes |
46 | */ |
47 | public $attrs; |
48 | |
49 | /** |
50 | * This is true if the element was created by the TreeBuilder either as a |
51 | * fragment context node, or as a synthetic <html> element to be used as |
52 | * the top-level element in fragment parsing. |
53 | * @var bool |
54 | */ |
55 | public $isVirtual; |
56 | |
57 | /** |
58 | * Internal to CachingStack. A link in the scope list. |
59 | */ |
60 | public $nextEltInScope; |
61 | |
62 | /** |
63 | * Internal to CachingStack and SimpleStack. The current stack index, or |
64 | * null if the element is not in the stack. |
65 | */ |
66 | public $stackIndex; |
67 | |
68 | /** |
69 | * Internal to ActiveFormattingElements. |
70 | */ |
71 | public $prevAFE; |
72 | |
73 | /** |
74 | * Internal to ActiveFormattingElements. |
75 | */ |
76 | public $nextAFE; |
77 | |
78 | /** |
79 | * Internal to ActiveFormattingElements. |
80 | */ |
81 | public $nextNoah; |
82 | |
83 | /** |
84 | * The cache for getNoahKey() |
85 | */ |
86 | private $noahKey; |
87 | |
88 | /** |
89 | * This member variable can be written to by the TreeHandler, to store any |
90 | * state associated with the element (such as a DOM node). It is not used |
91 | * by TreeBuilder. |
92 | */ |
93 | public $userData; |
94 | |
95 | /** |
96 | * A unique ID which identifies the element |
97 | * @var int |
98 | */ |
99 | public $uid; |
100 | |
101 | /** |
102 | * The next unique ID to be used |
103 | * |
104 | * @var int |
105 | */ |
106 | private static $nextUid = 1; |
107 | |
108 | /** |
109 | * The element types in the MathML namespace which are MathML text |
110 | * integration points. |
111 | * @var array<string,bool> |
112 | */ |
113 | private static $mathmlIntegration = [ |
114 | 'mi' => true, |
115 | 'mo' => true, |
116 | 'mn' => true, |
117 | 'ms' => true, |
118 | 'mtext' => true |
119 | ]; |
120 | |
121 | /** |
122 | * The element types in the SVG namespace which are SVG text integration |
123 | * points. |
124 | * @var array<string,bool> |
125 | */ |
126 | private static $svgHtmlIntegration = [ |
127 | 'foreignObject' => true, |
128 | 'desc' => true, |
129 | 'title' => true |
130 | ]; |
131 | |
132 | /** |
133 | * Constructor. |
134 | * |
135 | * @param string $namespace |
136 | * @param string $name |
137 | * @param Attributes $attrs |
138 | */ |
139 | public function __construct( $namespace, $name, Attributes $attrs ) { |
140 | $this->namespace = $namespace; |
141 | $this->name = $name; |
142 | if ( $namespace === HTMLData::NS_HTML ) { |
143 | $this->htmlName = $name; |
144 | } elseif ( $namespace === HTMLData::NS_MATHML ) { |
145 | $this->htmlName = "mathml $name"; |
146 | } elseif ( $namespace === HTMLData::NS_SVG ) { |
147 | $this->htmlName = "svg $name"; |
148 | } else { |
149 | $this->htmlName = "$namespace $name"; |
150 | } |
151 | $this->attrs = $attrs; |
152 | $this->uid = self::$nextUid++; |
153 | } |
154 | |
155 | /** |
156 | * Is the element a MathML text integration point? |
157 | * |
158 | * @return bool |
159 | */ |
160 | public function isMathmlTextIntegration() { |
161 | return $this->namespace === HTMLData::NS_MATHML |
162 | && isset( self::$mathmlIntegration[$this->name] ); |
163 | } |
164 | |
165 | /** |
166 | * Is the element an HTML integration point? |
167 | * @return bool |
168 | */ |
169 | public function isHtmlIntegration() { |
170 | if ( $this->namespace === HTMLData::NS_MATHML ) { |
171 | if ( isset( $this->attrs['encoding'] ) ) { |
172 | $encoding = strtolower( $this->attrs['encoding'] ); |
173 | return $encoding === 'text/html' || $encoding === 'application/xhtml+xml'; |
174 | } else { |
175 | return false; |
176 | } |
177 | } elseif ( $this->namespace === HTMLData::NS_SVG ) { |
178 | return isset( self::$svgHtmlIntegration[$this->name] ); |
179 | } else { |
180 | return false; |
181 | } |
182 | } |
183 | |
184 | /** |
185 | * Get a string key for the Noah's Ark algorithm |
186 | * |
187 | * @return string |
188 | */ |
189 | public function getNoahKey() { |
190 | if ( $this->noahKey === null ) { |
191 | $attrs = $this->attrs->getValues(); |
192 | ksort( $attrs ); |
193 | $this->noahKey = serialize( [ $this->htmlName, $attrs ] ); |
194 | } |
195 | return $this->noahKey; |
196 | } |
197 | |
198 | /** |
199 | * Get a string identifying the element, for use in debugging. |
200 | * @return string |
201 | */ |
202 | public function getDebugTag() { |
203 | return $this->htmlName . '#' . $this->uid; |
204 | } |
205 | } |