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