Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReplacementMachine
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 4
110
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
 getCodes
n/a
0 / 0
n/a
0 / 0
0
 isValidCodePair
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 replace
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 convert
n/a
0 / 0
n/a
0 / 0
0
 jsonEncode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Wikimedia\LangConv;
4
5use DOMDocument;
6use DOMDocumentFragment;
7use DOMNode;
8
9/**
10 * A machine to convert and/or replace text.
11 */
12abstract class ReplacementMachine {
13    /**
14     * ReplacementMachine constructor.
15     */
16    public function __construct() {
17    }
18
19    /**
20     * Return the set of language codes supported.  Both key and value are
21     * set in order to facilitate inclusion testing.
22     *
23     * @return array<string,string>
24     */
25    abstract public function getCodes();
26
27    /**
28     * Override this method in subclass if you want to limit the possible code pairs bracketed.
29     * (For example, zh has a large number of variants, but we typically want to use only a limited
30     * number of these as possible invert codes.)
31     * @param string $destCode
32     * @param string $invertCode
33     * @return bool whether this is a valid bracketing pair.
34     */
35    public function isValidCodePair( $destCode, $invertCode ) {
36        return true;
37    }
38
39    /**
40     * Replace the given text Node with converted text, protecting any markup which can't be
41     * round-tripped back to `invertCode` with appropriate synthetic language-converter markup.
42     * @param DOMNode $textNode
43     * @param string $destCode
44     * @param string $invertCode
45     * @return DOMNode
46     */
47    public function replace( $textNode, $destCode, $invertCode ) {
48        $fragment = $this->convert(
49            $textNode->ownerDocument,
50            $textNode->textContent,
51            $destCode,
52            $invertCode
53        );
54        // Was a change made?
55        $next = $textNode->nextSibling;
56        if (
57            // `fragment` has exactly 1 child.
58            $fragment->firstChild && !$fragment->firstChild->nextSibling &&
59            // `fragment.firstChild` is a DOM text node
60            $fragment->firstChild->nodeType === XML_TEXT_NODE &&
61            // `textNode` is a DOM text node
62            $textNode->nodeType === XML_TEXT_NODE &&
63            $textNode->textContent === $fragment->firstChild->textContent
64        ) {
65            return $next; // No change.
66        }
67        // Poor man's `$textNode->replaceWith($fragment)`; use the
68        // actual DOM method if/when we switch to a proper DOM implementation
69        $parentNode = $textNode->parentNode;
70        if ( $fragment->firstChild ) { # fragment could be empty!
71            $parentNode->insertBefore( $fragment, $textNode );
72        }
73        $parentNode->removeChild( $textNode );
74
75        return $next;
76    }
77
78    /**
79     * Convert a string of text.
80     * @param DOMDocument $document
81     * @param string $s text to convert
82     * @param string $destCode destination language code
83     * @param string $invertCode
84     * @return DOMDocumentFragment DocumentFragment containing converted text
85     */
86    abstract public function convert( $document, $s, $destCode, $invertCode );
87
88    /**
89     * Allow client to customize the JSON encoding of data-mw-variant
90     * attributes.
91     * @param array $obj The structured attribute value to encode
92     * @return string The encoded attribute value
93     */
94    public function jsonEncode( array $obj ): string {
95        return json_encode( $obj, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
96    }
97
98}