Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 96
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
DOMHandlerFactory
0.00% covered (danger)
0.00%
0 / 96
0.00% covered (danger)
0.00%
0 / 2
3080
0.00% covered (danger)
0.00%
0 / 1
 newFromTagHandler
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 1
1640
 getDOMHandler
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
240
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Html2Wt\DOMHandlers;
5
6use Wikimedia\Parsoid\DOM\DocumentFragment;
7use Wikimedia\Parsoid\DOM\Element;
8use Wikimedia\Parsoid\DOM\Node;
9use Wikimedia\Parsoid\Utils\DOMCompat;
10use Wikimedia\Parsoid\Utils\DOMDataUtils;
11use Wikimedia\Parsoid\Utils\DOMUtils;
12use Wikimedia\Parsoid\Utils\WTUtils;
13use Wikimedia\Parsoid\Wikitext\Consts;
14
15/**
16 * Factory for picking the right DOMHandler for a DOM element.
17 * FIXME: memoize handlers, maybe?
18 */
19class DOMHandlerFactory {
20
21    /**
22     * Get the DOMHandler that's appropriate for serializing a HTML tag.
23     *
24     * Porting note: this is the equivalent of DOMHandlers.tagHandlers[tag].
25     * @param string $tag
26     * @return DOMHandler|null
27     */
28    public function newFromTagHandler( string $tag ): ?DOMHandler {
29        switch ( $tag ) {
30            case 'a':
31                return new AHandler();
32            case 'audio':
33                return new MediaHandler();
34            case 'b':
35                return new QuoteHandler( "'''" );
36            case 'body':
37                return new BodyHandler();
38            case 'br':
39                return new BRHandler();
40            case 'caption':
41                return new CaptionHandler();
42            case 'dd':
43                return new DDHandler(); // multi-line dt/dd
44            case 'dd_row':
45                return new DDHandler( 'row' ); // single-line dt/dd
46            case 'dl':
47                return new ListHandler( [ 'dt', 'dd' ] );
48            case 'dt':
49                return new DTHandler();
50            case 'figure':
51                return new FigureHandler();
52            // TODO: Remove when 2.1.x content is deprecated, since we no
53            // longer emit inline media in figure-inline.  See the test,
54            // "Serialize simple image with figure-inline wrapper"
55            case 'figure-inline':
56                return new MediaHandler();
57            case 'hr':
58                return new HRHandler();
59            case 'h1':
60                return new HeadingHandler( '=' );
61            case 'h2':
62                return new HeadingHandler( '==' );
63            case 'h3':
64                return new HeadingHandler( '===' );
65            case 'h4':
66                return new HeadingHandler( '====' );
67            case 'h5':
68                return new HeadingHandler( '=====' );
69            case 'h6':
70                return new HeadingHandler( '======' );
71            case 'i':
72                return new QuoteHandler( "''" );
73            case 'img':
74                return new ImgHandler();
75            case 'li':
76                return new LIHandler();
77            case 'link':
78                return new LinkHandler();
79            case 'meta':
80                return new MetaHandler();
81            case 'ol':
82                return new ListHandler( [ 'li' ] );
83            case 'p':
84                return new PHandler();
85            case 'pre':
86                return new PreHandler(); // Wikitext indent pre generated with leading space
87            case 'pre_html':
88                return new HTMLPreHandler(); // HTML pre
89            case 'span':
90                return new SpanHandler();
91            case 'table':
92                return new TableHandler();
93            case 'tbody':
94                return new JustChildrenHandler();
95            case 'td':
96                return new TDHandler();
97            case 'tfoot':
98                return new JustChildrenHandler();
99            case 'th':
100                return new THHandler();
101            case 'thead':
102                return new JustChildrenHandler();
103            case 'tr':
104                return new TRHandler();
105            case 'ul':
106                return new ListHandler( [ 'li' ] );
107            case 'video':
108                return new MediaHandler();
109            default:
110                return null;
111        }
112    }
113
114    /**
115     * Get a DOMHandler for an element node.
116     * @param ?Node $node
117     * @return DOMHandler
118     */
119    public function getDOMHandler( ?Node $node ): DOMHandler {
120        if ( $node instanceof DocumentFragment ) {
121            return new BodyHandler();
122        }
123
124        if ( !( $node instanceof Element ) ) {
125            return new DOMHandler();
126        }
127        '@phan-var Element $node';/** @var Element $node */
128
129        if ( WTUtils::isFirstEncapsulationWrapperNode( $node ) ) {
130            return new EncapsulatedContentHandler();
131        }
132
133        $dp = DOMDataUtils::getDataParsoid( $node );
134
135        // If available, use a specialized handler for serializing
136        // to the specialized syntactic form of the tag.
137        $handler = $this->newFromTagHandler( DOMCompat::nodeName( $node ) . '_' . ( $dp->stx ?? null ) );
138
139        // Unless a specialized handler is available, use the HTML handler
140        // for html-stx tags. But, <a> tags should never serialize as HTML.
141        if ( !$handler && ( $dp->stx ?? null ) === 'html' && DOMCompat::nodeName( $node ) !== 'a' ) {
142            return new FallbackHTMLHandler();
143        }
144
145        // If in a HTML table tag, serialize table tags in the table
146        // using HTML tags, instead of native wikitext tags.
147        if ( isset( Consts::$HTML['ChildTableTags'][DOMCompat::nodeName( $node )] )
148             && !isset( Consts::$ZeroWidthWikitextTags[DOMCompat::nodeName( $node )] )
149             && WTUtils::inHTMLTableTag( $node )
150        ) {
151            return new FallbackHTMLHandler();
152        }
153
154        // If parent node is a list in html-syntax, then serialize
155        // list content in html-syntax rather than wiki-syntax.
156        if ( DOMUtils::isListItem( $node )
157             && DOMUtils::isList( $node->parentNode )
158             && WTUtils::isLiteralHTMLNode( $node->parentNode )
159        ) {
160            return new FallbackHTMLHandler();
161        }
162
163        // Pick the best available handler
164        return $handler ?: $this->newFromTagHandler( DOMCompat::nodeName( $node ) ) ?: new FallbackHTMLHandler();
165    }
166
167}