Index: trunk/extensions/LocalisationUpdate/LocalisationUpdate.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | /** |
13 | 13 | * Directory to store serialized cache files in. Defaults to $wgCacheDirectory. |
14 | 14 | * It's OK to share this directory among wikis as long as the wiki you run |
15 | | - * update.php on has all extensions the other wikis using the same directory |
| 15 | + * update.php on has all extensions the other wikis using the same directory |
16 | 16 | * have. |
17 | 17 | * NOTE: If this variable and $wgCacheDirectory are both false, this extension |
18 | 18 | * WILL NOT WORK. |
— | — | @@ -33,7 +33,6 @@ |
34 | 34 | |
35 | 35 | $wgLocalisationUpdateRetryAttempts = 5; |
36 | 36 | |
37 | | - |
38 | 37 | // Info about me! |
39 | 38 | $wgExtensionCredits['other'][] = array( |
40 | 39 | 'path' => __FILE__, |
Index: trunk/extensions/LocalisationUpdate/LocalisationUpdate.class.php |
— | — | @@ -2,21 +2,21 @@ |
3 | 3 | |
4 | 4 | /** |
5 | 5 | * Class for localization updates. |
6 | | - * |
| 6 | + * |
7 | 7 | * TODO: refactor code to remove duplication |
8 | 8 | */ |
9 | 9 | class LocalisationUpdate { |
10 | | - |
| 10 | + |
11 | 11 | private static $newHashes = null; |
12 | 12 | private static $filecache = array(); |
13 | | - |
| 13 | + |
14 | 14 | /** |
15 | 15 | * LocalisationCacheRecache hook handler. |
16 | | - * |
| 16 | + * |
17 | 17 | * @param $lc LocalisationCache |
18 | 18 | * @param $langcode String |
19 | 19 | * @param $cache Array |
20 | | - * |
| 20 | + * |
21 | 21 | * @return true |
22 | 22 | */ |
23 | 23 | public static function onRecache( LocalisationCache $lc, $langcode, array &$cache ) { |
— | — | @@ -24,50 +24,50 @@ |
25 | 25 | $cache['messages'], |
26 | 26 | self::readFile( $langcode ) |
27 | 27 | ); |
28 | | - |
| 28 | + |
29 | 29 | $cache['deps'][] = new FileDependency( |
30 | 30 | self::filename( $langcode ) |
31 | 31 | ); |
32 | | - |
| 32 | + |
33 | 33 | return true; |
34 | 34 | } |
35 | 35 | |
36 | 36 | /** |
37 | 37 | * Called from the cronjob to fetch new messages from SVN. |
38 | | - * |
| 38 | + * |
39 | 39 | * @param $options Array |
40 | | - * |
| 40 | + * |
41 | 41 | * @return true |
42 | 42 | */ |
43 | 43 | public static function updateMessages( array $options ) { |
44 | 44 | global $wgLocalisationUpdateDirectory; |
45 | | - |
| 45 | + |
46 | 46 | $verbose = !isset( $options['quiet'] ); |
47 | 47 | $all = isset( $options['all'] ); |
48 | 48 | $skipCore = isset( $options['skip-core'] ); |
49 | 49 | $skipExtensions = isset( $options['skip-extensions'] ); |
50 | | - |
| 50 | + |
51 | 51 | if( isset( $options['outdir'] ) ) { |
52 | 52 | $wgLocalisationUpdateDirectory = $options['outdir']; |
53 | 53 | } |
54 | | - |
| 54 | + |
55 | 55 | $result = 0; |
56 | | - |
| 56 | + |
57 | 57 | // Update all MW core messages. |
58 | 58 | if( !$skipCore ) { |
59 | 59 | $result = self::updateMediawikiMessages( $verbose ); |
60 | 60 | } |
61 | | - |
| 61 | + |
62 | 62 | // Update all Extension messages. |
63 | 63 | if( !$skipExtensions ) { |
64 | 64 | if( $all ) { |
65 | 65 | global $IP; |
66 | 66 | $extFiles = array(); |
67 | | - |
| 67 | + |
68 | 68 | // Look in extensions/ for all available items... |
69 | 69 | // TODO: add support for $wgExtensionAssetsPath |
70 | 70 | $dirs = new RecursiveDirectoryIterator( "$IP/extensions/" ); |
71 | | - |
| 71 | + |
72 | 72 | // I ain't kidding... RecursiveIteratorIterator. |
73 | 73 | foreach( new RecursiveIteratorIterator( $dirs ) as $pathname => $item ) { |
74 | 74 | $filename = basename( $pathname ); |
— | — | @@ -85,30 +85,30 @@ |
86 | 86 | $result += self::updateExtensionMessages( $locFile, $extension, $verbose ); |
87 | 87 | } |
88 | 88 | } |
89 | | - |
| 89 | + |
90 | 90 | self::writeHashes(); |
91 | 91 | |
92 | 92 | // And output the result! |
93 | 93 | self::myLog( "Updated {$result} messages in total" ); |
94 | 94 | self::myLog( "Done" ); |
95 | | - |
| 95 | + |
96 | 96 | return true; |
97 | 97 | } |
98 | 98 | |
99 | 99 | /** |
100 | 100 | * Update Extension Messages. |
101 | | - * |
| 101 | + * |
102 | 102 | * @param $file String |
103 | 103 | * @param $extension String |
104 | 104 | * @param $verbose Boolean |
105 | | - * |
| 105 | + * |
106 | 106 | * @return Integer: the amount of updated messages |
107 | 107 | */ |
108 | 108 | public static function updateExtensionMessages( $file, $extension, $verbose ) { |
109 | 109 | global $IP, $wgLocalisationUpdateSVNURL; |
110 | | - |
| 110 | + |
111 | 111 | $relfile = wfRelativePath( $file, "$IP/extensions" ); |
112 | | - |
| 112 | + |
113 | 113 | // Create a full path. |
114 | 114 | // TODO: add support for $wgExtensionAssetsPath |
115 | 115 | $localfile = "$IP/extensions/$relfile"; |
— | — | @@ -119,15 +119,15 @@ |
120 | 120 | |
121 | 121 | // Compare the 2 files. |
122 | 122 | $result = self::compareExtensionFiles( $extension, $svnfile, $file, $verbose, false, true ); |
123 | | - |
| 123 | + |
124 | 124 | return $result; |
125 | 125 | } |
126 | 126 | |
127 | 127 | /** |
128 | 128 | * Update the Mediawiki Core Messages. |
129 | | - * |
| 129 | + * |
130 | 130 | * @param $verbose Boolean |
131 | | - * |
| 131 | + * |
132 | 132 | * @return Integer: the amount of updated messages |
133 | 133 | */ |
134 | 134 | public static function updateMediawikiMessages( $verbose ) { |
— | — | @@ -173,22 +173,22 @@ |
174 | 174 | |
175 | 175 | // Compare the files. |
176 | 176 | $result = self::compareFiles( $svnfile, $localfile, $verbose, $changedEnglishStrings, false, true ); |
177 | | - |
| 177 | + |
178 | 178 | // And update the change counter. |
179 | 179 | $changedCount += count( $result ); |
180 | 180 | } |
181 | 181 | |
182 | 182 | // Log some nice info. |
183 | 183 | self::myLog( "{$changedCount} Mediawiki messages are updated" ); |
184 | | - |
| 184 | + |
185 | 185 | return $changedCount; |
186 | 186 | } |
187 | 187 | |
188 | 188 | /** |
189 | 189 | * Removes all unneeded content from a file and returns it. |
190 | | - * |
| 190 | + * |
191 | 191 | * @param $contents String |
192 | | - * |
| 192 | + * |
193 | 193 | * @return String |
194 | 194 | */ |
195 | 195 | public static function cleanupFile( $contents ) { |
— | — | @@ -199,9 +199,9 @@ |
200 | 200 | '?' . '>' => '' |
201 | 201 | ) |
202 | 202 | ); |
203 | | - |
| 203 | + |
204 | 204 | $results = array(); |
205 | | - |
| 205 | + |
206 | 206 | // And we only want the messages array. |
207 | 207 | preg_match( "/\\\$messages(.*\s)*?\);/", $contents, $results ); |
208 | 208 | |
— | — | @@ -218,26 +218,26 @@ |
219 | 219 | // Return the cleaned up file. |
220 | 220 | return $contents; |
221 | 221 | } |
222 | | - |
| 222 | + |
223 | 223 | /** |
224 | 224 | * Removes all unneeded content from a file and returns it. |
225 | | - * |
226 | | - * FIXME: duplicated cleanupFile code |
227 | | - * |
| 225 | + * |
| 226 | + * FIXME: duplicated cleanupFile code |
| 227 | + * |
228 | 228 | * @param $contents String |
229 | | - * |
| 229 | + * |
230 | 230 | * @return string |
231 | 231 | */ |
232 | 232 | public static function cleanupExtensionFile( $contents ) { |
233 | 233 | // We don't want PHP tags. |
234 | 234 | $contents = preg_replace( "/<\?php/", "", $contents ); |
235 | 235 | $contents = preg_replace( "/\?" . ">/", "", $contents ); |
236 | | - |
| 236 | + |
237 | 237 | $results = array(); |
238 | | - |
| 238 | + |
239 | 239 | // And we only want message arrays. |
240 | 240 | preg_match_all( "/\\\$messages(.*\s)*?\);/", $contents, $results ); |
241 | | - |
| 241 | + |
242 | 242 | // But we want them all in one string. |
243 | 243 | if( !empty( $results[0] ) && is_array( $results[0] ) ) { |
244 | 244 | $contents = implode( "\n\n", $results[0] ); |
— | — | @@ -247,23 +247,23 @@ |
248 | 248 | |
249 | 249 | // And we hate the windows vs linux linebreaks. |
250 | 250 | $contents = preg_replace( "/\\\r\\\n?/", "\n", $contents ); |
251 | | - |
| 251 | + |
252 | 252 | return $contents; |
253 | | - } |
| 253 | + } |
254 | 254 | |
255 | 255 | /** |
256 | 256 | * Returns the contents of a file or false on failiure. |
257 | | - * |
| 257 | + * |
258 | 258 | * @param $basefile String |
259 | | - * |
| 259 | + * |
260 | 260 | * @return string or false |
261 | 261 | */ |
262 | 262 | public static function getFileContents( $basefile ) { |
263 | 263 | global $wgLocalisationUpdateRetryAttempts; |
264 | | - |
| 264 | + |
265 | 265 | $attempts = 0; |
266 | 266 | $basefilecontents = ''; |
267 | | - |
| 267 | + |
268 | 268 | // Use cURL to get the SVN contents. |
269 | 269 | if ( preg_match( "/^http/", $basefile ) ) { |
270 | 270 | while( !$basefilecontents && $attempts <= $wgLocalisationUpdateRetryAttempts ) { |
— | — | @@ -272,7 +272,7 @@ |
273 | 273 | self::myLog( 'Failed to download ' . $basefile . "; retrying in ${delay}s..." ); |
274 | 274 | sleep( $delay ); |
275 | 275 | } |
276 | | - |
| 276 | + |
277 | 277 | $basefilecontents = Http::get( $basefile ); |
278 | 278 | $attempts++; |
279 | 279 | } |
— | — | @@ -286,20 +286,20 @@ |
287 | 287 | return false; |
288 | 288 | } |
289 | 289 | } |
290 | | - |
| 290 | + |
291 | 291 | return $basefilecontents; |
292 | 292 | } |
293 | 293 | |
294 | 294 | /** |
295 | 295 | * Returns an array containing the differences between the files. |
296 | | - * |
| 296 | + * |
297 | 297 | * @param $basefile String |
298 | 298 | * @param $comparefile String |
299 | 299 | * @param $verbose Boolean |
300 | 300 | * @param $forbiddenKeys Array |
301 | 301 | * @param $alwaysGetResult Boolean |
302 | 302 | * @param $saveResults Boolean |
303 | | - * |
| 303 | + * |
304 | 304 | * @return array |
305 | 305 | */ |
306 | 306 | public static function compareFiles( $basefile, $comparefile, $verbose, array $forbiddenKeys = array(), $alwaysGetResult = true, $saveResults = false ) { |
— | — | @@ -307,7 +307,7 @@ |
308 | 308 | $langcode = Language::getCodeFromFileName( $basefile, 'Messages' ); |
309 | 309 | |
310 | 310 | $basefilecontents = self::getFileContents( $basefile ); |
311 | | - |
| 311 | + |
312 | 312 | if ( $basefilecontents === false || $basefilecontents === '' ) { |
313 | 313 | return array(); // Failed |
314 | 314 | } |
— | — | @@ -318,7 +318,7 @@ |
319 | 319 | // Change the variable name. |
320 | 320 | $basefilecontents = preg_replace( "/\\\$messages/", "\$base_messages", $basefilecontents ); |
321 | 321 | $basehash = md5( $basefilecontents ); |
322 | | - |
| 322 | + |
323 | 323 | // Check if the file has changed since our last update. |
324 | 324 | if ( !$alwaysGetResult ) { |
325 | 325 | if ( !self::checkHash( $basefile, $basehash ) ) { |
— | — | @@ -331,7 +331,7 @@ |
332 | 332 | $base_messages = self::parsePHP( $basefilecontents, 'base_messages' ); |
333 | 333 | |
334 | 334 | $comparefilecontents = self::getFileContents( $comparefile ); |
335 | | - |
| 335 | + |
336 | 336 | if ( $comparefilecontents === false || $comparefilecontents === '' ) { |
337 | 337 | return array(); // Failed |
338 | 338 | } |
— | — | @@ -342,7 +342,7 @@ |
343 | 343 | // Rename the array. |
344 | 344 | $comparefilecontents = preg_replace( "/\\\$messages/", "\$compare_messages", $comparefilecontents ); |
345 | 345 | $comparehash = md5( $comparefilecontents ); |
346 | | - |
| 346 | + |
347 | 347 | // If this is the remote file check if the file has changed since our last update. |
348 | 348 | if ( preg_match( "/^http/", $comparefile ) && !$alwaysGetResult ) { |
349 | 349 | if ( !self::checkHash( $comparefile, $comparehash ) ) { |
— | — | @@ -350,7 +350,7 @@ |
351 | 351 | return array(); |
352 | 352 | } |
353 | 353 | } |
354 | | - |
| 354 | + |
355 | 355 | // Get the array. |
356 | 356 | $compare_messages = self::parsePHP( $comparefilecontents, 'compare_messages' ); |
357 | 357 | |
— | — | @@ -378,69 +378,69 @@ |
379 | 379 | } elseif ( $saveResults ) { |
380 | 380 | self::myLog( "--{$langcode} hasn't changed--", $verbose ); |
381 | 381 | } |
382 | | - |
| 382 | + |
383 | 383 | self::saveHash( $basefile, $basehash ); |
384 | | - |
| 384 | + |
385 | 385 | self::saveHash( $comparefile, $comparehash ); |
386 | | - |
| 386 | + |
387 | 387 | return $changedStrings; |
388 | 388 | } |
389 | 389 | |
390 | 390 | /** |
391 | 391 | * Checks whether a messages file has a certain hash. |
392 | | - * |
| 392 | + * |
393 | 393 | * TODO: Swap return values, this is insane |
394 | | - * |
| 394 | + * |
395 | 395 | * @param $file string Filename |
396 | 396 | * @param $hash string Hash |
397 | | - * |
| 397 | + * |
398 | 398 | * @return bool True if $file does NOT have hash $hash, false if it does |
399 | 399 | */ |
400 | 400 | public static function checkHash( $file, $hash ) { |
401 | 401 | $hashes = self::readFile( 'hashes' ); |
402 | 402 | return @$hashes[$file] !== $hash; |
403 | 403 | } |
404 | | - |
| 404 | + |
405 | 405 | public static function saveHash( $file, $hash ) { |
406 | 406 | if ( is_null( self::$newHashes ) ) { |
407 | 407 | self::$newHashes = self::readFile( 'hashes' ); |
408 | 408 | } |
409 | | - |
| 409 | + |
410 | 410 | self::$newHashes[$file] = $hash; |
411 | 411 | } |
412 | | - |
| 412 | + |
413 | 413 | public static function writeHashes() { |
414 | 414 | self::writeFile( 'hashes', self::$newHashes ); |
415 | 415 | } |
416 | 416 | |
417 | 417 | /** |
418 | | - * |
419 | | - * |
| 418 | + * |
| 419 | + * |
420 | 420 | * @param $changedStrings Array |
421 | 421 | * @param $forbiddenKeys Array |
422 | 422 | * @param $compare_messages Array |
423 | 423 | * @param $base_messages Array |
424 | 424 | * @param $langcode String |
425 | 425 | * @param $verbose Boolean |
426 | | - * |
| 426 | + * |
427 | 427 | * @return Integer: the amount of updated messages |
428 | 428 | */ |
429 | 429 | public static function saveChanges( $changedStrings, array $forbiddenKeys, array $compare_messages, array $base_messages, $langcode, $verbose ) { |
430 | 430 | // Count the updates. |
431 | 431 | $updates = 0; |
432 | | - |
| 432 | + |
433 | 433 | if( !is_array( $changedStrings ) ) { |
434 | 434 | self::myLog("CRITICAL ERROR: \$changedStrings is not an array in file " . (__FILE__) . ' at line ' .( __LINE__ ) ); |
435 | 435 | return 0; |
436 | 436 | } |
437 | 437 | |
438 | 438 | $new_messages = self::readFile( $langcode ); |
439 | | - |
| 439 | + |
440 | 440 | foreach ( $changedStrings as $key => $value ) { |
441 | 441 | // If this message wasn't changed in English. |
442 | 442 | if ( !isset( $forbiddenKeys[$key] ) ) { |
443 | 443 | $new_messages[$key] = $base_messages[$key]; |
444 | | - |
| 444 | + |
445 | 445 | // Output extra logmessages when needed. |
446 | 446 | if ( $verbose ) { |
447 | 447 | $oldmsg = isset( $compare_messages[$key] ) ? "'{$compare_messages[$key]}'" : 'not set'; |
— | — | @@ -452,26 +452,26 @@ |
453 | 453 | } |
454 | 454 | } |
455 | 455 | self::writeFile( $langcode, $new_messages ); |
456 | | - |
| 456 | + |
457 | 457 | return $updates; |
458 | 458 | } |
459 | 459 | |
460 | 460 | /** |
461 | | - * |
| 461 | + * |
462 | 462 | * @param $extension String |
463 | 463 | * @param $basefile String |
464 | 464 | * @param $comparefile String |
465 | 465 | * @param $verbose Boolean |
466 | 466 | * @param $alwaysGetResult Boolean |
467 | 467 | * @param $saveResults Boolean |
468 | | - * |
| 468 | + * |
469 | 469 | * @return Integer: the amount of updated messages |
470 | 470 | */ |
471 | 471 | public static function compareExtensionFiles( $extension, $basefile, $comparefile, $verbose, $alwaysGetResult = true, $saveResults = false ) { |
472 | 472 | // FIXME: Factor out duplicated code? |
473 | 473 | |
474 | 474 | $basefilecontents = self::getFileContents( $basefile ); |
475 | | - |
| 475 | + |
476 | 476 | if ( $basefilecontents === false || $basefilecontents === '' ) { |
477 | 477 | return 0; // Failed |
478 | 478 | } |
— | — | @@ -482,7 +482,7 @@ |
483 | 483 | // Rename the arrays. |
484 | 484 | $basefilecontents = preg_replace( "/\\\$messages/", "\$base_messages", $basefilecontents ); |
485 | 485 | $basehash = md5( $basefilecontents ); |
486 | | - |
| 486 | + |
487 | 487 | // If this is the remote file |
488 | 488 | if ( preg_match( "/^http/", $basefile ) && !$alwaysGetResult ) { |
489 | 489 | // Check if the hash has changed |
— | — | @@ -516,8 +516,13 @@ |
517 | 517 | } |
518 | 518 | } |
519 | 519 | |
520 | | - // Get the real array. |
521 | | - $compare_messages = self::parsePHP( $comparefilecontents, 'compare_messages' ); |
| 520 | + try { |
| 521 | + // Get the real array. |
| 522 | + $compare_messages = self::parsePHP( $comparefilecontents, 'compare_messages' ); |
| 523 | + } catch (Exception $ex) { |
| 524 | + var_dump( $basefile, $comparefile ); |
| 525 | + die(); |
| 526 | + } |
522 | 527 | |
523 | 528 | // If both files are the same, they can be skipped. |
524 | 529 | if ( $basehash == $comparehash && !$alwaysGetResult ) { |
— | — | @@ -578,21 +583,21 @@ |
579 | 584 | } elseif($saveResults === true) { |
580 | 585 | self::myLog( "--{$language} hasn't changed--", $verbose ); |
581 | 586 | } |
582 | | - } |
| 587 | + } |
583 | 588 | |
584 | 589 | // And log some stuff. |
585 | 590 | self::myLog( "Updated " . $updates . " messages for the '{$extension}' extension", $verbose ); |
586 | 591 | |
587 | 592 | self::saveHash( $basefile, $basehash ); |
588 | | - |
| 593 | + |
589 | 594 | self::saveHash( $comparefile, $comparehash ); |
590 | | - |
| 595 | + |
591 | 596 | return $updates; |
592 | 597 | } |
593 | | - |
| 598 | + |
594 | 599 | /** |
595 | 600 | * Logs a message. |
596 | | - * |
| 601 | + * |
597 | 602 | * @param $log String |
598 | 603 | */ |
599 | 604 | public static function myLog( $log, $verbose = true ) { |
— | — | @@ -605,7 +610,7 @@ |
606 | 611 | print( $log . "\n" ); |
607 | 612 | } |
608 | 613 | } |
609 | | - |
| 614 | + |
610 | 615 | public static function parsePHP( $php, $varname ) { |
611 | 616 | try { |
612 | 617 | $reader = new QuickArrayReader("<?php $php"); |
— | — | @@ -615,32 +620,32 @@ |
616 | 621 | return false; |
617 | 622 | } |
618 | 623 | } |
619 | | - |
| 624 | + |
620 | 625 | public static function filename( $lang ) { |
621 | 626 | global $wgLocalisationUpdateDirectory, $wgCacheDirectory; |
622 | | - |
| 627 | + |
623 | 628 | $dir = $wgLocalisationUpdateDirectory ? |
624 | 629 | $wgLocalisationUpdateDirectory : |
625 | 630 | $wgCacheDirectory; |
626 | | - |
| 631 | + |
627 | 632 | if ( !$dir ) { |
628 | 633 | throw new MWException( 'No cache directory configured' ); |
629 | 634 | } |
630 | | - |
| 635 | + |
631 | 636 | return "$dir/l10nupdate-$lang.cache"; |
632 | 637 | } |
633 | | - |
| 638 | + |
634 | 639 | public static function readFile( $lang ) { |
635 | 640 | if ( !isset( self::$filecache[$lang] ) ) { |
636 | 641 | $file = self::filename( $lang ); |
637 | 642 | $contents = @file_get_contents( $file ); |
638 | | - |
| 643 | + |
639 | 644 | if ( $contents === false ) { |
640 | 645 | wfDebug( "Failed to read file '$file'\n" ); |
641 | 646 | $retval = array(); |
642 | 647 | } else { |
643 | 648 | $retval = unserialize( $contents ); |
644 | | - |
| 649 | + |
645 | 650 | if ( $retval === false ) { |
646 | 651 | wfDebug( "Corrupted data in file '$file'\n" ); |
647 | 652 | $retval = array(); |
— | — | @@ -648,18 +653,18 @@ |
649 | 654 | } |
650 | 655 | self::$filecache[$lang] = $retval; |
651 | 656 | } |
652 | | - |
| 657 | + |
653 | 658 | return self::$filecache[$lang]; |
654 | 659 | } |
655 | | - |
| 660 | + |
656 | 661 | public static function writeFile( $lang, $var ) { |
657 | 662 | $file = self::filename( $lang ); |
658 | | - |
| 663 | + |
659 | 664 | if ( !@file_put_contents( $file, serialize( $var ) ) ) { |
660 | 665 | throw new MWException( "Failed to write to file '$file'" ); |
661 | 666 | } |
662 | | - |
| 667 | + |
663 | 668 | self::$filecache[$lang] = $var; |
664 | 669 | } |
665 | | - |
666 | | -} |
\ No newline at end of file |
| 670 | + |
| 671 | +} |