Index: branches/wmf-deployment/extensions/LocalisationUpdate/tests/tokenTest.php |
— | — | @@ -0,0 +1,91 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +$IP = strval( getenv( 'MW_INSTALL_PATH' ) ) !== '' |
| 5 | + ? getenv( 'MW_INSTALL_PATH' ) |
| 6 | + : realpath( dirname( __FILE__ ) . "/../../../" ); |
| 7 | + |
| 8 | +require_once( "$IP/maintenance/commandLine.inc" ); |
| 9 | + |
| 10 | +function evalExtractArray( $php, $varname ) { |
| 11 | + eval( $php ); |
| 12 | + return @$$varname; |
| 13 | +} |
| 14 | + |
| 15 | +function confExtractArray( $php, $varname ) { |
| 16 | + try { |
| 17 | + $ce = new ConfEditor("<?php $php"); |
| 18 | + $vars = $ce->getVars(); |
| 19 | + $retval = @$vars[$varname]; |
| 20 | + } catch( Exception $e ) { |
| 21 | + print $e . "\n"; |
| 22 | + $retval = null; |
| 23 | + } |
| 24 | + return $retval; |
| 25 | +} |
| 26 | + |
| 27 | +function quickTokenExtractArray( $php, $varname ) { |
| 28 | + $reader = new QuickArrayReader("<?php $php"); |
| 29 | + return $reader->getVar( $varname ); |
| 30 | +} |
| 31 | + |
| 32 | + |
| 33 | +if( count( $args ) ) { |
| 34 | + $sources = $args; |
| 35 | +} else { |
| 36 | + $sources = |
| 37 | + array_merge( |
| 38 | + glob("$IP/extensions/*/*.i18n.php"), |
| 39 | + glob("$IP/languages/messages/Messages*.php") ); |
| 40 | +} |
| 41 | + |
| 42 | +foreach( $sources as $sourceFile ) { |
| 43 | + $rel = basename( $sourceFile ); |
| 44 | + $out = str_replace( '/', '-', $rel ); |
| 45 | + |
| 46 | + $sourceData = file_get_contents( $sourceFile ); |
| 47 | + |
| 48 | + if( preg_match( '!extensions/!', $sourceFile ) ) { |
| 49 | + $sourceData = LocalisationUpdate::cleanupExtensionFile( $sourceData ); |
| 50 | + $items = 'langs'; |
| 51 | + } else { |
| 52 | + $sourceData = LocalisationUpdate::cleanupFile( $sourceData ); |
| 53 | + $items = 'messages'; |
| 54 | + } |
| 55 | + |
| 56 | + file_put_contents( "$out.txt", $sourceData ); |
| 57 | + |
| 58 | + $start = microtime(true); |
| 59 | + $eval = evalExtractArray( $sourceData, 'messages' ); |
| 60 | + $deltaEval = microtime(true) - $start; |
| 61 | + |
| 62 | + $start = microtime(true); |
| 63 | + $quick = quickTokenExtractArray( $sourceData, 'messages' ); |
| 64 | + $deltaQuick = microtime(true) - $start; |
| 65 | + |
| 66 | + $start = microtime(true); |
| 67 | + $token = confExtractArray( $sourceData, 'messages' ); |
| 68 | + $deltaToken = microtime(true) - $start; |
| 69 | + |
| 70 | + $hashEval = md5(serialize($eval)); |
| 71 | + $hashToken = md5(serialize($token)); |
| 72 | + $hashQuick = md5(serialize($quick)); |
| 73 | + $countEval = count( (array)$eval); |
| 74 | + $countToken = count( (array)$token ); |
| 75 | + $countQuick = count( (array)$quick ); |
| 76 | + |
| 77 | + printf( "%s %s %d $items - %0.1fms - eval\n", $rel, $hashEval, $countEval, $deltaEval * 1000 ); |
| 78 | + printf( "%s %s %d $items - %0.1fms - QuickArrayReader\n", $rel, $hashQuick, $countQuick, $deltaQuick * 1000 ); |
| 79 | + printf( "%s %s %d $items - %0.1fms - ConfEditor\n", $rel, $hashToken, $countToken, $deltaToken * 1000 ); |
| 80 | + |
| 81 | + if( $hashEval !== $hashToken || $hashEval !== $hashQuick ) { |
| 82 | + echo "FAILED on $rel\n"; |
| 83 | + file_put_contents( "$out-eval.txt", var_export( $eval, true ) ); |
| 84 | + file_put_contents( "$out-token.txt", var_export( $token, true ) ); |
| 85 | + file_put_contents( "$out-quick.txt", var_export( $quick, true ) ); |
| 86 | + #die("check eval.txt and token.txt\n"); |
| 87 | + } |
| 88 | + echo "\n"; |
| 89 | +} |
| 90 | + |
| 91 | +echo "ok\n"; |
| 92 | + |
Property changes on: branches/wmf-deployment/extensions/LocalisationUpdate/tests/tokenTest.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 93 | + native |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/QuickArrayReader.php |
— | — | @@ -0,0 +1,172 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Quickie parser class that can happily read the subset of PHP we need |
| 6 | + * for our localization arrays safely. |
| 7 | + * |
| 8 | + * About an order of magnitude faster than ConfEditor(), but still an |
| 9 | + * order of magnitude slower than eval(). |
| 10 | + */ |
| 11 | +class QuickArrayReader { |
| 12 | + var $vars = array(); |
| 13 | + |
| 14 | + function __construct( $string ) { |
| 15 | + $scalarTypes = array( |
| 16 | + T_LNUMBER => true, |
| 17 | + T_DNUMBER => true, |
| 18 | + T_STRING => true, |
| 19 | + T_CONSTANT_ENCAPSED_STRING => true, |
| 20 | + ); |
| 21 | + $skipTypes = array( |
| 22 | + T_WHITESPACE => true, |
| 23 | + T_COMMENT => true, |
| 24 | + T_DOC_COMMENT => true, |
| 25 | + ); |
| 26 | + $tokens = token_get_all( $string ); |
| 27 | + $count = count( $tokens ); |
| 28 | + for( $i = 0; $i < $count; ) { |
| 29 | + while( isset($skipTypes[$tokens[$i][0]] ) ) { |
| 30 | + $i++; |
| 31 | + } |
| 32 | + switch( $tokens[$i][0] ) { |
| 33 | + case T_OPEN_TAG: |
| 34 | + $i++; |
| 35 | + continue; |
| 36 | + case T_VARIABLE: |
| 37 | + // '$messages' -> 'messages' |
| 38 | + $varname = trim( substr( $tokens[$i][1], 1 ) ); |
| 39 | + $varindex = null; |
| 40 | + |
| 41 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 42 | + |
| 43 | + if( $tokens[$i] === '[' ) { |
| 44 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 45 | + |
| 46 | + if( isset($scalarTypes[$tokens[$i][0]] ) ) { |
| 47 | + $varindex = $this->parseScalar( $tokens[$i] ); |
| 48 | + } else { |
| 49 | + throw $this->except( $tokens[$i], 'scalar index' ); |
| 50 | + } |
| 51 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 52 | + |
| 53 | + if( $tokens[$i] !== ']' ) { |
| 54 | + throw $this->except( $tokens[$i], ']' ); |
| 55 | + } |
| 56 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 57 | + } |
| 58 | + |
| 59 | + if( $tokens[$i] !== '=' ) { |
| 60 | + throw $this->except( $tokens[$i], '=' ); |
| 61 | + } |
| 62 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 63 | + |
| 64 | + if( isset($scalarTypes[$tokens[$i][0]] ) ) { |
| 65 | + $buildval = $this->parseScalar( $tokens[$i] ); |
| 66 | + } elseif( $tokens[$i][0] === T_ARRAY ) { |
| 67 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 68 | + if( $tokens[$i] !== '(' ) { |
| 69 | + throw $this->except( $tokens[$i], '(' ); |
| 70 | + } |
| 71 | + $buildval = array(); |
| 72 | + do { |
| 73 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 74 | + |
| 75 | + if( $tokens[$i] === ')' ) { |
| 76 | + break; |
| 77 | + } |
| 78 | + if( isset($scalarTypes[$tokens[$i][0]] ) ) { |
| 79 | + $key = $this->parseScalar( $tokens[$i] ); |
| 80 | + } |
| 81 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 82 | + |
| 83 | + if( $tokens[$i][0] !== T_DOUBLE_ARROW ) { |
| 84 | + throw $this->except( $tokens[$i], '=>' ); |
| 85 | + } |
| 86 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 87 | + |
| 88 | + if( isset($scalarTypes[$tokens[$i][0]] ) ) { |
| 89 | + $val = $this->parseScalar( $tokens[$i] ); |
| 90 | + } |
| 91 | + @$buildval[$key] = $val; |
| 92 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 93 | + |
| 94 | + if( $tokens[$i] === ',' ) { |
| 95 | + continue; |
| 96 | + } elseif( $tokens[$i] === ')' ) { |
| 97 | + break; |
| 98 | + } else { |
| 99 | + throw $this->except( $tokens[$i], ', or )' ); |
| 100 | + } |
| 101 | + } while(true); |
| 102 | + } else { |
| 103 | + throw $this->except( $tokens[$i], 'scalar or array' ); |
| 104 | + } |
| 105 | + if( is_null( $varindex ) ) { |
| 106 | + $this->vars[$varname] = $buildval; |
| 107 | + } else { |
| 108 | + @$this->vars[$varname][$varindex] = $buildval; |
| 109 | + } |
| 110 | + while( isset($skipTypes[$tokens[++$i][0]] ) ); |
| 111 | + if( $tokens[$i] !== ';' ) { |
| 112 | + throw $this->except($tokens[$i], ';'); |
| 113 | + } |
| 114 | + $i++; |
| 115 | + break; |
| 116 | + default: |
| 117 | + throw $this->except($tokens[$i], 'open tag, whitespace, or variable.'); |
| 118 | + } |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + private function except( $got, $expected ) { |
| 123 | + if( is_array( $got ) ) { |
| 124 | + $got = token_name( $got[0] ) . " ('" . $got[1] . "')"; |
| 125 | + } else { |
| 126 | + $got = "'" . $got . "'"; |
| 127 | + } |
| 128 | + return new Exception( "Expected $expected, got $got" ); |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * Parse a scalar value in PHP |
| 133 | + * @return mixed Parsed value |
| 134 | + */ |
| 135 | + function parseScalar( $token ) { |
| 136 | + if( is_array( $token ) ) { |
| 137 | + $str = $token[1]; |
| 138 | + } else { |
| 139 | + $str = $token; |
| 140 | + } |
| 141 | + if ( $str !== '' && $str[0] == '\'' ) |
| 142 | + // Single-quoted string |
| 143 | + // @fixme trim() call is due to mystery bug where whitespace gets |
| 144 | + // appended to the token; without it we ended up reading in the |
| 145 | + // extra quote on the end! |
| 146 | + return strtr( substr( trim( $str ), 1, -1 ), |
| 147 | + array( '\\\'' => '\'', '\\\\' => '\\' ) ); |
| 148 | + if ( $str !== '' && @$str[0] == '"' ) |
| 149 | + // Double-quoted string |
| 150 | + // @fixme trim() call is due to mystery bug where whitespace gets |
| 151 | + // appended to the token; without it we ended up reading in the |
| 152 | + // extra quote on the end! |
| 153 | + return stripcslashes( substr( trim( $str ), 1, -1 ) ); |
| 154 | + if ( substr( $str, 0, 4 ) === 'true' ) |
| 155 | + return true; |
| 156 | + if ( substr( $str, 0, 5 ) === 'false' ) |
| 157 | + return false; |
| 158 | + if ( substr( $str, 0, 4 ) === 'null' ) |
| 159 | + return null; |
| 160 | + // Must be some kind of numeric value, so let PHP's weak typing |
| 161 | + // be useful for a change |
| 162 | + return $str; |
| 163 | + } |
| 164 | + |
| 165 | + function getVar( $varname ) { |
| 166 | + if( isset( $this->vars[$varname] ) ) { |
| 167 | + return $this->vars[$varname]; |
| 168 | + } else { |
| 169 | + return null; |
| 170 | + } |
| 171 | + } |
| 172 | +} |
| 173 | + |
Property changes on: branches/wmf-deployment/extensions/LocalisationUpdate/QuickArrayReader.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 174 | + native |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/KNOWN_ISSUES.txt |
— | — | @@ -1,2 +1,11 @@ |
2 | 2 | - Only works with SVN revision 50605 or later of the |
3 | 3 | MediaWiki core |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +Key issues at the moment: |
| 8 | +* Seems to want to store a copy of the localization updates in each local database. |
| 9 | +We've got hundreds of wikis run from the same installation set; we don't want to multiply our effort by 1000. |
| 10 | + |
| 11 | +* It doesn't seem to be using available memcached stuff; unsure yet whether this is taken care of |
| 12 | +by the general message caching or if we're going to end up making extra hits we don't need. |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/patch-lfh_timestamp.sql |
— | — | @@ -0,0 +1,4 @@ |
| 2 | +-- Patch that adds lfh_timestamp field and index |
| 3 | + |
| 4 | +ALTER TABLE /*_*/localisation_file_hash ADD lfh_timestamp varchar(14) NOT NULL; |
| 5 | +CREATE INDEX /*i*/lfh_timestamp ON /*_*/localisation_file_hash (lfh_timestamp); |
Property changes on: branches/wmf-deployment/extensions/LocalisationUpdate/patch-lfh_timestamp.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 6 | + native |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/LocalisationUpdate.i18n.php |
— | — | @@ -5,7 +5,7 @@ |
6 | 6 | * @file |
7 | 7 | * @ingroup Extensions |
8 | 8 | */ |
9 | | - |
| 9 | + |
10 | 10 | $messages = array(); |
11 | 11 | |
12 | 12 | /** English |
— | — | @@ -31,6 +31,13 @@ |
32 | 32 | 'localisationupdate-desc' => 'يبقي الرسائل المترجمة محدثة كأفضل ما يكون', |
33 | 33 | ); |
34 | 34 | |
| 35 | +/** Bavarian (Boarisch) |
| 36 | + * @author Man77 |
| 37 | + */ |
| 38 | +$messages['bar'] = array( |
| 39 | + 'localisationupdate-desc' => "Lokalisiade Texte und Nåchrichtn so aktuell håidn wia's gråd gehd", |
| 40 | +); |
| 41 | + |
35 | 42 | /** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца)) |
36 | 43 | * @author EugeneZelenko |
37 | 44 | */ |
— | — | @@ -45,6 +52,13 @@ |
46 | 53 | 'localisationupdate-desc' => 'Zadržavanje lokaliziranih poruka ažurnim koliko je god moguće', |
47 | 54 | ); |
48 | 55 | |
| 56 | +/** Catalan (Català) |
| 57 | + * @author Paucabot |
| 58 | + */ |
| 59 | +$messages['ca'] = array( |
| 60 | + 'localisationupdate-desc' => 'Manté els missatges localitzats tan actualitzats com sigui possible', |
| 61 | +); |
| 62 | + |
49 | 63 | /** German (Deutsch) |
50 | 64 | * @author Purodha |
51 | 65 | */ |
— | — | @@ -59,6 +73,20 @@ |
60 | 74 | 'localisationupdate-desc' => 'Źaržy lokalizěrowane powěźeńki tak aktualne ako móžno', |
61 | 75 | ); |
62 | 76 | |
| 77 | +/** Spanish (Español) |
| 78 | + * @author Crazymadlover |
| 79 | + */ |
| 80 | +$messages['es'] = array( |
| 81 | + 'localisationupdate-desc' => 'Mantener los mensajes localizados tan actualizados como sean posibles', |
| 82 | +); |
| 83 | + |
| 84 | +/** Finnish (Suomi) |
| 85 | + * @author Nike |
| 86 | + */ |
| 87 | +$messages['fi'] = array( |
| 88 | + 'localisationupdate-desc' => 'Pitää käännetyt viestit niin ajantasaisina kuin mahdollista', |
| 89 | +); |
| 90 | + |
63 | 91 | /** French (Français) |
64 | 92 | * @author Crochet.david |
65 | 93 | */ |
— | — | @@ -94,6 +122,13 @@ |
95 | 123 | 'localisationupdate-desc' => 'Dźerži lokalizowane zdźělenki tak aktualne kaž móžno', |
96 | 124 | ); |
97 | 125 | |
| 126 | +/** Hungarian (Magyar) |
| 127 | + * @author Glanthor Reviol |
| 128 | + */ |
| 129 | +$messages['hu'] = array( |
| 130 | + 'localisationupdate-desc' => 'Frissíti a lefordított üzeneteket', |
| 131 | +); |
| 132 | + |
98 | 133 | /** Interlingua (Interlingua) |
99 | 134 | * @author McDutchie |
100 | 135 | */ |
— | — | @@ -101,6 +136,20 @@ |
102 | 137 | 'localisationupdate-desc' => 'Mantene le messages localisate tanto actual como possibile', |
103 | 138 | ); |
104 | 139 | |
| 140 | +/** Indonesian (Bahasa Indonesia) |
| 141 | + * @author Bennylin |
| 142 | + */ |
| 143 | +$messages['id'] = array( |
| 144 | + 'localisationupdate-desc' => 'Mengusahakan agar pesan-pesan yang telah diterjemahkan tetap semutakhir mungkin', |
| 145 | +); |
| 146 | + |
| 147 | +/** Italian (Italiano) |
| 148 | + * @author Darth Kule |
| 149 | + */ |
| 150 | +$messages['it'] = array( |
| 151 | + 'localisationupdate-desc' => 'Mantiene i messaggi localizzati quanto più aggiornati è possibile', |
| 152 | +); |
| 153 | + |
105 | 154 | /** Japanese (日本語) |
106 | 155 | * @author Fryed-peach |
107 | 156 | */ |
— | — | @@ -122,6 +171,13 @@ |
123 | 172 | 'localisationupdate-desc' => 'hält déi lokaliséiert Messagen esou aktuell wéi méiglech.', |
124 | 173 | ); |
125 | 174 | |
| 175 | +/** Macedonian (Македонски) |
| 176 | + * @author Bjankuloski06 |
| 177 | + */ |
| 178 | +$messages['mk'] = array( |
| 179 | + 'localisationupdate-desc' => 'Ги одржува локализираните пораки колку што е можно пообновени и повеќе во тек со настаните', |
| 180 | +); |
| 181 | + |
126 | 182 | /** Dutch (Nederlands) |
127 | 183 | * @author Siebrand |
128 | 184 | */ |
— | — | @@ -129,6 +185,13 @@ |
130 | 186 | 'localisationupdate-desc' => 'Houdt de gelokaliseerde berichten zo actueel mogelijk', |
131 | 187 | ); |
132 | 188 | |
| 189 | +/** Norwegian Nynorsk (Norsk (nynorsk)) |
| 190 | + * @author Gunnernett |
| 191 | + */ |
| 192 | +$messages['nn'] = array( |
| 193 | + 'localisationupdate-desc' => 'Held dei lokaliserte meldingane så oppdaterte som mogleg', |
| 194 | +); |
| 195 | + |
133 | 196 | /** Norwegian (bokmål) (Norsk (bokmål)) |
134 | 197 | * @author Nghtwlkr |
135 | 198 | */ |
— | — | @@ -150,6 +213,34 @@ |
151 | 214 | 'localisationupdate-desc' => 'Uaktualnia lokalne komunikaty w miarę możliwości na bieżąco', |
152 | 215 | ); |
153 | 216 | |
| 217 | +/** Piedmontese (Piemontèis) |
| 218 | + * @author Dragonòt |
| 219 | + */ |
| 220 | +$messages['pms'] = array( |
| 221 | + 'localisationupdate-desc' => 'A manten i messagi localisà ël pì agiornà possìbil', |
| 222 | +); |
| 223 | + |
| 224 | +/** Portuguese (Português) |
| 225 | + * @author Malafaya |
| 226 | + */ |
| 227 | +$messages['pt'] = array( |
| 228 | + 'localisationupdate-desc' => 'Mantém as mensagens localizadas tão atualizadas quanto possível', |
| 229 | +); |
| 230 | + |
| 231 | +/** Brazilian Portuguese (Português do Brasil) |
| 232 | + * @author Eduardo.mps |
| 233 | + */ |
| 234 | +$messages['pt-br'] = array( |
| 235 | + 'localisationupdate-desc' => 'Mantém as mensagens localizadas tão atualizadas quanto possível', |
| 236 | +); |
| 237 | + |
| 238 | +/** Romanian (Română) |
| 239 | + * @author KlaudiuMihaila |
| 240 | + */ |
| 241 | +$messages['ro'] = array( |
| 242 | + 'localisationupdate-desc' => 'Menţine mesajele localizate cât mai actualizate', |
| 243 | +); |
| 244 | + |
154 | 245 | /** Tarandíne (Tarandíne) |
155 | 246 | * @author Joetaras |
156 | 247 | */ |
— | — | @@ -157,6 +248,13 @@ |
158 | 249 | 'localisationupdate-desc' => "Mandine le messagge localizzate 'u cchiù aggiornate possibbile", |
159 | 250 | ); |
160 | 251 | |
| 252 | +/** Russian (Русский) |
| 253 | + * @author Александр Сигачёв |
| 254 | + */ |
| 255 | +$messages['ru'] = array( |
| 256 | + 'localisationupdate-desc' => 'Поддерживает актуальность локализованных сообщений, насколько это возможно', |
| 257 | +); |
| 258 | + |
161 | 259 | /** Slovak (Slovenčina) |
162 | 260 | * @author Helix84 |
163 | 261 | */ |
— | — | @@ -164,6 +262,13 @@ |
165 | 263 | 'localisationupdate-desc' => 'Udržiava lokalizované správy čo najaktuálnejšie', |
166 | 264 | ); |
167 | 265 | |
| 266 | +/** Vietnamese (Tiếng Việt) |
| 267 | + * @author Vinhtantran |
| 268 | + */ |
| 269 | +$messages['vi'] = array( |
| 270 | + 'localisationupdate-desc' => 'Giữ các thông điệp bản địa hóa được cập nhật nhất có thể', |
| 271 | +); |
| 272 | + |
168 | 273 | /** Yue (粵語) |
169 | 274 | * @author Tom Maaswinkel |
170 | 275 | */ |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/update.php |
— | — | @@ -6,25 +6,30 @@ |
7 | 7 | |
8 | 8 | require_once( "$IP/maintenance/commandLine.inc" ); |
9 | 9 | |
10 | | -$verbose = false; |
| 10 | +if( isset( $options['help'] ) ) { |
| 11 | + print "Fetches updated localisation files from MediaWiki development SVN\n"; |
| 12 | + print "and saves into local database to merge with release defaults.\n"; |
| 13 | + print "\n"; |
| 14 | + print "Usage: php extensions/LocalisationUpdate/update.php\n"; |
| 15 | + print "Options:\n"; |
| 16 | + print " --quiet Suppress progress output\n"; |
| 17 | + print " --all Fetch all present extensions, not just those enabled\n"; |
| 18 | + print "\n"; |
| 19 | + exit( 0 ); |
| 20 | +} |
11 | 21 | |
12 | | -if ( $argc > 1 && $argv[0] == "verbose" ) |
13 | | - $verbose = true; |
14 | 22 | |
15 | | -$mtime = microtime(); |
16 | | -$mtime = explode( " ", $mtime ); |
17 | | -$mtime = $mtime[1] + $mtime[0]; |
18 | | -$starttime = $mtime; |
| 23 | +$verbose = !isset( $options['quiet'] ); |
| 24 | +$all = isset( $options['all'] ); |
19 | 25 | |
| 26 | +$starttime = microtime( true ); |
| 27 | + |
20 | 28 | // Prevent the script from timing out |
21 | 29 | set_time_limit( 0 ); |
22 | 30 | ini_set( "max_execution_time", 0 ); |
23 | 31 | |
24 | | -LocalisationUpdate::updateMessages( $verbose ); |
| 32 | +LocalisationUpdate::updateMessages( $verbose, $all ); |
25 | 33 | |
26 | | -$mtime = microtime(); |
27 | | -$mtime = explode( " ", $mtime ); |
28 | | -$mtime = $mtime[1] + $mtime[0]; |
29 | | -$endtime = $mtime; |
| 34 | +$endtime = microtime( true ); |
30 | 35 | $totaltime = ( $endtime - $starttime ); |
31 | 36 | print "All done in " . $totaltime . " seconds\n"; |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/LocalisationUpdate.php |
— | — | @@ -7,7 +7,18 @@ |
8 | 8 | |
9 | 9 | // Configuration |
10 | 10 | |
11 | | -$wgLocalisationUpdateSVNURL = "svn.wikimedia.org/svnroot/mediawiki/"; |
| 11 | +/** |
| 12 | + * This should point to either an HTTP-accessible Subversion repository containing |
| 13 | + * MediaWiki's 'phase3' and 'extensions' directory, *or* a local directory containing |
| 14 | + * checkouts of them: |
| 15 | + * |
| 16 | + * cd /path/to/mediawiki-trunk |
| 17 | + * svn co http://svn.wikimedia.org/svnroot/mediawiki/trunk/phase3 |
| 18 | + * svn co http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions |
| 19 | + * $wgLocalisationUpdateSVNURL = '/path/to/mediawiki-trunk'; |
| 20 | + */ |
| 21 | +$wgLocalisationUpdateSVNURL = "http://svn.wikimedia.org/svnroot/mediawiki/trunk"; |
| 22 | + |
12 | 23 | $wgLocalisationUpdateRetryAttempts = 5; |
13 | 24 | |
14 | 25 | // Info about me! |
— | — | @@ -22,9 +33,13 @@ |
23 | 34 | ); |
24 | 35 | |
25 | 36 | // Use the right hook |
26 | | -$wgHooks['MessageNotInMwNs'][] = "LocalisationUpdate::FindUpdatedMessage"; |
| 37 | +$wgHooks['LocalisationCacheRecache'][] = 'LocalisationUpdate::onRecache'; // MW 1.16+ |
27 | 38 | |
28 | 39 | $dir = dirname( __FILE__ ) . '/'; |
29 | 40 | $wgExtensionMessagesFiles['LocalisationUpdate'] = $dir . 'LocalisationUpdate.i18n.php'; |
30 | 41 | $wgAutoloadClasses['LocalisationUpdate'] = $dir . 'LocalisationUpdate.class.php'; |
| 42 | +$wgAutoloadClasses['LUDependency'] = $dir . 'LocalisationUpdate.class.php'; |
| 43 | +$wgAutoloadClasses['QuickArrayReader'] = $dir . 'QuickArrayReader.php'; |
| 44 | + |
31 | 45 | $wgHooks['LoadExtensionSchemaUpdates'][] = 'LocalisationUpdate::schemaUpdates'; |
| 46 | + |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/LocalisationUpdate.class.php |
— | — | @@ -1,44 +1,44 @@ |
2 | 2 | <?php |
3 | 3 | class LocalisationUpdate { |
4 | 4 | // DB Search funtion |
5 | | - public static function FindUpdatedMessage( &$message, $lckey, $langcode, $isFullKey ) { |
6 | | - // Define a cache |
7 | | - static $cache = array(); |
8 | | - $db = wfGetDB ( DB_SLAVE ); |
| 5 | + public static function onRecache( $lc, $langcode, &$cache ) { |
| 6 | + $dbr = wfGetDB ( DB_SLAVE ); |
9 | 7 | |
10 | | - // If the key also contains the language code remove the language code from the key |
11 | | - if ( $isFullKey ) { |
12 | | - $lckey = preg_replace( "/\/" . $langcode . "/", "", $lckey ); |
13 | | - } |
| 8 | + // Get the messages from the database |
| 9 | + $res = $dbr->select( 'localisation', |
| 10 | + array( 'lo_key', 'lo_value' ), |
| 11 | + array( 'lo_language' => $langcode ), |
| 12 | + __METHOD__ ); |
14 | 13 | |
15 | | - // If message is in the cache, don't get an update! |
16 | | - if ( array_key_exists( $lckey . "/" . $langcode, $cache ) ) { |
17 | | - $message = $cache[$lckey . "/" . $langcode]; |
18 | | - return true; |
| 14 | + foreach ( $res as $row ) { |
| 15 | + $cache['messages'][$row->lo_key] = $row->lo_value; |
19 | 16 | } |
20 | | - |
21 | | - // Get the message from the database |
22 | | - $conds = array( 'lo_key' => $lckey, 'lo_language' => $langcode ); |
23 | | - $result = $db->selectField( 'localisation', 'lo_value', $conds, __METHOD__ ); // Check if the database has any updated message |
24 | | - if ( $result === false ) { // If no results found, exit here |
25 | | - return true; |
26 | | - } |
27 | | - |
28 | | - $message = $result; |
29 | | - $cache[$lckey . "/" . $langcode] = $result; // Update the cache |
| 17 | + $cache['deps'][] = new LUDependency; |
30 | 18 | return true; |
31 | 19 | } |
32 | 20 | |
33 | 21 | // Called from the cronjob to fetch new messages from SVN |
34 | | - public static function updateMessages( $verbose = false ) { |
35 | | - // Need this later |
36 | | - global $wgExtensionMessagesFiles; |
37 | | - |
| 22 | + public static function updateMessages( $verbose = false, $all = false ) { |
38 | 23 | // Update all MW core messages |
39 | 24 | $result = self::updateMediawikiMessages( $verbose ); |
40 | 25 | |
41 | 26 | // Update all Extension messages |
42 | | - foreach ( $wgExtensionMessagesFiles as $extension => $locFile ) { |
| 27 | + if( $all ) { |
| 28 | + global $IP; |
| 29 | + $extFiles = array(); |
| 30 | + $messageFiles = glob( "$IP/extensions/*/*.i18n.php" ); |
| 31 | + foreach( $messageFiles as $pathname ) { |
| 32 | + $filename = basename( $pathname ); |
| 33 | + if( preg_match( '/^(.*)\.i18n\.php$/', $filename, $matches ) ) { |
| 34 | + $group = $matches[1]; |
| 35 | + $extFiles[$group] = $pathname; |
| 36 | + } |
| 37 | + } |
| 38 | + } else { |
| 39 | + global $wgExtensionMessagesFiles; |
| 40 | + $extFiles = $wgExtensionMessagesFiles; |
| 41 | + } |
| 42 | + foreach ( $extFiles as $extension => $locFile ) { |
43 | 43 | $result += self::updateExtensionMessages( $locFile, $extension, $verbose ); |
44 | 44 | } |
45 | 45 | |
— | — | @@ -51,18 +51,21 @@ |
52 | 52 | // Update Extension Messages |
53 | 53 | public static function updateExtensionMessages( $file, $extension, $verbose ) { |
54 | 54 | global $IP, $wgLocalisationUpdateSVNURL; |
55 | | - |
56 | | - // Find the right SVN folder |
57 | | - $svnFolder = SpecialVersion::getSvnRevision( dirname( $file ), false, false, true ); |
58 | | - |
| 55 | + |
| 56 | + $relfile = wfRelativePath( $file, "$IP/extensions" ); |
| 57 | + if( substr( $relfile, 0, 2 ) == ".." ) { |
| 58 | + self::myLog( "Skipping $file; not in $IP/extensions\n" ); |
| 59 | + return false; |
| 60 | + } |
| 61 | + |
59 | 62 | // Create a full path |
60 | | - $localfile = $IP . "/" . $file; |
| 63 | + $localfile = "$IP/extensions/$relfile"; |
61 | 64 | |
62 | 65 | // Get the full SVN directory path |
63 | | - $svndir = "http://" . $wgLocalisationUpdateSVNURL . $svnFolder; |
| 66 | + $svnfile = "$wgLocalisationUpdateSVNURL/extensions/$relfile"; |
64 | 67 | |
65 | 68 | // Compare the 2 files |
66 | | - $result = self::compareExtensionFiles( $extension, $svndir . "/" . basename( $file ), $file, $verbose, false, true ); |
| 69 | + $result = self::compareExtensionFiles( $extension, $svnfile, $file, $verbose, false, true ); |
67 | 70 | return $result; |
68 | 71 | } |
69 | 72 | |
— | — | @@ -77,22 +80,13 @@ |
78 | 81 | $dirname = "languages/messages"; |
79 | 82 | |
80 | 83 | // Get the full path to the directory |
81 | | - $dirname = $IP . "/" . $dirname; |
| 84 | + $localdir = $IP . "/" . $dirname; |
82 | 85 | |
83 | | - // Get the SVN folder used for the checkout |
84 | | - $svnFolder = SpecialVersion::getSvnRevision( $dirname, false, false, true ); |
85 | | - |
86 | | - // Do not update if not from SVN |
87 | | - if ( empty( $svnFolder ) ) { |
88 | | - self::myLog( 'Cannot update localisation as the files are not retrieved from SVN' ); |
89 | | - return 0; |
90 | | - } |
91 | | - |
92 | 86 | // Get the full SVN Path |
93 | | - $svndir = "http://" . $wgLocalisationUpdateSVNURL . $svnFolder; |
| 87 | + $svndir = "$wgLocalisationUpdateSVNURL/phase3/$dirname"; |
94 | 88 | |
95 | 89 | // Open the directory |
96 | | - $dir = opendir( $dirname ); |
| 90 | + $dir = opendir( $localdir ); |
97 | 91 | while ( false !== ( $file = readdir( $dir ) ) ) { |
98 | 92 | $m = array(); |
99 | 93 | |
— | — | @@ -106,7 +100,7 @@ |
107 | 101 | closedir( $dir ); |
108 | 102 | |
109 | 103 | // Find the changed English strings (as these messages won't be updated in ANY language) |
110 | | - $changedEnglishStrings = self::compareFiles( $dirname . "/MessagesEn.php", $svndir . "/MessagesEn.php", $verbose ); |
| 104 | + $changedEnglishStrings = self::compareFiles( $localdir . "/MessagesEn.php", $svndir . "/MessagesEn.php", $verbose, true ); |
111 | 105 | |
112 | 106 | // Count the changes |
113 | 107 | $changedCount = 0; |
— | — | @@ -115,7 +109,7 @@ |
116 | 110 | sort($files); |
117 | 111 | foreach ( $files as $file ) { |
118 | 112 | $svnfile = $svndir . "/" . $file; |
119 | | - $localfile = $dirname . "/" . $file; |
| 113 | + $localfile = $localdir . "/" . $file; |
120 | 114 | |
121 | 115 | // Compare the files |
122 | 116 | $result = self::compareFiles( $svnfile, $localfile, $verbose, $changedEnglishStrings, false, true ); |
— | — | @@ -133,7 +127,7 @@ |
134 | 128 | public static function cleanupFile( $contents ) { |
135 | 129 | // We don't need any PHP tags |
136 | 130 | $contents = preg_replace( "/<\\?php/", "", $contents ); |
137 | | - $contents = preg_replace( "/\?>/", "", $contents ); |
| 131 | + $contents = preg_replace( "/\?" . ">/", "", $contents ); |
138 | 132 | $results = array(); |
139 | 133 | // And we only want the messages array |
140 | 134 | preg_match( "/\\\$messages(.*\s)*?\);/", $contents, $results ); |
— | — | @@ -159,8 +153,11 @@ |
160 | 154 | // use cURL to get the SVN contents |
161 | 155 | if ( preg_match( "/^http/", $basefile ) ) { |
162 | 156 | while( !$basefilecontents && $attempts <= $wgLocalisationUpdateRetryAttempts) { |
163 | | - if($attempts > 0) |
164 | | - sleep(1); |
| 157 | + if($attempts > 0) { |
| 158 | + $delay = 1; |
| 159 | + self::myLog( "Failed to download " . $basefile . "; retrying in ${delay}s..." ); |
| 160 | + sleep( $delay ); |
| 161 | + } |
165 | 162 | $basefilecontents = Http::get( $basefile ); |
166 | 163 | $attempts++; |
167 | 164 | } |
— | — | @@ -199,8 +196,8 @@ |
200 | 197 | $basefilecontents = preg_replace( "/\\\$messages/", "\$base_messages", $basefilecontents ); |
201 | 198 | |
202 | 199 | $basehash = md5( $basefilecontents ); |
203 | | - // If this is the remote file check if the file has changed since our last update |
204 | | - if ( preg_match( "/^http/", $basefile ) && !$alwaysGetResult ) { |
| 200 | + // Check if the file has changed since our last update |
| 201 | + if ( !$alwaysGetResult ) { |
205 | 202 | if ( !self::checkHash( $basefile, $basehash ) ) { |
206 | 203 | self::myLog( "Skipping {$langcode} since the remote file hasn't changed since our last update" ); |
207 | 204 | return array(); |
— | — | @@ -208,9 +205,7 @@ |
209 | 206 | } |
210 | 207 | |
211 | 208 | // Get the array with messages |
212 | | - $fileEditor = new ConfEditor( $basefilecontents ); |
213 | | - $vars = $fileEditor->getVars(); |
214 | | - $base_messages = $vars['base_messages']; |
| 209 | + $base_messages = self::parsePHP( $basefilecontents, 'base_messages' ); |
215 | 210 | |
216 | 211 | $comparefilecontents = self::getFileContents( $comparefile ); |
217 | 212 | if ( $comparefilecontents === false || $comparefilecontents === "" ) return array(); // Failed |
— | — | @@ -230,9 +225,7 @@ |
231 | 226 | } |
232 | 227 | } |
233 | 228 | // Get the array |
234 | | - $fileEditor = new ConfEditor( $comparefilecontents ); |
235 | | - $vars = $fileEditor->getVars(); |
236 | | - $compare_messages = $vars['compare_messages']; |
| 229 | + $compare_messages = self::parsePHP( $comparefilecontents, 'compare_messages' ); |
237 | 230 | |
238 | 231 | // if the localfile and the remote file are the same, skip them! |
239 | 232 | if ( $basehash == $comparehash && !$alwaysGetResult ) { |
— | — | @@ -252,27 +245,30 @@ |
253 | 246 | $changedStrings = array_diff_assoc( $base_messages, $compare_messages ); |
254 | 247 | |
255 | 248 | // If we want to save the differences |
256 | | - if ( $saveResults === true && !empty($changedStrings) && is_array($changedStrings)) { |
| 249 | + if ( $saveResults && !empty($changedStrings) && is_array($changedStrings)) { |
257 | 250 | self::myLog( "--Checking languagecode {$langcode}--" ); |
258 | 251 | // The save them |
259 | | - $updates = self::saveChanges( $changedStrings, $forbiddenKeys, $base_messages, $langcode, $verbose ); |
| 252 | + $updates = self::saveChanges( $changedStrings, $forbiddenKeys, $compare_messages, $base_messages, $langcode, $verbose ); |
260 | 253 | self::myLog( "{$updates} messages updated for {$langcode}." ); |
261 | | - } elseif($saveResults === true) { |
| 254 | + } elseif ( $saveResults ) { |
262 | 255 | self::myLog( "--{$langcode} hasn't changed--" ); |
263 | 256 | } |
264 | 257 | |
265 | 258 | |
266 | | - if ( preg_match( "/^http/", $basefile )) { |
267 | | - self::saveHash( $basefile, $basehash ); |
268 | | - } |
| 259 | + self::saveHash( $basefile, $basehash ); |
269 | 260 | |
270 | | - if ( preg_match( "/^http/", $comparefile )) { |
271 | | - self::saveHash( $comparefile, $comparehash ); |
272 | | - } |
| 261 | + self::saveHash( $comparefile, $comparehash ); |
273 | 262 | |
274 | 263 | return $changedStrings; |
275 | 264 | } |
276 | 265 | |
| 266 | + /** |
| 267 | + * Checks whether a messages file has a certain hash |
| 268 | + * TODO: Swap return values, this is insane |
| 269 | + * @param $file string Filename |
| 270 | + * @param $hash string Hash |
| 271 | + * @return bool True if $file does NOT have hash $hash, false if it does |
| 272 | + */ |
277 | 273 | public static function checkHash( $file, $hash ) { |
278 | 274 | $db = wfGetDB( DB_MASTER ); |
279 | 275 | |
— | — | @@ -287,13 +283,18 @@ |
288 | 284 | |
289 | 285 | public static function saveHash ($file, $hash) { |
290 | 286 | $db = wfGetDB ( DB_MASTER ); |
291 | | - $hashConds = array( 'lfh_file' => $file, 'lfh_hash' => $hash ); |
292 | | - $conds = array( 'lfh_file' => $file ); |
293 | | - $db->delete( 'localisation_file_hash', $conds , __METHOD__ ); |
294 | | - $db->insert( 'localisation_file_hash', $hashConds, __METHOD__ ); |
| 287 | + // Double query sucks but we wanna make sure we don't update |
| 288 | + // the timestamp when the hash hasn't changed |
| 289 | + if ( self::checkHash( $file, $hash ) ) |
| 290 | + $db->replace( 'localisation_file_hash', array( 'lfh_file' ), array( |
| 291 | + 'lfh_file' => $file, |
| 292 | + 'lfh_hash' => $hash, |
| 293 | + 'lfh_timestamp' => $db->timestamp( wfTimestamp() ) |
| 294 | + ), __METHOD__ |
| 295 | + ); |
295 | 296 | } |
296 | 297 | |
297 | | - public static function saveChanges( $changedStrings, $forbiddenKeys, $base_messages, $langcode, $verbose ) { |
| 298 | + public static function saveChanges( $changedStrings, $forbiddenKeys, $compare_messages, $base_messages, $langcode, $verbose ) { |
298 | 299 | // Gonna write to the DB again |
299 | 300 | $db = wfGetDB ( DB_MASTER ); |
300 | 301 | |
— | — | @@ -305,8 +306,8 @@ |
306 | 307 | } |
307 | 308 | |
308 | 309 | foreach ( $changedStrings as $key => $value ) { |
309 | | - // If this message wasn't changed in English |
310 | | - if ( !array_key_exists( $key , $forbiddenKeys ) ) { |
| 310 | + // If this message wasn't changed in English, and is in fact set |
| 311 | + if ( !array_key_exists( $key , $forbiddenKeys ) && isset( $compare_messages[$key] ) ) { |
311 | 312 | // See if we can update the database |
312 | 313 | |
313 | 314 | $values = array( |
— | — | @@ -320,7 +321,7 @@ |
321 | 322 | |
322 | 323 | // Output extra logmessages when needed |
323 | 324 | if ( $verbose ) { |
324 | | - self::myLog( "Updated message {$key} from {$compare_messages[$key]} to {$base_messages[$key]}" ); |
| 325 | + self::myLog( "Updated message {$key} from '{$compare_messages[$key]}' to '{$base_messages[$key]}'" ); |
325 | 326 | } |
326 | 327 | |
327 | 328 | // Update the counter |
— | — | @@ -333,7 +334,7 @@ |
334 | 335 | public static function cleanupExtensionFile( $contents ) { |
335 | 336 | // We don't want PHP tags |
336 | 337 | $contents = preg_replace( "/<\?php/", "", $contents ); |
337 | | - $contents = preg_replace( "/\?>/", "", $contents ); |
| 338 | + $contents = preg_replace( "/\?" . ">/", "", $contents ); |
338 | 339 | $results = array(); |
339 | 340 | // And we only want message arrays |
340 | 341 | preg_match_all( "/\\\$messages(.*\s)*?\);/", $contents, $results ); |
— | — | @@ -377,10 +378,8 @@ |
378 | 379 | } |
379 | 380 | |
380 | 381 | // And get the real contents |
381 | | - $fileEditor = new ConfEditor( $basefilecontents ); |
382 | | - $vars = $fileEditor->getVars(); |
383 | | - $base_messages = $vars['base_messages']; |
384 | | - |
| 382 | + $base_messages = self::parsePHP( $basefilecontents, 'base_messages' ); |
| 383 | + |
385 | 384 | $comparefilecontents = self::getFileContents( $comparefile ); |
386 | 385 | if ( $comparefilecontents === false || $comparefilecontents === "" ) return 0; // Failed |
387 | 386 | |
— | — | @@ -398,9 +397,7 @@ |
399 | 398 | } |
400 | 399 | } |
401 | 400 | // Get the real array |
402 | | - $fileEditor = new ConfEditor( $comparefilecontents ); |
403 | | - $vars = $fileEditor->getVars(); |
404 | | - $compare_messages = $vars['compare_messages']; |
| 401 | + $compare_messages = self::parsePHP( $comparefilecontents, 'compare_messages' ); |
405 | 402 | |
406 | 403 | // If both files are the same, they can be skipped |
407 | 404 | if ( $basehash == $comparehash && !$alwaysGetResult ) { |
— | — | @@ -456,7 +453,7 @@ |
457 | 454 | if ( $saveResults === true && !empty($changedStrings) && is_array($changedStrings)) { |
458 | 455 | self::myLog( "--Checking languagecode {$language}--" ); |
459 | 456 | // The save them |
460 | | - $updates = self::saveChanges( $changedStrings, $forbiddenKeys, $messages, $language, $verbose ); |
| 457 | + $updates = self::saveChanges( $changedStrings, $forbiddenKeys, $compare_messages, $messages, $language, $verbose ); |
461 | 458 | self::myLog( "{$updates} messages updated for {$language}." ); |
462 | 459 | } elseif($saveResults === true) { |
463 | 460 | self::myLog( "--{$language} hasn't changed--" ); |
— | — | @@ -466,21 +463,18 @@ |
467 | 464 | // And log some stuff |
468 | 465 | self::myLog( "Updated " . $updates . " messages for the '{$extension}' extension" ); |
469 | 466 | |
470 | | - if ( preg_match( "/^http/", $basefile )) { |
471 | | - self::saveHash( $basefile, $basehash ); |
472 | | - } |
| 467 | + self::saveHash( $basefile, $basehash ); |
473 | 468 | |
474 | | - if ( preg_match( "/^http/", $comparefile )) { |
475 | | - self::saveHash( $comparefile, $comparehash ); |
476 | | - } |
| 469 | + self::saveHash( $comparefile, $comparehash ); |
477 | 470 | |
478 | 471 | return $updates; |
479 | 472 | } |
480 | 473 | |
481 | 474 | public static function schemaUpdates() { |
482 | | - global $wgExtNewTables; |
| 475 | + global $wgExtNewTables, $wgExtNewFields; |
483 | 476 | $dir = dirname( __FILE__ ); |
484 | 477 | $wgExtNewTables[] = array( 'localisation', "$dir/schema.sql" ); |
| 478 | + $wgExtNewFields[] = array( 'localisation_file_hash', 'lfh_timestamp', "$dir/patch-lfh_timestamp.sql" ); |
485 | 479 | return true; |
486 | 480 | } |
487 | 481 | |
— | — | @@ -491,5 +485,39 @@ |
492 | 486 | print( $log . "\n" ); |
493 | 487 | } |
494 | 488 | } |
| 489 | + |
| 490 | + public static function parsePHP( $php, $varname ) { |
| 491 | + try { |
| 492 | + $reader = new QuickArrayReader("<?php $php"); |
| 493 | + return $reader->getVar( $varname ); |
| 494 | + } catch( Exception $e ) { |
| 495 | + self::myLog( "Failed to read file: " . $e ); |
| 496 | + return false; |
| 497 | + } |
| 498 | + } |
| 499 | +} |
495 | 500 | |
496 | | -} |
\ No newline at end of file |
| 501 | +class LUDependency extends CacheDependency { |
| 502 | + var $timestamp; |
| 503 | + |
| 504 | + function isExpired() { |
| 505 | + $timestamp = $this->getTimestamp(); |
| 506 | + return $timestamp !== $this->timestamp; |
| 507 | + } |
| 508 | + |
| 509 | + function loadDependencyValues() { |
| 510 | + $this->timestamp = $this->getTimestamp(); |
| 511 | + } |
| 512 | + |
| 513 | + function getTimestamp() { |
| 514 | + $dbr = wfGetDB( DB_SLAVE ); |
| 515 | + return $dbr->selectField( |
| 516 | + 'localisation_file_hash', 'MAX(lfh_timestamp)', '', |
| 517 | + __METHOD__ ); |
| 518 | + } |
| 519 | + |
| 520 | + function __sleep() { |
| 521 | + $this->loadDependencyValues(); |
| 522 | + return array( 'timestamp' ); |
| 523 | + } |
| 524 | +} |
Index: branches/wmf-deployment/extensions/LocalisationUpdate/schema.sql |
— | — | @@ -9,10 +9,13 @@ |
10 | 10 | |
11 | 11 | CREATE TABLE /*$wgDBprefix*/localisation_file_hash ( |
12 | 12 | lfh_file varchar(250) NOT NULL, |
13 | | - lfh_hash varchar(50) NOT NULL |
| 13 | + lfh_hash varchar(50) NOT NULL, |
| 14 | + lfh_timestamp varchar(14) NOT NULL |
14 | 15 | ) /*$wgDBTableOptions*/; |
15 | 16 | |
16 | 17 | CREATE UNIQUE INDEX /*i*/lfh_file ON |
17 | 18 | /*$wgDBprefix*/localisation_file_hash (lfh_file); |
18 | 19 | CREATE INDEX /*i*/lfh_file_hash ON |
19 | | - /*$wgDBprefix*/localisation_file_hash (lfh_file, lfh_hash); |
\ No newline at end of file |
| 20 | + /*$wgDBprefix*/localisation_file_hash (lfh_file, lfh_hash); |
| 21 | +CREATE INDEX /*i*/lfh_timestamp ON |
| 22 | + /*$wgDBprefix*/localisation_file_hash (lfh_timestamp); |
\ No newline at end of file |
Property changes on: branches/wmf-deployment/extensions/LocalisationUpdate |
___________________________________________________________________ |
Name: svn:mergeinfo |
20 | 23 | + /branches/REL1_15/phase3/extensions/LocalisationUpdate:51646 |
/trunk/extensions/LocalisationUpdate:52089-55252 |
/trunk/phase3/LocalisationUpdate:52859,53272 |
/trunk/phase3/extensions/LocalisationUpdate:52290,52402,52404,52718,52737,52759,52776,52791,52800,52808,52812-52813,52815-52819,52822,52846,52850,52852-52853,52855-52857,52859,52924,52986,53128-53129,53190,53197,53199,53203-53204,53210-53211,53247,53249,53252,53267,53270,53293,53305,53344,53369,53427,53502-53504,53506,53777,54384,54494,54592,54599-54602,54604,54613,54764,54793,54806,55178 |