Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
EnConverter
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 6
132
0.00% covered (danger)
0.00%
0 / 1
 getMainCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLanguageVariants
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getVariantsFallbacks
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 loadDefaultTables
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 translate
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
 pigLatin
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21/**
22 * English specific converter routines.
23 *
24 * @ingroup Languages
25 */
26class EnConverter extends LanguageConverter {
27
28    public function getMainCode(): string {
29        return 'en';
30    }
31
32    public function getLanguageVariants(): array {
33        return [ 'en', 'en-x-piglatin' ];
34    }
35
36    public function getVariantsFallbacks(): array {
37        return [];
38    }
39
40    protected function loadDefaultTables(): array {
41        return [
42            'en' => new ReplacementArray(),
43            'en-x-piglatin' => new ReplacementArray(),
44        ];
45    }
46
47    /**
48     * Translates text into Pig Latin. This allows developers to test the language variants
49     * functionality and user interface without having to switch wiki language away from default.
50     * This method also processes custom conversion rules to allow testing these parts of the
51     * language converter as well.
52     *
53     * @param string $text
54     * @param string $toVariant
55     * @return string
56     */
57    public function translate( $text, $toVariant ) {
58        if ( $toVariant !== 'en-x-piglatin' ) {
59            return $text;
60        }
61        // Apply any custom rules.  (Primarily for testing.)
62        $this->loadTables();
63        $customRules = $this->mTables[$toVariant];
64
65        if ( !$customRules->getArray() ) {
66            return self::pigLatin( $text );
67        }
68
69        // Split on the matches from custom rules, so that we only apply
70        // the Pig Latin transformation on output. which is not from a
71        // custom rule; this avoids double-conversion.
72        // (See SrConverter for similar split-and-process code.)
73        $re = '(' .
74            implode(
75                '|',
76                array_map(
77                    'preg_quote',
78                    // "Original" texts from the ReplacementArray rules
79                    array_keys( $customRules->getArray() )
80                )
81            ) . ')';
82
83        $matches = preg_split( $re, $text, -1, PREG_SPLIT_OFFSET_CAPTURE );
84        $m = array_shift( $matches );
85
86        // Apply Pig Latin transformation to the initial "non-matching" section.
87        $ret = self::pigLatin( $m[0] );
88        $mstart = (int)$m[1] + strlen( $m[0] );
89        foreach ( $matches as $m ) {
90            // Use the ReplacementArray rules to transform any matching sections
91            $ret .= $customRules->replace(
92                substr( $text, $mstart, (int)$m[1] - $mstart )
93            );
94            // And Pig Latin transformation on the non-matching sections.
95            $ret .= self::pigLatin( $m[0] );
96            $mstart = (int)$m[1] + strlen( $m[0] );
97        }
98        // $mstart will always equal strlen($text) here.
99
100        return $ret;
101    }
102
103    /**
104     * Translates words into Pig Latin.
105     *
106     * @param string $text
107     * @return string
108     */
109    private static function pigLatin( string $text ): string {
110        // Only process words composed of standard English alphabet, leave the rest unchanged.
111        // This skips some English words like 'naïve' or 'résumé', but we can live with that.
112        // Ignore single letters and words which aren't lowercase or uppercase-first.
113        return preg_replace_callback( '/[A-Za-z][a-z\']+/', static function ( $matches ) {
114            $word = $matches[0];
115            if ( preg_match( '/^[aeiou]/i', $word ) ) {
116                return $word . 'way';
117            }
118
119            return preg_replace_callback( '/^(s?qu|[^aeiou][^aeiouy]*)(.*)$/i', static function ( $m ) {
120                $ucfirst = strtoupper( $m[1][0] ) === $m[1][0];
121                if ( $ucfirst ) {
122                    return ucfirst( $m[2] ) . lcfirst( $m[1] ) . 'ay';
123                }
124
125                return $m[2] . $m[1] . 'ay';
126            }, $word );
127        }, $text );
128    }
129}