Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.30% covered (success)
96.30%
26 / 27
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
RemoveRedLinks
96.30% covered (success)
96.30%
26 / 27
50.00% covered (danger)
50.00%
1 / 2
10
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 run
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
9
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Html2Wt;
5
6use Wikimedia\Parsoid\Config\Env;
7use Wikimedia\Parsoid\DOM\Element;
8use Wikimedia\Parsoid\DOM\Node;
9use Wikimedia\Parsoid\Utils\DOMCompat;
10use Wikimedia\Parsoid\Utils\UrlUtils;
11
12class RemoveRedLinks {
13
14    private Env $env;
15
16    public function __construct( Env $env ) {
17        $this->env = $env;
18    }
19
20    /**
21     * Remove redlinks from a document
22     * @param Element $root
23     */
24    public function run( Node $root ): void {
25        '@phan-var Element|DocumentFragment $root';  // @var Element|DocumentFragment $root
26        $wikilinks = DOMCompat::querySelectorAll( $root, 'a[rel~="mw:WikiLink"].new' );
27        foreach ( $wikilinks as $a ) {
28            $href = DOMCompat::getAttribute( $a, 'href' );
29            $qmPos = strpos( $href ?? '', '?' );
30            if ( $qmPos !== false ) {
31                $parsedURL = UrlUtils::parseUrl( $href );
32                if ( !isset( $parsedURL['query'] ) ) {
33                    // TODO this mitigates a bug in the AddRedLinks pass, which puts the query
34                    // parameters AFTER a fragment; the parse_url then interprets these query parameters
35                    // as part of the fragment.
36                    // 2022-12-01: That issue is solved in the "wt2html" direction, but some
37                    // RESTBase-stored content may still exist, so we'll have to remove this when
38                    // 2.7.0 is not longer being stored.
39                    $href = str_replace(
40                        [ '?action=edit&redlink=1', '?action=edit&amp;redlink=1',
41                            '&action=edit&redlink=1', '&amp;action=edit&amp;redlink=1' ],
42                        [ '', '', '', '' ],
43                        $href
44                    );
45                } else {
46                    $queryParams = $parsedURL['query'];
47                    $queryElts = [];
48                    parse_str( $queryParams, $queryElts );
49                    if ( isset( $queryElts['action'] ) && $queryElts['action'] === 'edit' ) {
50                        unset( $queryElts['action'] );
51                    }
52                    if ( isset( $queryElts['redlink'] ) && $queryElts['redlink'] === '1' ) {
53                        unset( $queryElts['redlink'] );
54                    }
55
56                    // My understanding of this method and of PHP array handling makes me
57                    // believe that the order of the parameters should not be modified here.
58                    // There is however no guarantee whatsoever in the documentation or spec
59                    // of these methods.
60                    $newQueryParams = http_build_query( $queryElts );
61
62                    if ( count( $queryElts ) === 0 ) {
63                        // avoids the insertion of ? on empty query string
64                        $parsedURL['query'] = null;
65                    } else {
66                        $parsedURL['query'] = http_build_query( $queryElts );
67                    }
68                    $href = UrlUtils::assembleUrl( $parsedURL );
69                }
70                $a->setAttribute( 'href', $href );
71            }
72        }
73    }
74}