Index: trunk/extensions/LocalisationUpdate/LocalisationUpdate.class.php |
— | — | @@ -1,45 +1,71 @@ |
2 | 2 | <?php |
3 | 3 | class LocalisationUpdate { |
| 4 | + |
4 | 5 | private static $newHashes = null; |
5 | 6 | private static $filecache = array(); |
6 | 7 | |
7 | | - public static function onRecache( $lc, $langcode, &$cache ) { |
8 | | - $cache['messages'] = array_merge( $cache['messages'], |
9 | | - self::readFile( $langcode ) ); |
| 8 | + /** |
| 9 | + * LocalisationCacheRecache hook handler. |
| 10 | + * |
| 11 | + * @param $lc LocalisationCache |
| 12 | + * @param $langcode String |
| 13 | + * @param $cache Array |
| 14 | + * |
| 15 | + * @return true |
| 16 | + */ |
| 17 | + public static function onRecache( LocalisationCache $lc, $langcode, array &$cache ) { |
| 18 | + $cache['messages'] = array_merge( |
| 19 | + $cache['messages'], |
| 20 | + self::readFile( $langcode ) |
| 21 | + ); |
| 22 | + |
10 | 23 | $cache['deps'][] = new FileDependency( |
11 | | - self::filename( $langcode ) ); |
| 24 | + self::filename( $langcode ) |
| 25 | + ); |
| 26 | + |
12 | 27 | return true; |
13 | 28 | } |
14 | 29 | |
15 | | - // Called from the cronjob to fetch new messages from SVN |
16 | | - public static function updateMessages( $options ) { |
| 30 | + /** |
| 31 | + * Called from the cronjob to fetch new messages from SVN. |
| 32 | + * |
| 33 | + * @param $options Array |
| 34 | + * |
| 35 | + * @return true |
| 36 | + */ |
| 37 | + public static function updateMessages( array $options ) { |
17 | 38 | global $wgLocalisationUpdateDirectory; |
18 | 39 | |
19 | 40 | $verbose = !isset( $options['quiet'] ); |
20 | 41 | $all = isset( $options['all'] ); |
21 | 42 | $skipCore = isset( $options['skip-core'] ); |
22 | 43 | $skipExtensions = isset( $options['skip-extensions'] ); |
| 44 | + |
23 | 45 | if( isset( $options['outdir'] ) ) { |
24 | 46 | $wgLocalisationUpdateDirectory = $options['outdir']; |
25 | 47 | } |
26 | 48 | |
27 | | - // Update all MW core messages |
| 49 | + $result = 0; |
| 50 | + |
| 51 | + // Update all MW core messages. |
28 | 52 | if( !$skipCore ) { |
29 | 53 | $result = self::updateMediawikiMessages( $verbose ); |
30 | 54 | } |
31 | 55 | |
32 | | - // Update all Extension messages |
| 56 | + // Update all Extension messages. |
33 | 57 | if( !$skipExtensions ) { |
34 | 58 | if( $all ) { |
35 | 59 | global $IP; |
36 | 60 | $extFiles = array(); |
37 | 61 | |
38 | 62 | // Look in extensions/ for all available items... |
| 63 | + // TODO: add support for $wgExtensionAssetsPath |
39 | 64 | $dirs = new RecursiveDirectoryIterator( "$IP/extensions/" ); |
40 | 65 | |
41 | 66 | // I ain't kidding... RecursiveIteratorIterator. |
42 | 67 | foreach( new RecursiveIteratorIterator( $dirs ) as $pathname => $item ) { |
43 | 68 | $filename = basename( $pathname ); |
| 69 | + |
44 | 70 | if( preg_match( '/^(.*)\.i18n\.php$/', $filename, $matches ) ) { |
45 | 71 | $group = $matches[1]; |
46 | 72 | $extFiles[$group] = $pathname; |
— | — | @@ -59,129 +85,167 @@ |
60 | 86 | // And output the result! |
61 | 87 | self::myLog( "Updated {$result} messages in total" ); |
62 | 88 | self::myLog( "Done" ); |
| 89 | + |
63 | 90 | return true; |
64 | 91 | } |
65 | 92 | |
66 | | - // Update Extension Messages |
| 93 | + /** |
| 94 | + * Update Extension Messages. |
| 95 | + * |
| 96 | + * @param $file String |
| 97 | + * @param $extension String |
| 98 | + * @param $verbose Boolean |
| 99 | + * |
| 100 | + * @return Integer: the amount of updated messages |
| 101 | + */ |
67 | 102 | public static function updateExtensionMessages( $file, $extension, $verbose ) { |
68 | 103 | global $IP, $wgLocalisationUpdateSVNURL; |
69 | 104 | |
70 | 105 | $relfile = wfRelativePath( $file, "$IP/extensions" ); |
71 | | - // Create a full path |
| 106 | + |
| 107 | + // Create a full path. |
| 108 | + // TODO: add support for $wgExtensionAssetsPath |
72 | 109 | $localfile = "$IP/extensions/$relfile"; |
73 | 110 | |
74 | | - // Get the full SVN directory path |
| 111 | + // Get the full SVN directory path. |
| 112 | + // TODO: add support for $wgExtensionAssetsPath |
75 | 113 | $svnfile = "$wgLocalisationUpdateSVNURL/extensions/$relfile"; |
76 | 114 | |
77 | | - // Compare the 2 files |
| 115 | + // Compare the 2 files. |
78 | 116 | $result = self::compareExtensionFiles( $extension, $svnfile, $file, $verbose, false, true ); |
| 117 | + |
79 | 118 | return $result; |
80 | 119 | } |
81 | 120 | |
82 | | - // Update the Mediawiki Core Messages |
| 121 | + /** |
| 122 | + * Update the Mediawiki Core Messages. |
| 123 | + * |
| 124 | + * @param $verbose Boolean |
| 125 | + * |
| 126 | + * @return Integer: the amount of updated messages |
| 127 | + */ |
83 | 128 | public static function updateMediawikiMessages( $verbose ) { |
84 | 129 | global $IP, $wgLocalisationUpdateSVNURL; |
85 | 130 | |
86 | | - // Create an array which will later contain all the files that we want to try to update |
| 131 | + // Create an array which will later contain all the files that we want to try to update. |
87 | 132 | $files = array(); |
88 | 133 | |
89 | | - // The directory which contains the files |
| 134 | + // The directory which contains the files. |
90 | 135 | $dirname = "languages/messages"; |
91 | 136 | |
92 | | - // Get the full path to the directory |
| 137 | + // Get the full path to the directory. |
93 | 138 | $localdir = $IP . "/" . $dirname; |
94 | 139 | |
95 | | - // Get the full SVN Path |
| 140 | + // Get the full SVN Path. |
96 | 141 | $svndir = "$wgLocalisationUpdateSVNURL/phase3/$dirname"; |
97 | 142 | |
98 | | - // Open the directory |
| 143 | + // Open the directory. |
99 | 144 | $dir = opendir( $localdir ); |
100 | 145 | while ( false !== ( $file = readdir( $dir ) ) ) { |
101 | 146 | $m = array(); |
102 | 147 | |
103 | 148 | // And save all the filenames of files containing messages |
104 | 149 | if ( preg_match( '/Messages([A-Z][a-z_]+)\.php$/', $file, $m ) ) { |
105 | | - if ( $m[1] != 'En' ) { // Except for the English one |
| 150 | + if ( $m[1] != 'En' ) { // Except for the English one. |
106 | 151 | $files[] = $file; |
107 | 152 | } |
108 | 153 | } |
109 | 154 | } |
110 | 155 | closedir( $dir ); |
111 | 156 | |
112 | | - // Find the changed English strings (as these messages won't be updated in ANY language) |
113 | | - $changedEnglishStrings = self::compareFiles( $localdir . "/MessagesEn.php", $svndir . "/MessagesEn.php", $verbose, true ); |
| 157 | + // Find the changed English strings (as these messages won't be updated in ANY language). |
| 158 | + $changedEnglishStrings = self::compareFiles( $localdir . '/MessagesEn.php', $svndir . '/MessagesEn.php', $verbose, true ); |
114 | 159 | |
115 | | - // Count the changes |
| 160 | + // Count the changes. |
116 | 161 | $changedCount = 0; |
117 | 162 | |
118 | | - // For each language |
119 | | - sort($files); |
| 163 | + // For each language. |
| 164 | + sort( $files ); |
120 | 165 | foreach ( $files as $file ) { |
121 | | - $svnfile = $svndir . "/" . $file; |
122 | | - $localfile = $localdir . "/" . $file; |
| 166 | + $svnfile = $svndir . '/' . $file; |
| 167 | + $localfile = $localdir . '/' . $file; |
123 | 168 | |
124 | | - // Compare the files |
| 169 | + // Compare the files. |
125 | 170 | $result = self::compareFiles( $svnfile, $localfile, $verbose, $changedEnglishStrings, false, true ); |
126 | 171 | |
127 | | - // And update the change counter |
| 172 | + // And update the change counter. |
128 | 173 | $changedCount += count( $result ); |
129 | 174 | } |
130 | 175 | |
131 | | - // Log some nice info |
| 176 | + // Log some nice info. |
132 | 177 | self::myLog( "{$changedCount} Mediawiki messages are updated" ); |
| 178 | + |
133 | 179 | return $changedCount; |
134 | 180 | } |
135 | 181 | |
136 | | - // Remove all unneeded content |
| 182 | + /** |
| 183 | + * Removes all unneeded content from a file and returns it. |
| 184 | + * |
| 185 | + * @param $contents String |
| 186 | + * |
| 187 | + * @return String |
| 188 | + */ |
137 | 189 | public static function cleanupFile( $contents ) { |
138 | | - // We don't need any PHP tags |
| 190 | + // We don't need any PHP tags. |
139 | 191 | $contents = strtr( $contents, |
140 | | - array( "<?php" => "", |
141 | | - "?" . ">" => "" |
142 | | - ) ); |
| 192 | + array( |
| 193 | + '<?php' => '', |
| 194 | + '?' . '>' => '' |
| 195 | + ) |
| 196 | + ); |
| 197 | + |
143 | 198 | $results = array(); |
144 | | - // And we only want the messages array |
| 199 | + |
| 200 | + // And we only want the messages array. |
145 | 201 | preg_match( "/\\\$messages(.*\s)*?\);/", $contents, $results ); |
146 | 202 | |
147 | 203 | // If there is any! |
148 | 204 | if ( !empty( $results[0] ) ) { |
149 | 205 | $contents = $results[0]; |
150 | 206 | } else { |
151 | | - $contents = ""; |
| 207 | + $contents = ''; |
152 | 208 | } |
153 | 209 | |
154 | | - // Windows vs Unix always stinks when comparing files |
| 210 | + // Windows vs Unix always stinks when comparing files. |
155 | 211 | $contents = preg_replace( "/\\r\\n?/", "\n", $contents ); |
156 | 212 | |
157 | | - // return the cleaned up file |
| 213 | + // Return the cleaned up file. |
158 | 214 | return $contents; |
159 | 215 | } |
160 | 216 | |
| 217 | + /** |
| 218 | + * |
| 219 | + * @param $basefile String |
| 220 | + */ |
161 | 221 | public static function getFileContents( $basefile ) { |
162 | 222 | global $wgLocalisationUpdateRetryAttempts; |
| 223 | + |
163 | 224 | $attempts = 0; |
164 | | - $basefilecontents = ""; |
165 | | - // use cURL to get the SVN contents |
| 225 | + $basefilecontents = ''; |
| 226 | + |
| 227 | + // Use cURL to get the SVN contents. |
166 | 228 | if ( preg_match( "/^http/", $basefile ) ) { |
167 | | - while( !$basefilecontents && $attempts <= $wgLocalisationUpdateRetryAttempts) { |
168 | | - if($attempts > 0) { |
| 229 | + while( !$basefilecontents && $attempts <= $wgLocalisationUpdateRetryAttempts ) { |
| 230 | + if( $attempts > 0 ) { |
169 | 231 | $delay = 1; |
170 | | - self::myLog( "Failed to download " . $basefile . "; retrying in ${delay}s..." ); |
| 232 | + self::myLog( 'Failed to download ' . $basefile . "; retrying in ${delay}s..." ); |
171 | 233 | sleep( $delay ); |
172 | 234 | } |
| 235 | + |
173 | 236 | $basefilecontents = Http::get( $basefile ); |
174 | 237 | $attempts++; |
175 | 238 | } |
176 | 239 | if ( !$basefilecontents ) { |
177 | | - self::myLog( "Cannot get the contents of " . $basefile . " (curl)" ); |
| 240 | + self::myLog( 'Cannot get the contents of ' . $basefile . ' (curl)' ); |
178 | 241 | return false; |
179 | 242 | } |
180 | 243 | } else {// otherwise try file_get_contents |
181 | 244 | if ( !( $basefilecontents = file_get_contents( $basefile ) ) ) { |
182 | | - self::myLog( "Cannot get the contents of " . $basefile ); |
| 245 | + self::myLog( 'Cannot get the contents of ' . $basefile ); |
183 | 246 | return false; |
184 | 247 | } |
185 | 248 | } |
| 249 | + |
186 | 250 | return $basefilecontents; |
187 | 251 | } |
188 | 252 | |
— | — | @@ -466,11 +530,15 @@ |
467 | 531 | |
468 | 532 | public static function filename( $lang ) { |
469 | 533 | global $wgLocalisationUpdateDirectory, $wgCacheDirectory; |
| 534 | + |
470 | 535 | $dir = $wgLocalisationUpdateDirectory ? |
471 | 536 | $wgLocalisationUpdateDirectory : |
472 | 537 | $wgCacheDirectory; |
473 | | - if ( !$dir ) |
| 538 | + |
| 539 | + if ( !$dir ) { |
474 | 540 | throw new MWException( 'No cache directory configured' ); |
| 541 | + } |
| 542 | + |
475 | 543 | return "$dir/l10nupdate-$lang.cache"; |
476 | 544 | } |
477 | 545 | |
— | — | @@ -478,11 +546,13 @@ |
479 | 547 | if ( !isset( self::$filecache[$lang] ) ) { |
480 | 548 | $file = self::filename( $lang ); |
481 | 549 | $contents = @file_get_contents( $file ); |
| 550 | + |
482 | 551 | if ( $contents === false ) { |
483 | 552 | wfDebug( "Failed to read file '$file'\n" ); |
484 | 553 | $retval = array(); |
485 | 554 | } else { |
486 | 555 | $retval = unserialize( $contents ); |
| 556 | + |
487 | 557 | if ( $retval === false ) { |
488 | 558 | wfDebug( "Corrupted data in file '$file'\n" ); |
489 | 559 | $retval = array(); |
— | — | @@ -490,13 +560,18 @@ |
491 | 561 | } |
492 | 562 | self::$filecache[$lang] = $retval; |
493 | 563 | } |
| 564 | + |
494 | 565 | return self::$filecache[$lang]; |
495 | 566 | } |
496 | 567 | |
497 | 568 | public static function writeFile( $lang, $var ) { |
498 | 569 | $file = self::filename( $lang ); |
499 | | - if ( !@file_put_contents( $file, serialize( $var ) ) ) |
| 570 | + |
| 571 | + if ( !@file_put_contents( $file, serialize( $var ) ) ) { |
500 | 572 | throw new MWException( "Failed to write to file '$file'" ); |
| 573 | + } |
| 574 | + |
501 | 575 | self::$filecache[$lang] = $var; |
502 | 576 | } |
503 | | -} |
| 577 | + |
| 578 | +} |
\ No newline at end of file |