MediaWiki REL1_30
Updater.php
Go to the documentation of this file.
1<?php
8namespace LocalisationUpdate;
9
13class Updater {
21 public function isDirectory( $path ) {
22 $filename = basename( $path );
23 return strpos( $filename, '*' ) !== false;
24 }
25
35 public function expandRemotePath( $info, $repos ) {
36 $pattern = $repos[$info['repo']];
37 unset( $info['repo'], $info['orig'] );
38
39 // This assumes all other keys are used as variables
40 // in the pattern. For example name -> %NAME%.
41 $keys = [];
42 foreach ( array_keys( $info ) as $key ) {
43 $keys[] = '%' . strtoupper( $key ) . '%';
44 }
45
46 $values = array_values( $info );
47 return str_replace( $keys, $values, $pattern );
48 }
49
57 public function readMessages( ReaderFactory $readerFactory, array $files ) {
58 $messages = [];
59
60 foreach ( $files as $filename => $contents ) {
61 $reader = $readerFactory->getReader( $filename );
62 try {
63 $parsed = $reader->parse( $contents );
64 } catch ( \Exception $e ) {
65 trigger_error( __METHOD__ . ": Unable to parse messages from $filename", E_USER_WARNING );
66 continue;
67 }
68
69 foreach ( $parsed as $code => $langMessages ) {
70 if ( !isset( $messages[$code] ) ) {
71 $messages[$code] = [];
72 }
73 $messages[$code] = array_merge( $messages[$code], $langMessages );
74 }
75
76 $c = array_sum( array_map( 'count', $parsed ) );
77 // Useful for debugging, maybe create interface to pass this to the script?
78 # echo "$filename with " . get_class( $reader ) . " and $c\n";
79 }
80
81 return $messages;
82 }
83
92 public function findChangedTranslations( $origin, $remote, $blacklist = [] ) {
93 $changed = [];
94 foreach ( $remote as $key => $value ) {
95 if ( isset( $blacklist[$key] ) ) {
96 continue;
97 }
98
99 if ( !isset( $origin[$key] ) || $value !== $origin[$key] ) {
100 $changed[$key] = $value;
101 }
102 }
103 return $changed;
104 }
105
113 public function fetchFiles( FetcherFactory $factory, $path ) {
114 $fetcher = $factory->getFetcher( $path );
115
116 if ( $this->isDirectory( $path ) ) {
117 $files = $fetcher->fetchDirectory( $path );
118 } else {
119 $files = [ $path => $fetcher->fetchFile( $path ) ];
120 }
121
122 // Remove files which were not found
123 return array_filter( $files );
124 }
125
126 public function execute(
127 Finder $finder,
128 ReaderFactory $readerFactory,
129 FetcherFactory $fetcherFactory,
130 array $repos
131 ) {
132 $components = $finder->getComponents();
133
134 $updatedMessages = [];
135
136 foreach ( $components as $key => $info ) {
137 $originFiles = $this->fetchFiles( $fetcherFactory, $info['orig'] );
138 $remoteFiles = $this->fetchFiles( $fetcherFactory, $this->expandRemotePath( $info, $repos ) );
139
140 if ( $remoteFiles === [] ) {
141 // Small optimization: if nothing to compare with, skip
142 continue;
143 }
144
145 $originMessages = $this->readMessages( $readerFactory, $originFiles );
146 $remoteMessages = $this->readMessages( $readerFactory, $remoteFiles );
147
148 if ( !isset( $remoteMessages['en'] ) ) {
149 // Could not find remote messages
150 continue;
151 }
152
153 // If remote translation in English is not present or differs, we do not want
154 // translations for other languages for those messages, as they are either not
155 // used in this version of code or can be incompatible.
156 $forbiddenKeys = $this->findChangedTranslations(
157 $originMessages['en'],
158 $remoteMessages['en']
159 );
160
161 // We never accept updates for English strings
162 unset( $originMessages['en'], $remoteMessages['en'] );
163
164 // message: string in all languages; translation: string in one language.
165 foreach ( $remoteMessages as $language => $remoteTranslations ) {
166 // Check for completely new languages
167 $originTranslations = [];
168 if ( isset( $originMessages[$language] ) ) {
169 $originTranslations = $originMessages[$language];
170 }
171
172 $updatedTranslations = $this->findChangedTranslations(
173 $originTranslations,
174 $remoteTranslations,
175 $forbiddenKeys
176 );
177
178 // Avoid empty arrays
179 if ( $updatedTranslations === [] ) {
180 continue;
181 }
182
183 if ( !isset( $updatedMessages[$language] ) ) {
184 $updatedMessages[$language] = [];
185 }
186
187 // In case of conflicts, which should not exist, this prefers the
188 // first translation seen.
189 $updatedMessages[$language] += $updatedTranslations;
190 }
191 }
192
193 return $updatedMessages;
194 }
195}
$messages
Constructs fetchers based on the repository urls.
Interface for classes which provide list of components, which should be included for l10n updates.
Definition Finder.php:14
Constructs readers for files based on the names.
Executes the localisation update.
Definition Updater.php:13
fetchFiles(FetcherFactory $factory, $path)
Fetches files from given Url pattern.
Definition Updater.php:113
execute(Finder $finder, ReaderFactory $readerFactory, FetcherFactory $fetcherFactory, array $repos)
Definition Updater.php:126
expandRemotePath( $info, $repos)
Expands repository relative path to full url with the given repository patterns.
Definition Updater.php:35
findChangedTranslations( $origin, $remote, $blacklist=[])
Find new and changed translations in $remote and returns them.
Definition Updater.php:92
readMessages(ReaderFactory $readerFactory, array $files)
Parses translations from given list of files.
Definition Updater.php:57
isDirectory( $path)
Whether the path is a pattern and thus we need to use appropriate code for fetching directories.
Definition Updater.php:21
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code
Definition hooks.txt:863
returning false will NOT prevent logging $e
Definition hooks.txt:2146