Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
86.21% |
25 / 29 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
RegexInsertablesSuggester | |
86.21% |
25 / 29 |
|
66.67% |
2 / 3 |
12.38 | |
0.00% |
0 / 1 |
__construct | |
69.23% |
9 / 13 |
|
0.00% |
0 / 1 |
7.05 | |||
getInsertables | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
mapInsertables | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
5 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace MediaWiki\Extension\Translate\TranslatorInterface\Insertable; |
5 | |
6 | use InvalidArgumentException; |
7 | |
8 | /** |
9 | * Regex InsertablesSuggester implementation that can be extended or used |
10 | * for insertables in message groups |
11 | * @author Abijeet Patro |
12 | * @license GPL-2.0-or-later |
13 | * @since 2020.12 |
14 | */ |
15 | class RegexInsertablesSuggester implements InsertablesSuggester { |
16 | /** |
17 | * The regex to run on the message. The regex must use named group captures |
18 | * @var string |
19 | */ |
20 | protected $regex = null; |
21 | /** |
22 | * The named parameter from the regex that should be used for |
23 | * insertable display. |
24 | * @var string |
25 | */ |
26 | protected $display = null; |
27 | /** |
28 | * The named parameter from the regex that should be used as pre |
29 | * @var string |
30 | */ |
31 | protected $pre = null; |
32 | /** |
33 | * The named paramater from the regex that should be used as post |
34 | * @var string |
35 | */ |
36 | protected $post = null; |
37 | |
38 | /** |
39 | * Constructor function |
40 | * @param array|string $params If params is specified as a string, it is used as the regex. |
41 | * Eg: "/\$[a-z0-9]+/". In this case `display` is the first value from the regex match. |
42 | * `pre` is also the first value from the regex match, `post` is left empty. |
43 | * |
44 | * If params is specified as a collection / array, see below for further details. |
45 | * |
46 | * Example: |
47 | * |
48 | * ``` |
49 | * params: |
50 | * regex: "/(?<pre>\[)[^]]+(?<post>\]\([^)]+\))/" |
51 | * display: "$pre $post" |
52 | * pre: "$pre" |
53 | * post: "$post" |
54 | * ``` |
55 | * |
56 | * Details: |
57 | * |
58 | * $params = [ |
59 | * 'regex' => (string, required) The regex to be used for insertable. Must use named captures. |
60 | * When specifying named captures, do not use the $ symbol in the name. In the above |
61 | * example, two named captures are used - `pre` and `post` |
62 | * 'display' => (string) Mandatory value. The display value for the insertable. Named captures |
63 | * prefixed with $ are used here. |
64 | * 'pre' => (string) The pre value for the insertable. Named captures prefixed with $ are used |
65 | * here. If not specified, is set to the display value. |
66 | * 'post' => (string) The post value for the insertable. Named captures prefixed with $ are used |
67 | * here. If not specified, defaults to an empty string. |
68 | * ] |
69 | */ |
70 | public function __construct( $params ) { |
71 | if ( is_string( $params ) ) { |
72 | $this->regex = $params; |
73 | } elseif ( is_array( $params ) ) { |
74 | // Validate if the array is in a proper format. |
75 | $this->regex = $params['regex'] ?? null; |
76 | $this->display = $params['display'] ?? null; |
77 | $this->pre = $params['pre'] ?? null; |
78 | $this->post = $params['post'] ?? null; |
79 | } |
80 | |
81 | if ( $this->regex === null ) { |
82 | throw new InvalidArgumentException( |
83 | 'Invalid configuration for the RegexInsertablesSuggester. Did not find a regex specified' |
84 | ); |
85 | } |
86 | |
87 | if ( $this->display !== null && $this->pre === null ) { |
88 | // if display value is set, and pre value is not set, set the display to pre. |
89 | // makes the configuration easier. |
90 | $this->pre = $this->display; |
91 | } |
92 | } |
93 | |
94 | public function getInsertables( string $text ): array { |
95 | $matches = []; |
96 | preg_match_all( $this->regex, $text, $matches, PREG_SET_ORDER ); |
97 | |
98 | return array_map( [ $this, 'mapInsertables' ], $matches ); |
99 | } |
100 | |
101 | protected function mapInsertables( array $match ) { |
102 | if ( $this->display === null ) { |
103 | return new Insertable( $match[0], $match[0] ); |
104 | } |
105 | |
106 | $replacements = []; |
107 | // add '$' to the other keys for replacement. |
108 | foreach ( $match as $key => $value ) { |
109 | if ( !is_int( $key ) ) { |
110 | $tmpKey = '$' . $key; |
111 | $replacements[ $tmpKey ] = $value; |
112 | } |
113 | } |
114 | |
115 | $displayVal = strtr( $this->display, $replacements ); |
116 | $preVal = strtr( $this->pre, $replacements ); |
117 | $postVal = ''; |
118 | if ( $this->post !== null ) { |
119 | $postVal = strtr( $this->post, $replacements ); |
120 | } |
121 | |
122 | return new Insertable( $displayVal, $preVal, $postVal ); |
123 | } |
124 | } |