Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
91.11% |
41 / 45 |
|
88.89% |
8 / 9 |
CRAP | |
0.00% |
0 / 1 |
ParserOutput | |
91.11% |
41 / 45 |
|
88.89% |
8 / 9 |
16.18 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
sourcePageTemplate | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
translationPageTemplate | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
units | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
sourcePageTextForRendering | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPageTextForRendering | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
2 | |||
sourcePageTextForSaving | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
sourcePageTemplateForDiffs | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
assertContainsOnlyInstancesOf | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace MediaWiki\Extension\Translate\PageTranslation; |
5 | |
6 | use InvalidArgumentException; |
7 | use Language; |
8 | use MediaWiki\Extension\Translate\MessageLoading\Message; |
9 | use Parser; |
10 | |
11 | /** |
12 | * Represents a parsing output produced by TranslatablePageParser. |
13 | * |
14 | * It is required generate translatable and translation page sources or just get the list of |
15 | * translations units. |
16 | * |
17 | * @author Niklas Laxström |
18 | * @license GPL-2.0-or-later |
19 | * @since 2020.08 |
20 | */ |
21 | class ParserOutput { |
22 | /** @var string */ |
23 | private $template; |
24 | /** @var Section[] */ |
25 | private $sectionMap; |
26 | /** @var TranslationUnit[] */ |
27 | private $unitMap; |
28 | |
29 | public function __construct( string $template, array $sectionMap, array $unitMap ) { |
30 | $this->assertContainsOnlyInstancesOf( Section::class, '$sectionMap', $sectionMap ); |
31 | $this->assertContainsOnlyInstancesOf( TranslationUnit::class, '$unitMap', $unitMap ); |
32 | |
33 | $this->template = $template; |
34 | $this->sectionMap = $sectionMap; |
35 | $this->unitMap = $unitMap; |
36 | } |
37 | |
38 | /** Returns template that contains <translate> tags */ |
39 | public function sourcePageTemplate(): string { |
40 | $replacements = []; |
41 | foreach ( $this->sectionMap as $ph => $section ) { |
42 | $replacements[$ph] = $section->wrappedContents(); |
43 | } |
44 | |
45 | return strtr( $this->template, $replacements ); |
46 | } |
47 | |
48 | /** Returns template that does not contain <translate> tags */ |
49 | public function translationPageTemplate(): string { |
50 | $replacements = []; |
51 | foreach ( $this->sectionMap as $ph => $section ) { |
52 | $replacements[$ph] = $section->contents(); |
53 | } |
54 | |
55 | return strtr( $this->template, $replacements ); |
56 | } |
57 | |
58 | /** @return TranslationUnit[] */ |
59 | public function units(): array { |
60 | return $this->unitMap; |
61 | } |
62 | |
63 | /** Returns the source page wikitext used for rendering the page. */ |
64 | public function sourcePageTextForRendering( Language $sourceLanguage ): string { |
65 | return $this->getPageTextForRendering( $sourceLanguage, $sourceLanguage, false ); |
66 | } |
67 | |
68 | /** |
69 | * @param Language $sourceLanguage Language of the translatable page |
70 | * @param Language $targetLanguage Language of the translation page; same as |
71 | * $sourceLanguage when rendering the translatable page |
72 | * @param bool $wrapUntranslated Whether to wrap untranslated units in `<span>` or `<div>` |
73 | * with appropriate language and directionality set |
74 | * @param array<string,Message> $messages Translations by translation unit; |
75 | * empty when rendering the translatable page |
76 | * @param Parser|null $parser Wikitext parser to use when generating anchors for translated |
77 | * headings; if `null`, no anchors will be generated |
78 | */ |
79 | public function getPageTextForRendering( |
80 | Language $sourceLanguage, |
81 | Language $targetLanguage, |
82 | bool $wrapUntranslated, |
83 | array $messages = [], |
84 | ?Parser $parser = null |
85 | ): string { |
86 | $text = $this->translationPageTemplate(); |
87 | |
88 | foreach ( $this->unitMap as $ph => $s ) { |
89 | $t = $s->getTextForRendering( |
90 | $messages[$s->id] ?? null, |
91 | $sourceLanguage, |
92 | $targetLanguage, |
93 | $wrapUntranslated, |
94 | $parser |
95 | ); |
96 | $text = str_replace( $ph, $t, $text ); |
97 | } |
98 | |
99 | // Replace {{TRANSLATIONLANGUAGE}} usage outside of translation units (T224810) |
100 | $text = preg_replace( |
101 | TranslationUnit::TRANSLATIONLANGUAGE_REGEX, |
102 | $targetLanguage->getCode(), |
103 | $text |
104 | ); |
105 | |
106 | return $text; |
107 | } |
108 | |
109 | /** Returns the source page with translation unit markers. */ |
110 | public function sourcePageTextForSaving(): string { |
111 | $text = $this->sourcePageTemplate(); |
112 | |
113 | foreach ( $this->unitMap as $ph => $s ) { |
114 | $text = str_replace( $ph, $s->getMarkedText(), $text ); |
115 | } |
116 | |
117 | return $text; |
118 | } |
119 | |
120 | /** Returns the page text with translation tags and unit placeholders for easy diffs */ |
121 | public function sourcePageTemplateForDiffs(): string { |
122 | $text = $this->sourcePageTemplate(); |
123 | |
124 | foreach ( $this->unitMap as $ph => $s ) { |
125 | $text = str_replace( $ph, "<!--T:{$s->id}-->", $text ); |
126 | } |
127 | |
128 | return $text; |
129 | } |
130 | |
131 | private function assertContainsOnlyInstancesOf( |
132 | string $expected, |
133 | string $name, |
134 | array $x |
135 | ): void { |
136 | foreach ( $x as $item ) { |
137 | if ( !$item instanceof $expected ) { |
138 | $actual = gettype( $item ); |
139 | throw new InvalidArgumentException( |
140 | "Parameter $name must only contain instances of class $expected. Got $actual." |
141 | ); |
142 | } |
143 | } |
144 | } |
145 | } |