MediaWiki  1.34.0
Updater.php
Go to the documentation of this file.
1 <?php
8 namespace LocalisationUpdate;
9 
13 class 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  $logger
132  ) {
133  $components = $finder->getComponents();
134 
135  $updatedMessages = [];
136 
137  foreach ( $components as $key => $info ) {
138  $logger->logInfo( "Updating component $key" );
139 
140  $originFiles = $this->fetchFiles( $fetcherFactory, $info['orig'] );
141  $remotePath = $this->expandRemotePath( $info, $repos );
142  try {
143  $remoteFiles = $this->fetchFiles( $fetcherFactory, $remotePath );
144  } catch ( \Exception $e ) {
145  $logger->logError( __METHOD__ . ": Unable to fetch messages from $remotePath" );
146  continue;
147  }
148 
149  if ( $remoteFiles === [] ) {
150  // Small optimization: if nothing to compare with, skip
151  continue;
152  }
153 
154  $originMessages = $this->readMessages( $readerFactory, $originFiles );
155  $remoteMessages = $this->readMessages( $readerFactory, $remoteFiles );
156 
157  if ( !isset( $remoteMessages['en'] ) ) {
158  // Could not find remote messages
159  continue;
160  }
161 
162  // If remote translation in English is not present or differs, we do not want
163  // translations for other languages for those messages, as they are either not
164  // used in this version of code or can be incompatible.
165  $forbiddenKeys = $this->findChangedTranslations(
166  $originMessages['en'],
167  $remoteMessages['en']
168  );
169 
170  // We never accept updates for English strings
171  unset( $originMessages['en'], $remoteMessages['en'] );
172 
173  // message: string in all languages; translation: string in one language.
174  foreach ( $remoteMessages as $language => $remoteTranslations ) {
175  // Check for completely new languages
176  $originTranslations = [];
177  if ( isset( $originMessages[$language] ) ) {
178  $originTranslations = $originMessages[$language];
179  }
180 
181  $updatedTranslations = $this->findChangedTranslations(
182  $originTranslations,
183  $remoteTranslations,
184  $forbiddenKeys
185  );
186 
187  // Avoid empty arrays
188  if ( $updatedTranslations === [] ) {
189  continue;
190  }
191 
192  if ( !isset( $updatedMessages[$language] ) ) {
193  $updatedMessages[$language] = [];
194  }
195 
196  // In case of conflicts, which should not exist, this prefers the
197  // first translation seen.
198  $updatedMessages[$language] += $updatedTranslations;
199  }
200  }
201 
202  return $updatedMessages;
203  }
204 }
LocalisationUpdate\Updater\findChangedTranslations
findChangedTranslations( $origin, $remote, $blacklist=[])
Find new and changed translations in $remote and returns them.
Definition: Updater.php:92
LocalisationUpdate\Updater\isDirectory
isDirectory( $path)
Whether the path is a pattern and thus we need to use appropriate code for fetching directories.
Definition: Updater.php:21
LocalisationUpdate\Updater\expandRemotePath
expandRemotePath( $info, $repos)
Expands repository relative path to full url with the given repository patterns.
Definition: Updater.php:35
LocalisationUpdate\Updater
Executes the localisation update.
Definition: Updater.php:13
LocalisationUpdate
Definition: Fetcher.php:8
LocalisationUpdate\ReaderFactory
Constructs readers for files based on the names.
Definition: ReaderFactory.php:13
LocalisationUpdate\Updater\fetchFiles
fetchFiles(FetcherFactory $factory, $path)
Fetches files from given Url pattern.
Definition: Updater.php:113
$path
$path
Definition: NoLocalSettings.php:25
$keys
$keys
Definition: testCompression.php:67
LocalisationUpdate\Updater\readMessages
readMessages(ReaderFactory $readerFactory, array $files)
Parses translations from given list of files.
Definition: Updater.php:57
LocalisationUpdate\ReaderFactory\getReader
getReader( $filename)
Constructs a suitable reader for a given path.
Definition: ReaderFactory.php:20
LocalisationUpdate\Updater\execute
execute(Finder $finder, ReaderFactory $readerFactory, FetcherFactory $fetcherFactory, array $repos, $logger)
Definition: Updater.php:126