Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
69.23% covered (warning)
69.23%
9 / 13
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
AnchorFormatter
69.23% covered (warning)
69.23%
9 / 13
71.43% covered (warning)
71.43%
5 / 7
9.86
0.00% covered (danger)
0.00%
0 / 1
 refKey
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 backLink
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 backLinkTarget
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getReferencesKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 jumpLink
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 jumpLinkTarget
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 normalizeKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Cite;
4
5use MediaWiki\Parser\Sanitizer;
6
7/**
8 * Compiles unique identifiers and formats them as anchors for use in `href="#…"` and `id="…"`
9 * attributes.
10 *
11 * @license GPL-2.0-or-later
12 */
13class AnchorFormatter {
14
15    /**
16     * Return an id for use in wikitext output based on a key and
17     * optionally the number of it, used in <references>, not <ref>
18     * (since otherwise it would link to itself)
19     *
20     * @param string|int $key
21     * @param string|null $num The number of the key
22     *
23     * @return string
24     */
25    private function refKey( $key, ?string $num ): string {
26        if ( $num !== null ) {
27            $key = $key . '_' . $num;
28        }
29        return $this->normalizeKey( "cite_ref-$key" );
30    }
31
32    /**
33     * @param string|int $key
34     * @param string|null $num
35     * @return string Escaped to be used as part of a [[#…]] link
36     */
37    public function backLink( $key, ?string $num = null ): string {
38        $key = $this->refKey( $key, $num );
39        // This does both URL encoding (e.g. %A0, which only makes sense in href="…") and HTML
40        // entity encoding (e.g. &#xA0;). The browser will decode in reverse order.
41        return Sanitizer::safeEncodeAttribute( Sanitizer::escapeIdForLink( $key ) );
42    }
43
44    /**
45     * @param string|int $key
46     * @param string|null $num
47     * @return string Already escaped to be used directly in an id="…" attribute
48     */
49    public function backLinkTarget( $key, ?string $num ): string {
50        $key = $this->refKey( $key, $num );
51        return Sanitizer::safeEncodeAttribute( $key );
52    }
53
54    /**
55     * Return an id for use in wikitext output based on a key and
56     * optionally the number of it, used in <ref>, not <references>
57     * (since otherwise it would link to itself)
58     *
59     * @param string $key
60     *
61     * @return string
62     */
63    private function getReferencesKey( string $key ): string {
64        return $this->normalizeKey( "cite_note-$key" );
65    }
66
67    /**
68     * @param string $key
69     * @return string Escaped to be used as part of a [[#…]] link
70     */
71    public function jumpLink( string $key ): string {
72        $key = $this->getReferencesKey( $key );
73        // This does both URL encoding (e.g. %A0, which only makes sense in href="…") and HTML
74        // entity encoding (e.g. &#xA0;). The browser will decode in reverse order.
75        return Sanitizer::safeEncodeAttribute( Sanitizer::escapeIdForLink( $key ) );
76    }
77
78    /**
79     * @param string $key
80     * @return string Already escaped to be used directly in an id="…" attribute
81     */
82    public function jumpLinkTarget( string $key ): string {
83        $key = $this->getReferencesKey( $key );
84        return Sanitizer::safeEncodeAttribute( $key );
85    }
86
87    private function normalizeKey( string $key ): string {
88        // MediaWiki normalizes spaces and underscores in [[#…]] links, but not in id="…"
89        // attributes. To make them behave the same we normalize in advance.
90        return preg_replace( '/[_\s]+/u', '_', $key );
91    }
92
93}