Index: trunk/extensions/ParserFunctions/convertTests.txt |
— | — | @@ -0,0 +1,193 @@ |
| 2 | +!! test |
| 3 | +Simple conversion |
| 4 | +!! input |
| 5 | +{{#convert: 10 m | km }} |
| 6 | +!!result |
| 7 | +<p>0.01 kilometres |
| 8 | +</p> |
| 9 | +!! end |
| 10 | + |
| 11 | +!! test |
| 12 | +Position and formatting of numbers and units |
| 13 | +!! input |
| 14 | +*{{#convert: 10 m | km }} |
| 15 | +*{{#convert: 10m | km }} |
| 16 | +*{{#convert: 10 km | m }} |
| 17 | +*{{#convert: 10-km | m }} |
| 18 | +*{{#convert: 10E2 km | m }} |
| 19 | +*{{#convert: 10E-2 km | m }} |
| 20 | +*{{#convert: 10.0E2 km | m }} |
| 21 | +*{{#convert: 10.0E2.5 km | m }} |
| 22 | +!! result |
| 23 | +<ul><li>0.01 kilometres |
| 24 | +</li><li>0.01 kilometres |
| 25 | +</li><li>10,000 metres |
| 26 | +</li><li>10,000- metres |
| 27 | +</li><li>1,000,000 metres |
| 28 | +</li><li>100 metres |
| 29 | +</li><li>1,000,000 metres |
| 30 | +</li><li>1,000,000.5,000 metres |
| 31 | +</li></ul> |
| 32 | + |
| 33 | +!! end |
| 34 | + |
| 35 | +!! test |
| 36 | +Precision 1 |
| 37 | +!! input |
| 38 | +*{{#convert: 10 m | km }} |
| 39 | +*{{#convert: 11 m | km }} |
| 40 | +*{{#convert: 12 m | km }} |
| 41 | +*{{#convert: 13 m | km }} |
| 42 | +*{{#convert: 14 m | km }} |
| 43 | +*{{#convert: 15 m | km }} |
| 44 | +*{{#convert: 16 m | km }} |
| 45 | +*{{#convert: 17 m | km }} |
| 46 | +*{{#convert: 18 m | km }} |
| 47 | +*{{#convert: 19 m | km }} |
| 48 | +*{{#convert: 20 m | km }} |
| 49 | +!! result |
| 50 | +<ul><li>0.01 kilometres |
| 51 | +</li><li>0.011 kilometres |
| 52 | +</li><li>0.012 kilometres |
| 53 | +</li><li>0.013 kilometres |
| 54 | +</li><li>0.014 kilometres |
| 55 | +</li><li>0.015 kilometres |
| 56 | +</li><li>0.016 kilometres |
| 57 | +</li><li>0.017 kilometres |
| 58 | +</li><li>0.018 kilometres |
| 59 | +</li><li>0.019 kilometres |
| 60 | +</li><li>0.02 kilometres |
| 61 | +</li></ul> |
| 62 | + |
| 63 | +!! end |
| 64 | + |
| 65 | +!! test |
| 66 | +Precision 2 |
| 67 | +!! input |
| 68 | +*{{#convert: 10.0 m | km }} |
| 69 | +*{{#convert: 10.1 m | km }} |
| 70 | +*{{#convert: 10.2 m | km }} |
| 71 | +*{{#convert: 10.3 m | km }} |
| 72 | +*{{#convert: 10.4 m | km }} |
| 73 | +*{{#convert: 10.5 m | km }} |
| 74 | +*{{#convert: 10.6 m | km }} |
| 75 | +*{{#convert: 10.7 m | km }} |
| 76 | +!! result |
| 77 | +<ul><li>0.0100 kilometres |
| 78 | +</li><li>0.0101 kilometres |
| 79 | +</li><li>0.0102 kilometres |
| 80 | +</li><li>0.0103 kilometres |
| 81 | +</li><li>0.0104 kilometres |
| 82 | +</li><li>0.0105 kilometres |
| 83 | +</li><li>0.0106 kilometres |
| 84 | +</li><li>0.0107 kilometres |
| 85 | +</li></ul> |
| 86 | + |
| 87 | +!! end |
| 88 | + |
| 89 | +!! test |
| 90 | +String interpolation |
| 91 | +!! input |
| 92 | +{{#convert: 25, 26, 27, 28, 29, and 30 km }} |
| 93 | +!! result |
| 94 | +<p>25,000, 26,000, 27,000, 28,000, 29,000, and 30,000 metres |
| 95 | +</p> |
| 96 | +!! end |
| 97 | + |
| 98 | +!! test |
| 99 | +Precision 3 |
| 100 | +!! input |
| 101 | +{{#convert: 25, 26, 27, 28, 29, and 30 miles }} |
| 102 | +!! result |
| 103 | +<p>40,000, 42,000, 43,000, 45,000, 47,000, and 50,000 metres |
| 104 | +</p> |
| 105 | +!! end |
| 106 | + |
| 107 | +!! test |
| 108 | +Precision 4 |
| 109 | +!! input |
| 110 | +{{#convert:35000, 35E3, 35.0E3, 350E2, 3.500E4, 35000E0, 350000E-1 m | km }} |
| 111 | +!! result |
| 112 | +<p>35, 35, 35.0, 35, 35.00, 35, 35 kilometres |
| 113 | +</p> |
| 114 | +!! end |
| 115 | + |
| 116 | +!! test |
| 117 | +#sourceunit |
| 118 | +!!input |
| 119 | +*{{#convert: 25 | #sourceunit = km }} |
| 120 | +*{{#convert: 25 | #sourceunit=km }} |
| 121 | +*{{#convert: 25 | #sourceunit = km | #sourceunit = mm }} |
| 122 | +*{{#convert: 25 | #sourceunit = km | cm }} |
| 123 | +!! result |
| 124 | +<ul><li>25,000 metres |
| 125 | +</li><li>25,000 metres |
| 126 | +</li><li>0.025 metres |
| 127 | +</li><li>2,500,000 centimetres |
| 128 | +</li></ul> |
| 129 | + |
| 130 | +!! end |
| 131 | + |
| 132 | +!! test |
| 133 | +Precision overrides |
| 134 | +!!input |
| 135 | +*{{#convert: 1 mi | #dp = 0 }} |
| 136 | +*{{#convert: 1 mi | #dp=1 }} |
| 137 | +*{{#convert: 1 mi | #dp = -2 }} |
| 138 | +*{{#convert: 1 mi | #dp = 5 }} |
| 139 | +*{{#convert: 1 mi | #dp = -8 }} |
| 140 | +*{{#convert: 1 mi | #sf = 0 }} |
| 141 | +*{{#convert: 1 mi | #sf=1 }} |
| 142 | +*{{#convert: 1 mi | #sf = 3 }} |
| 143 | +*{{#convert: 1 mi | #sf = 5 }} |
| 144 | +*{{#convert: 1 mi | #sf = -8 }} |
| 145 | +!! result |
| 146 | +<ul><li>1,609 metres |
| 147 | +</li><li>1,609.3 metres |
| 148 | +</li><li>1,600 metres |
| 149 | +</li><li>1,609.344 metres |
| 150 | +</li><li>0 metres |
| 151 | +</li><li>2,000 metres |
| 152 | +</li><li>2,000 metres |
| 153 | +</li><li>1,610 metres |
| 154 | +</li><li>1,609.3 metres |
| 155 | +</li><li>2,000 metres |
| 156 | +</li></ul> |
| 157 | + |
| 158 | +!! end |
| 159 | + |
| 160 | + |
| 161 | +!! test |
| 162 | +Errors |
| 163 | +!! input |
| 164 | +*{{#convert: 25 | km }} |
| 165 | +*{{#convert: 25 foobars | mi }} |
| 166 | +*{{#convert: 25 mi | #sourceunit = foobar }} |
| 167 | +*{{#convert: 25 km | s }} |
| 168 | +*{{#convert: 25 km/Pa | m/Pa }} |
| 169 | +*{{#convert: 25 km/s/l }} |
| 170 | +*{{#convert: 25 km/m3 }} |
| 171 | +!! result |
| 172 | +<ul><li><strong class="error">Error: no source unit given</strong> |
| 173 | +</li><li><strong class="error">Error: unknown unit "foobars"</strong> |
| 174 | +</li><li><strong class="error">Error: unknown unit "foobar"</strong> |
| 175 | +</li><li><strong class="error">Error: cannot convert between units of "length" and "time"</strong> |
| 176 | +</li><li><strong class="error">Error: invalid compound unit "length/pressure"</strong> |
| 177 | +</li><li><strong class="error">Error: cannot parse double compound units like "km/s/l"</strong> |
| 178 | +</li><li><strong class="error">Error: invalid compound unit "length/volume"</strong> |
| 179 | +</li></ul> |
| 180 | + |
| 181 | +!! end |
| 182 | + |
| 183 | + |
| 184 | +!! test |
| 185 | +#sourceunit = #targetunit |
| 186 | +!! input |
| 187 | +*{{#convert: 25 km | #targetunit = #sourceunit }} |
| 188 | +*{{#convert: 25 km | #sourceunit = #targetunit }} |
| 189 | +!! result |
| 190 | +<ul><li>25 kilometres |
| 191 | +</li><li>25 kilometres |
| 192 | +</li></ul> |
| 193 | + |
| 194 | +!! end |
Property changes on: trunk/extensions/ParserFunctions/convertTests.txt |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 195 | + native |
Index: trunk/extensions/ParserFunctions/Convert.php |
— | — | @@ -0,0 +1,735 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 5 | + die( 'This file is a MediaWiki extension, it is not a valid entry point' ); |
| 6 | +} |
| 7 | + |
| 8 | +class ConvertError extends Exception { |
| 9 | + public function __construct( $msg /*...*/ ) { |
| 10 | + $args = func_get_args(); |
| 11 | + array_shift( $args ); |
| 12 | + $this->message = '<strong class="error">' . wfMsgExt( "pfunc-convert-$msg", 'parseinline', $args ) . '</strong>'; |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +class ConvertParser { |
| 17 | + |
| 18 | + # A regex which matches the body of the string and the source unit separately |
| 19 | + const UNITS_REGEX = '/^(.+?)\s*([a-z]+\^?\d?(?:\/\w+\^?\d?)*)$/i'; |
| 20 | + |
| 21 | + # A regex which matches a number |
| 22 | + const NUM_REGEX = '/\b((?:\+|\-|−|\x2212)?(\d+(?:\.\d+)?)(?:E(?:\+|\-|−|\x2212)?\d+)?)\b/i'; |
| 23 | + |
| 24 | + # ConvertUnit objects |
| 25 | + protected $sourceUnit; |
| 26 | + protected $targetUnit; |
| 27 | + |
| 28 | + # Whether to abbreviate the output unit |
| 29 | + protected $abbreviate; |
| 30 | + |
| 31 | + # Whether to link the output unit, if possible |
| 32 | + protected $link; |
| 33 | + |
| 34 | + # If set, don't output the unit or format the number |
| 35 | + protected $raw; |
| 36 | + |
| 37 | + # What precision to round to. |
| 38 | + protected $decimalPlaces; |
| 39 | + protected $significantFigures; |
| 40 | + |
| 41 | + # The last value converted, which will be used for PLURAL evaluation |
| 42 | + protected $lastValue; |
| 43 | + |
| 44 | + public function clearState(){ |
| 45 | + # Make sure we break any references set up in the parameter passing below |
| 46 | + unset( $this->sourceUnit ); |
| 47 | + unset( $this->targetUnit ); |
| 48 | + $this->sourceUnit = null; |
| 49 | + $this->targetUnit = null; |
| 50 | + |
| 51 | + $this->lastValue |
| 52 | + = $this->link |
| 53 | + = $this->precision |
| 54 | + = $this->abbreviate |
| 55 | + = $this->raw |
| 56 | + = $this->significantFigures |
| 57 | + = $this->decimalPlaces |
| 58 | + = null; |
| 59 | + } |
| 60 | + |
| 61 | + /** |
| 62 | + * Evaluate a convert expression |
| 63 | + * @param $args Array of the parameters passed to the original tag function |
| 64 | + * @return String |
| 65 | + * @throws ConvertError |
| 66 | + */ |
| 67 | + public function execute( $args ) { |
| 68 | + $this->clearState(); |
| 69 | + array_shift( $args ); # Dump Parser object |
| 70 | + |
| 71 | + if( count( $args ) == 0 ){ |
| 72 | + # that was easy |
| 73 | + return ''; |
| 74 | + } |
| 75 | + $string = trim( array_shift( $args ) ); |
| 76 | + |
| 77 | + # Process the rest of the args |
| 78 | + $sourceUnit =& MagicWord::get( 'sourceunit' ); |
| 79 | + $targetUnit =& MagicWord::get( 'targetunit' ); |
| 80 | + $linkUnit =& MagicWord::get( 'linkunit' ); |
| 81 | + $dp =& MagicWord::get( 'decimalplaces' ); |
| 82 | + $sf =& MagicWord::get( 'significantfigures' ); |
| 83 | + $abbr =& MagicWord::get( 'abbreviate' ); |
| 84 | + $raw =& MagicWord::get( 'rawsuffix' ); |
| 85 | + |
| 86 | + $n = 0; # Count of unnamed parameters |
| 87 | + foreach ( $args as $arg ) { |
| 88 | + $parts = array_map( 'trim', explode( '=', $arg, 2 ) ); |
| 89 | + if ( count( $parts ) == 2 ) { |
| 90 | + # Found "=" |
| 91 | + if ( $sourceUnit->matchStartAndRemove( $parts[0] ) ) { |
| 92 | + if( $targetUnit->matchStartAndRemove( $parts[1] ) ){ |
| 93 | + $this->targetUnit =& $this->sourceUnit; |
| 94 | + } else { |
| 95 | + $this->sourceUnit = new ConvertUnit( $parts[1] ); |
| 96 | + } |
| 97 | + |
| 98 | + } elseif ( $targetUnit->matchStartAndRemove( $parts[0] ) ) { |
| 99 | + if( $sourceUnit->matchStartAndRemove( $parts[1] ) ){ |
| 100 | + $this->targetUnit =& $this->sourceUnit; |
| 101 | + } else { |
| 102 | + $this->targetUnit = new ConvertUnit( $parts[1] ); |
| 103 | + } |
| 104 | + |
| 105 | + } elseif( $dp->matchStartAndRemove( $parts[0] ) ) { |
| 106 | + $this->decimalPlaces = intval( $parts[1] ); |
| 107 | + |
| 108 | + } elseif( $sf->matchStartAndRemove( $parts[0] ) ) { |
| 109 | + # It doesn't make any sense to have negative sig-figs |
| 110 | + if( intval( $parts[1] ) > 0 ){ |
| 111 | + $this->significantFigures = intval( $parts[1] ); |
| 112 | + } |
| 113 | + } |
| 114 | + } elseif( $linkUnit->matchStartAndRemove( $parts[0] ) ) { |
| 115 | + $this->link = true; |
| 116 | + } elseif( $abbr->matchStartAndRemove( $parts[0] ) ) { |
| 117 | + $this->abbreviate = true; |
| 118 | + } elseif( $raw->matchStartAndRemove( $parts[0] ) ) { |
| 119 | + $this->raw = true; |
| 120 | + } elseif( $parts[0] != '' && !$n++ && !$this->targetUnit instanceof ConvertUnit ){ |
| 121 | + # First unnamed parameter = output unit |
| 122 | + $this->targetUnit = new ConvertUnit( $parts[0] ); |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + # Get the source unit, if not already set. This throws ConvertError on failure |
| 127 | + if ( !$this->sourceUnit instanceof ConvertUnit ){ |
| 128 | + $this->deduceSourceUnit( $string ); |
| 129 | + } |
| 130 | + |
| 131 | + # Use the default unit (SI usually) |
| 132 | + if( !$this->targetUnit instanceof ConvertUnit ){ |
| 133 | + $this->targetUnit = $this->sourceUnit->getDefaultUnit(); |
| 134 | + } |
| 135 | + |
| 136 | + if( $this->targetUnit->dimension->value != $this->sourceUnit->dimension->value ){ |
| 137 | + throw new ConvertError( |
| 138 | + 'dimensionmismatch', |
| 139 | + $this->sourceUnit->dimension->getName(true), |
| 140 | + $this->targetUnit->dimension->getName(true) |
| 141 | + ); |
| 142 | + } |
| 143 | + |
| 144 | + return $this->processString( $string ); |
| 145 | + } |
| 146 | + |
| 147 | + protected function deduceSourceUnit( $string ){ |
| 148 | + # Get the unit from the end of the string |
| 149 | + $matches = array(); |
| 150 | + preg_match( self::UNITS_REGEX, $string, $matches ); |
| 151 | + |
| 152 | + if( count( $matches ) == 3 ){ |
| 153 | + $this->sourceUnit = new ConvertUnit( $matches[2] ); |
| 154 | + } else { |
| 155 | + throw new ConvertError( 'nounit' ); |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + /** |
| 160 | + * Identify the values to be converted, and convert them |
| 161 | + * @param $string String |
| 162 | + */ |
| 163 | + protected function processString( $string ){ |
| 164 | + # Replace values |
| 165 | + $string = preg_replace_callback( |
| 166 | + self::NUM_REGEX, |
| 167 | + array( $this, 'convert' ), |
| 168 | + trim( preg_replace( self::UNITS_REGEX, '$1', $string ) ) |
| 169 | + ); |
| 170 | + if( $this->raw ){ |
| 171 | + return $string; |
| 172 | + } else { |
| 173 | + $unit = $this->targetUnit->getText( |
| 174 | + $this->lastValue, |
| 175 | + $this->link, |
| 176 | + $this->abbreviate |
| 177 | + ); |
| 178 | + return "$string $unit"; |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + /** |
| 183 | + * Express a value in the $sourceUnit in terms of the $targetUnit, preserving |
| 184 | + * an appropriate degree of accuracy. |
| 185 | + * @param $value String |
| 186 | + * @return void |
| 187 | + */ |
| 188 | + public function convert( $value ){ |
| 189 | + global $wgContLang; |
| 190 | + $valueFloat = floatval( $value[1] ); |
| 191 | + $newValue = $valueFloat |
| 192 | + * $this->sourceUnit->getConversion() |
| 193 | + / $this->targetUnit->getConversion(); |
| 194 | + if( $this->decimalPlaces !== null && $this->significantFigures !== null ){ |
| 195 | + # round to the required number of decimal places, or the required number |
| 196 | + # of significant figures, whichever is the least precise |
| 197 | + $dp = floor( $this->significantFigures - log10( abs( $newValue ) ) ); # Convert SF to DP |
| 198 | + $newValue = round( $newValue, max( $dp, $this->decimalPlaces ) ); |
| 199 | + |
| 200 | + } elseif( $this->decimalPlaces !== null ){ |
| 201 | + $newValue = round( $newValue, $this->decimalPlaces ); |
| 202 | + |
| 203 | + } elseif( $this->significantFigures !== null ){ |
| 204 | + $dp = floor( $this->significantFigures - log10( abs( $newValue ) ) ); # Convert SF to DP |
| 205 | + $newValue = round( $newValue, $dp ); |
| 206 | + |
| 207 | + } else { |
| 208 | + # Need to round to a similar accuracy as the original value. To do that we |
| 209 | + # select the accuracy which will as closely as possible preserve the maximum |
| 210 | + # percentage error in the value. So 36ft = 36 � 0.5 ft, so the uncertainty |
| 211 | + # is �0.5/36 = �1.4%. In metres this is 10.9728 � 1.4%, or 10.9728 � 0.154 |
| 212 | + # we take the stance of choosing the limit which is *more* precise than the |
| 213 | + # original value. |
| 214 | + |
| 215 | + # Strip sign and exponent |
| 216 | + $num = preg_replace( self::NUM_REGEX, '$2', $value[1] ); |
| 217 | + |
| 218 | + if( strpos( $num, '.' ) !== false ){ |
| 219 | + # If there is a decimal point, this is the number of digits after it. |
| 220 | + $dpAfter = strlen( $num ) - strpos( $num, '.' ) - 1; |
| 221 | + $error = pow( 10, -$dpAfter - 1 ) * 5; |
| 222 | + |
| 223 | + } elseif( $num == 0 ) { |
| 224 | + # The logarithms below will be unhappy, and it doesn't actually matter |
| 225 | + # what error we come up with, zero is still zero |
| 226 | + $error = 1; |
| 227 | + |
| 228 | + } else { |
| 229 | + # Number of digits before the point |
| 230 | + $dpBefore = floor( log10( abs( $num ) ) ); |
| 231 | + |
| 232 | + # Number of digits if we reverse the string = number |
| 233 | + # of digits excluding trailing zeros |
| 234 | + $dpAfter = floor( log10( abs( strrev( $num ) ) ) ); |
| 235 | + |
| 236 | + # How many significant figures to consider numbers like "35000" to have |
| 237 | + # is a tricky question. We say 2 here because if people want to ensure |
| 238 | + # that the zeros are included, they could write it as 3.500E4 |
| 239 | + $error = pow( 10, $dpBefore - $dpAfter - 1 ) * 5; |
| 240 | + } |
| 241 | + |
| 242 | + $errorFraction = $error / $num; |
| 243 | + |
| 244 | + $i = 10; |
| 245 | + while( $i > -10 && ( round( $newValue, $i - 1 ) != 0 ) && |
| 246 | + # Rounding to 10dp avoids floating point errors in exact conversions, |
| 247 | + # which are on the order of 1E-16 |
| 248 | + ( round( 5 * pow( 10, -$i ) / round( $newValue, $i - 1 ), 10 ) <= round( $errorFraction, 10 ) ) ) |
| 249 | + { |
| 250 | + $i--; |
| 251 | + } |
| 252 | + |
| 253 | + $newValue = round( $newValue, $i ); |
| 254 | + # We may need to stick significant zeros back onto the number |
| 255 | + if( $i > 0 ){ |
| 256 | + if( strpos( $newValue, '.' ) !== false ){ |
| 257 | + $newValue = str_pad( $newValue, $i + strpos( $newValue, '.' ) + 1, '0' ); |
| 258 | + } else { |
| 259 | + $newValue .= '.' . str_repeat( '0', $i ); |
| 260 | + } |
| 261 | + } |
| 262 | + } |
| 263 | + |
| 264 | + # Store the last value for use in PLURAL later |
| 265 | + $this->lastValue = $newValue; |
| 266 | + |
| 267 | + return $this->raw |
| 268 | + ? $newValue |
| 269 | + : $wgContLang->formatNum( $newValue ); |
| 270 | + } |
| 271 | + |
| 272 | +} |
| 273 | + |
| 274 | +/** |
| 275 | + * A dimension |
| 276 | + */ |
| 277 | +class ConvertDimension { |
| 278 | + |
| 279 | + const MASS = 1; # KILOGRAM |
| 280 | + const LENGTH = 10; # METRE |
| 281 | + const TIME = 100; # SECOND |
| 282 | + const TEMPERATURE = 1E3; # KELVIN |
| 283 | + const QUANTITY = 1E4; # MOLE |
| 284 | + const CURRENT = 1E5; # AMPERE |
| 285 | + const INTENSITY = 1E6; # CANDELA |
| 286 | + |
| 287 | + # fuel efficiencies are ugly and horrible and dimensionally confused, and have the |
| 288 | + # same dimensions as LENGTH or 1/LENGTH. But someone wanted to include them... so |
| 289 | + # we have up to ten dimensions which can be identified by values of this. |
| 290 | + # 0 = sane unit |
| 291 | + # 1 = some sort of fuel efficiency |
| 292 | + const UGLY_HACK_VALUE = 1E7; |
| 293 | + |
| 294 | + /** |
| 295 | + * Dimension constants. These are the values you'd get if you added the SI |
| 296 | + * base units together with the weighting given above, also the output from |
| 297 | + * getDimensionHash(). Cool thing is, you can add these together to get new |
| 298 | + * compound dimensions. |
| 299 | + */ |
| 300 | + const DIM_DIMENSIONLESS = 0; # Numbers etc |
| 301 | + const DIM_LENGTH = 10; |
| 302 | + const DIM_AREA = 20; |
| 303 | + const DIM_VOLUME = 30; |
| 304 | + const DIM_TIME = 100; |
| 305 | + const DIM_TIME_SQ = 200; |
| 306 | + const DIM_MASS = 1; |
| 307 | + const DIM_TEMPERATURE = 1000; |
| 308 | + const DIM_SPEED = -90; # LENGTH / TIME |
| 309 | + const DIM_ACCELERATION = -190; # LENGTH / TIME_SQ |
| 310 | + const DIM_FORCE = -189; # MASS * LENGTH / TIME_SQ |
| 311 | + const DIM_TORQUE = -179; # also MASS * AREA / TIME_SQ, but all units are single |
| 312 | + const DIM_ENERGY = -179; # MASS * AREA / TIME_SQ, all units are compound |
| 313 | + const DIM_PRESSURE = -209; # MASS / ( LENGTH * TIME_SQ ) |
| 314 | + const DIM_POWER = -79; # MASS * AREA / TIME |
| 315 | + const DIM_DENSITY = -29; # MASS / VOLUME |
| 316 | + const DIM_FUELEFFICIENCY_PVE = 10000020; # fuel efficiency in VOLUME / LENGTH |
| 317 | + const DIM_FUELEFFICIENCY_NVE = 99999990; # fuel efficiency in LENGTH / VOLUME |
| 318 | + |
| 319 | + # Map of dimension names to message keys. This also serves as a list of what |
| 320 | + # dimensions will not throw an error when encountered. |
| 321 | + public static $legalDimensions = array( |
| 322 | + self::DIM_LENGTH => 'length', |
| 323 | + self::DIM_AREA => 'area', |
| 324 | + self::DIM_VOLUME => 'volume', |
| 325 | + self::DIM_TIME => 'time', |
| 326 | + self::DIM_TIME_SQ => 'timesquared', |
| 327 | + self::DIM_MASS => 'mass', |
| 328 | + self::DIM_TEMPERATURE => 'temperature', |
| 329 | + self::DIM_SPEED => 'speed', |
| 330 | + self::DIM_ACCELERATION => 'acceleration', |
| 331 | + self::DIM_FORCE => 'force', |
| 332 | + self::DIM_TORQUE => 'torque', |
| 333 | + self::DIM_ENERGY => 'energy', |
| 334 | + self::DIM_PRESSURE => 'pressure', |
| 335 | + self::DIM_POWER => 'power', |
| 336 | + self::DIM_DENSITY => 'density', |
| 337 | + self::DIM_FUELEFFICIENCY_PVE => 'fuelefficiencypositive', |
| 338 | + self::DIM_FUELEFFICIENCY_NVE => 'fuelefficiencynegative', |
| 339 | + ); |
| 340 | + |
| 341 | + public $value; |
| 342 | + protected $name; |
| 343 | + |
| 344 | + public function __construct( $var, $var2=null ){ |
| 345 | + static $legalDimensionsFlip; |
| 346 | + |
| 347 | + if( is_string( $var ) ){ |
| 348 | + if( $legalDimensionsFlip === null ){ |
| 349 | + $legalDimensionsFlip = array_flip( self::$legalDimensions ); |
| 350 | + } |
| 351 | + if( isset( $legalDimensionsFlip[$var] ) ){ |
| 352 | + $dim = $legalDimensionsFlip[$var]; |
| 353 | + } else { |
| 354 | + # Should be unreachable |
| 355 | + throw new ConvertError( 'unknowndimension' ); |
| 356 | + } |
| 357 | + } elseif( $var instanceof self ){ |
| 358 | + $dim = $var->value; |
| 359 | + } else { |
| 360 | + $dim = intval( $var ); |
| 361 | + } |
| 362 | + |
| 363 | + if( $var2 === null ){ |
| 364 | + $this->value = $dim; |
| 365 | + $this->name = $this->compoundName = self::$legalDimensions[$this->value]; |
| 366 | + |
| 367 | + } else { |
| 368 | + if( is_string( $var2 ) ){ |
| 369 | + if( $legalDimensionsFlip === null ){ |
| 370 | + $legalDimensionsFlip = array_flip( self::$legalDimensions ); |
| 371 | + } |
| 372 | + if( isset( $legalDimensionsFlip[$var2] ) ){ |
| 373 | + $dim2 = $legalDimensionsFlip[$var2]; |
| 374 | + } else { |
| 375 | + # Should be unreachable |
| 376 | + throw new ConvertError( 'unknowndimension' ); |
| 377 | + } |
| 378 | + } elseif( $var2 instanceof self ){ |
| 379 | + $dim2 = $var2->value; |
| 380 | + } else { |
| 381 | + $dim2 = intval( $var2 ); |
| 382 | + } |
| 383 | + |
| 384 | + $this->value = $dim - $dim2; |
| 385 | + if( in_array( $this->value, array_keys( self::$legalDimensions ) ) ){ |
| 386 | + $this->name = self::$legalDimensions[$this->value]; |
| 387 | + $this->compoundName = array( |
| 388 | + self::$legalDimensions[$var], |
| 389 | + self::$legalDimensions[$var2], |
| 390 | + ); |
| 391 | + } else { |
| 392 | + # Some combinations of units are fine (carats per bushel is a perfectly good, |
| 393 | + # if somewhat bizarre, measure of density, for instance). But others (like |
| 394 | + # carats per miles-per-gallon) are definitely not. |
| 395 | + # TODO: this allows compound units like <gigawatthours>/<pascal> as a unit |
| 396 | + # of volume; is that a good thing or a bad thing? |
| 397 | + throw new ConvertError( 'invalidcompoundunit', "$var/$var2" ); |
| 398 | + } |
| 399 | + } |
| 400 | + } |
| 401 | + |
| 402 | + /** |
| 403 | + * Convert to string. Magic in PHP 5.1 and above. |
| 404 | + * @return String |
| 405 | + */ |
| 406 | + public function __toString(){ |
| 407 | + return strval( $this->name ); |
| 408 | + } |
| 409 | + |
| 410 | + /** |
| 411 | + * Get the name, or names, of the dimension |
| 412 | + * @return String|Array of String |
| 413 | + */ |
| 414 | + public function getName( $expandCompound = false ){ |
| 415 | + return $expandCompound |
| 416 | + ? $this->name |
| 417 | + : $this->compoundName; |
| 418 | + } |
| 419 | + |
| 420 | + /** |
| 421 | + * Get the localised name of the dimension. Output is unescaped |
| 422 | + * @return String |
| 423 | + */ |
| 424 | + public function getLocalisedName(){ |
| 425 | + return wfMsg( "pfunc-convert-dimension-{$this->name}" ); |
| 426 | + } |
| 427 | + |
| 428 | +} |
| 429 | + |
| 430 | +class ConvertUnit { |
| 431 | + |
| 432 | + /** |
| 433 | + * array( |
| 434 | + * DIMENSION => array( |
| 435 | + * UNIT => array( |
| 436 | + * CONVERSION, |
| 437 | + * REGEX |
| 438 | + * ) |
| 439 | + * ) |
| 440 | + * ) |
| 441 | + */ |
| 442 | + protected static $units = array( |
| 443 | + ConvertDimension::DIM_LENGTH => array( |
| 444 | + 'gigametre' => array( 1000000000, 'Gm' ), |
| 445 | + 'megametre' => array( 1000000, '(?:(?-i)Mm)' ), # Case-sensitivity is forced |
| 446 | + 'kilometre' => array( 1000, 'km' ), |
| 447 | + 'hectometre' => array( 100, 'hm' ), |
| 448 | + 'decametre' => array( 10, 'dam' ), |
| 449 | + 'metre' => array( 1, 'm' ), |
| 450 | + 'decimetre' => array( 0.1, 'dm' ), |
| 451 | + 'centimetre' => array( 0.01, 'cm' ), |
| 452 | + 'millimetre' => array( 0.001, '(?:(?-i)mm)' ), # Case-sensitivity is forced |
| 453 | + 'micrometre' => array( 0.0001, '\x03BCm|\x00B5m|um' ), # There are two similar mu characters |
| 454 | + 'nanometre' => array( 0.0000001, 'nm' ), |
| 455 | + 'angstrom' => array( 0.00000001, '\x00C5' ), |
| 456 | + |
| 457 | + 'mile' => array( 1609.344, 'mi|miles?' ), |
| 458 | + 'furlong' => array( 201.168, 'furlong' ), |
| 459 | + 'chain' => array( 20.1168 , 'chain' ), |
| 460 | + 'rod' => array( 5.0292, 'rod|pole|perch' ), |
| 461 | + 'fathom' => array( 1.8288, 'fathom' ), |
| 462 | + 'yard' => array( 0.9144, 'yards?|yd' ), |
| 463 | + 'foot' => array( 0.3048, 'foot|feet|ft' ), |
| 464 | + 'hand' => array( 0.1016, 'hands?' ), |
| 465 | + 'inch' => array( 0.0254, 'inch|inches|in' ), |
| 466 | + |
| 467 | + 'nauticalmile' => array( 1852, 'nauticalmiles?|nmi' ), |
| 468 | + 'nauticalmileuk' => array( 1853.184, 'oldUKnmi|Brnmi|admi' ), |
| 469 | + 'nauticalmileus' => array( 1853.24496, 'oldUSnmi' ), |
| 470 | + |
| 471 | + 'gigaparsec' => array( 3.0856775813057E25, 'gigaparsecs?|Gpc' ), |
| 472 | + 'megaparsec' => array( 3.0856775813057E22, 'megaparsecs?|Mpc' ), |
| 473 | + 'kiloparsec' => array( 3.0856775813057E19, 'kiloparsecs?|kpc' ), |
| 474 | + 'parsec' => array( 3.0856775813057E16, 'parsecs?|pc' ), |
| 475 | + 'gigalightyear' => array( 9.4607304725808E24, 'gigalightyears?|Gly' ), |
| 476 | + 'mrgalightyear' => array( 9.4607304725808E21, 'megalightyears?|Mly' ), |
| 477 | + 'kilolightyear' => array( 9.4607304725808E18, 'kilolightyears?|kly' ), |
| 478 | + 'lightyear' => array( 9.4607304725808E15, 'lightyears?|ly' ), |
| 479 | + 'astronomicalunit' => array( 149597870700, 'astronomicalunits?|AU' ), |
| 480 | + ), |
| 481 | + |
| 482 | + ConvertDimension::DIM_AREA => array( |
| 483 | + 'squarekilometre' => array( 1E6, 'km2|km\^2' ), |
| 484 | + 'squaremetre' => array( 1, 'm2|m\^2' ), |
| 485 | + 'squarecentimetre' => array( 1E-4, 'cm2|cm\^2' ), |
| 486 | + 'squaremillimetre' => array( 1E-6, 'mm2|mm\^2' ), |
| 487 | + 'hectare' => array( 1E4, 'hectares?|ha' ), |
| 488 | + |
| 489 | + 'squaremile' => array( 2589988.110336, 'sqmi|mi2|mi\^2' ), |
| 490 | + 'acre' => array( 4046.856422 , 'acres?' ), |
| 491 | + 'squareyard' => array( 0.83612736, 'sqyd|yd2|yd\^2' ), |
| 492 | + 'squarefoot' => array( 0.09290304, 'sqft|ft2|ft\^2' ), |
| 493 | + 'squareinch' => array( 0.00064516, 'sqin|in2|in\^2' ), |
| 494 | + |
| 495 | + 'squarenauticalmile' => array( 3429904, 'sqnmi|nmi2|nmi\^2' ), |
| 496 | + 'dunam' => array( 1000, 'dunam' ), |
| 497 | + 'tsubo' => array( 3.305785, 'tsubo' ), |
| 498 | + ), |
| 499 | + |
| 500 | + ConvertDimension::DIM_VOLUME => array( |
| 501 | + 'cubicmetre' => array( 1, 'm3|m\^3' ), |
| 502 | + 'cubiccentimetre' => array( 1E-6, 'cm3|cm\^3' ), |
| 503 | + 'cubicmillimetre' => array( 1E-9, 'mm3|mm\^3' ), |
| 504 | + 'kilolitre' => array( 1, 'kl' ), |
| 505 | + 'litre' => array( 1E-3 , 'l' ), |
| 506 | + 'centilitre' => array( 1E-5, 'cl' ), |
| 507 | + 'millilitre' => array( 1E-6, 'ml' ), |
| 508 | + |
| 509 | + 'cubicyard' => array( 0.764554857984, 'cuyd|yd3|yd\^3' ), |
| 510 | + 'cubicfoot' => array( 0.028316846592, 'cuft|ft3|ft\^3' ), |
| 511 | + 'cubicinch' => array( 0.000016387064, 'cuin|in3|in\^3' ), |
| 512 | + 'barrel' => array( 0.16365924, 'bbl|barrels?|impbbl' ), |
| 513 | + 'bushel' => array( 0.03636872, 'bsh|bushels?|impbsh' ), |
| 514 | + 'gallon' => array( 0.00454609, 'gal|gallons?|impgal' ), |
| 515 | + 'quart' => array( 0.0011365225, 'qt|quarts?|impqt' ), |
| 516 | + 'pint' => array( 0.00056826125, 'pt|pints?|imppt' ), |
| 517 | + 'fluidounce' => array( 0.0000284130625, 'floz|impfloz' ), |
| 518 | + |
| 519 | + 'barrelus' => array( 0.119240471196, 'usbbl' ), |
| 520 | + 'barreloil' => array( 0.158987294928, 'oilbbl' ), |
| 521 | + 'barrelbeer' => array( 0.117347765304, 'beerbbl' ), |
| 522 | + 'usgallon' => array( 0.003785411784, 'usgal' ), |
| 523 | + 'usquart' => array( 0.000946352946, 'usqt' ), |
| 524 | + 'uspint' => array( 0.000473176473, 'uspt' ), |
| 525 | + 'usfluidounce' => array( 0.0000295735295625, 'usfloz' ), |
| 526 | + 'usdrybarrel' => array( 0.11562819898508, 'usdrybbl' ), |
| 527 | + 'usbushel' => array( 0.03523907016688, 'usbsh' ), |
| 528 | + 'usdrygallon' => array( 0.00440488377086, 'usdrygal' ), |
| 529 | + 'usdryquart' => array( 0.001101220942715, 'usdryqt' ), |
| 530 | + 'usdrypint' => array( 0.0005506104713575, 'usdrypt' ), |
| 531 | + ), |
| 532 | + |
| 533 | + ConvertDimension::DIM_TIME => array( |
| 534 | + 'year' => array( 31557600, 'yr' ), |
| 535 | + 'day' => array( 86400, 'days?' ), |
| 536 | + 'hour' => array( 3600, 'hours?|hr|h' ), |
| 537 | + 'minute' => array( 60, 'minutes?|mins?' ), |
| 538 | + 'second' => array( 1, 's' ), |
| 539 | + ), |
| 540 | + |
| 541 | + ConvertDimension::DIM_SPEED => array( |
| 542 | + 'knot' => array( 0.514444444, 'knot|kn' ), |
| 543 | + 'speedoflight' => array( 2.9979E8, 'c' ), |
| 544 | + ), |
| 545 | + |
| 546 | + ConvertDimension::DIM_PRESSURE => array( |
| 547 | + 'gigapascal' => array( 1000000000, 'GPa' ), |
| 548 | + 'megapascal' => array( 1000000, '(?:(?-i)M[Pp]a)' ), # Case-sensitivity is forced |
| 549 | + 'kilopascal' => array( 1000, 'kPa' ), |
| 550 | + 'hectopascal' => array( 100, 'hPa' ), |
| 551 | + 'pascal' => array( 1, 'Pa' ), |
| 552 | + 'millipascal' => array( 0.001, '(?:(?-i)m[Pp]a)' ), # Case-sensitivity is forced |
| 553 | + |
| 554 | + 'bar' => array( 100000, 'bar' ), |
| 555 | + 'decibar' => array( 10000, 'dbar' ), |
| 556 | + 'milibar' => array( 100 , 'mbar|mb' ), |
| 557 | + 'kilobarye' => array( 100, 'kba' ), |
| 558 | + 'barye' => array( 0.1, 'ba' ), |
| 559 | + |
| 560 | + 'atmosphere' => array( 101325, 'atm|atmospheres?' ), |
| 561 | + 'torr' => array( 133.32237, 'torr' ), |
| 562 | + 'mmhg' => array( 133.322387415, 'mmHg' ), |
| 563 | + 'inhg' => array( 3386.38864034, 'inHg' ), |
| 564 | + 'psi' => array( 6894.757293, 'psi' ), |
| 565 | + ), |
| 566 | + # TODO: other dimensions as needed |
| 567 | + ); |
| 568 | + |
| 569 | + # Default units for each dimension |
| 570 | + # TODO: this should ideally be localisable |
| 571 | + protected static $defaultUnit = array( |
| 572 | + ConvertDimension::DIM_LENGTH => 'metre', |
| 573 | + ConvertDimension::DIM_AREA => 'squaremetre', |
| 574 | + ConvertDimension::DIM_VOLUME => 'cubicmetre', |
| 575 | + ConvertDimension::DIM_TIME => 'second', |
| 576 | + ConvertDimension::DIM_SPEED => 'metre/second', |
| 577 | + ConvertDimension::DIM_PRESSURE => 'pascal', |
| 578 | + ); |
| 579 | + |
| 580 | + # An array of preprocessing conversions to apply to units |
| 581 | + protected static $unitConversions = array( |
| 582 | + '/^mph$/ui' => 'mi/h', |
| 583 | + ); |
| 584 | + |
| 585 | + # Map of UNIT => DIMENSION, created on construct |
| 586 | + protected static $dimensionMap = false; |
| 587 | + |
| 588 | + /***************** MEMBER VARIABLES *****************/ |
| 589 | + |
| 590 | + # @var ConvertDimension |
| 591 | + public $dimension; |
| 592 | + |
| 593 | + # What number you need to multiply this unit by to get the equivalent |
| 594 | + # value in SI base units |
| 595 | + protected $conversion = 1; |
| 596 | + |
| 597 | + # A regex which matches the unit |
| 598 | + protected $regex; |
| 599 | + |
| 600 | + # The name of the unit (key into $units[$dimension] above |
| 601 | + protected $unitName; |
| 602 | + |
| 603 | + /***************** MEMBER FUNCTIONS *****************/ |
| 604 | + |
| 605 | + /** |
| 606 | + * Constructor |
| 607 | + * @param $rawUnit String |
| 608 | + */ |
| 609 | + public function __construct( $rawUnit ){ |
| 610 | + if( self::$dimensionMap === false ){ |
| 611 | + self::$dimensionMap = array(); |
| 612 | + foreach( self::$units as $dimension => $arr ){ |
| 613 | + foreach( $arr as $unit => $val ){ |
| 614 | + self::$dimensionMap[$unit] = $dimension; |
| 615 | + } |
| 616 | + } |
| 617 | + } |
| 618 | + |
| 619 | + $this->parseUnit( $rawUnit ); |
| 620 | + } |
| 621 | + |
| 622 | + protected function parseUnit( $rawUnit ){ |
| 623 | + |
| 624 | + # Do mappings like 'mph' --> 'mi/h' |
| 625 | + $rawUnit = preg_replace( |
| 626 | + array_keys( self::$unitConversions ), |
| 627 | + array_values( self::$unitConversions ), |
| 628 | + $rawUnit |
| 629 | + ); |
| 630 | + |
| 631 | + $parts = explode( '/', $rawUnit ); |
| 632 | + array_map( 'trim', $parts ); |
| 633 | + if( count( $parts ) == 1 ){ |
| 634 | + # Single unit |
| 635 | + foreach( self::$units as $dimension => $units ){ |
| 636 | + foreach( $units as $unit => $data ){ |
| 637 | + if( $rawUnit == $unit || preg_match( "/^({$data[1]})$/ui", $parts[0] ) ){ |
| 638 | + $this->dimension = new ConvertDimension( self::$dimensionMap[$unit] ); |
| 639 | + $this->conversion = self::$units[$this->dimension->value][$unit][0]; |
| 640 | + $this->regex = $data[1]; |
| 641 | + $this->unitName = $unit; |
| 642 | + return; |
| 643 | + } |
| 644 | + } |
| 645 | + } |
| 646 | + |
| 647 | + # Unknown unit |
| 648 | + throw new ConvertError( 'unknownunit', $rawUnit ); |
| 649 | + |
| 650 | + } elseif( count( $parts ) == 2 ){ |
| 651 | + # Compound unit. |
| 652 | + $top = new self( $parts[0] ); |
| 653 | + $bottom = new self( $parts[1] ); |
| 654 | + $this->dimension = new ConvertDimension( $top->dimension, $bottom->dimension ); |
| 655 | + $this->conversion = $top->conversion / $bottom->conversion; |
| 656 | + $this->regex = "(?:{$top->regex})/(?:{$bottom->regex})"; |
| 657 | + $this->unitName = array( $top->unitName, $bottom->unitName ); |
| 658 | + return; |
| 659 | + |
| 660 | + } else { |
| 661 | + # Whaaat? Too many parts |
| 662 | + throw new ConvertError( 'doublecompoundunit', $rawUnit ); |
| 663 | + } |
| 664 | + } |
| 665 | + |
| 666 | + public function getConversion(){ |
| 667 | + return $this->conversion; |
| 668 | + } |
| 669 | + |
| 670 | + public function getRegex(){ |
| 671 | + return $this->regex; |
| 672 | + } |
| 673 | + |
| 674 | + /** |
| 675 | + * Get the text of the unit |
| 676 | + * @param $value String number for PLURAL support |
| 677 | + * @param $link Bool |
| 678 | + * @return String |
| 679 | + */ |
| 680 | + public function getText( $value, $link=false, $abbreviate=false ){ |
| 681 | + global $wgContLang; |
| 682 | + $value = $wgContLang->formatNum( $value ); |
| 683 | + $abbr = $abbreviate ? '-abbr' : ''; |
| 684 | + |
| 685 | + if( !is_array( $this->unitName ) ){ |
| 686 | + $msg = "pfunc-convert-unit-{$this->dimension->getName()}-{$this->unitName}"; |
| 687 | + $msgText = wfMsgExt( "$msg$abbr", array( 'parsemag', 'content' ), $value ); |
| 688 | + if( $link && !wfEmptyMsg( "$msg-link" ) ){ |
| 689 | + $title = Title::newFromText( wfMsgForContentNoTrans( "$msg-link" ) ); |
| 690 | + $msgText = "[[{$title->getFullText()}|$msgText]]"; |
| 691 | + } |
| 692 | + |
| 693 | + } elseif( !wfEmptyMsg( "pfunc-convert-unit-{$this->dimension->getName(true)}-{$this->unitName[0]}-{$this->unitName[1]}" ) ){ |
| 694 | + # A wiki has created, say, [[MediaWiki:pfunc-convert-unit-speed-metres-second]] |
| 695 | + # so they can have it display "<metres per second>" rather than |
| 696 | + # "<metres>/<second>" |
| 697 | + $msg = "pfunc-convert-unit-{$this->dimension->getName(true)}-{$this->unitName[0]}-{$this->unitName[1]}"; |
| 698 | + $msgText = wfMsgExt( "$msg$abbr", array( 'parsemag', 'content' ), $value ); |
| 699 | + if( $link && !wfEmptyMsg( "$msg-link" ) ){ |
| 700 | + $title = Title::newFromText( wfMsgForContentNoTrans( "$msg-link" ) ); |
| 701 | + if( $title instanceof Title ){ |
| 702 | + $msgText = "[[$title|$msgText]]"; |
| 703 | + } |
| 704 | + } |
| 705 | + |
| 706 | + } else { |
| 707 | + $dimensionNames = $this->dimension->getName(); |
| 708 | + $msg = "pfunc-convert-unit-{$dimensionNames[0]}-{$this->unitName[0]}"; |
| 709 | + $msgText = wfMsgExt( "$msg$abbr", array( 'parsemag', 'content' ), $value ); |
| 710 | + if( $link && !wfEmptyMsg( "$msg-link" ) ){ |
| 711 | + $title = Title::newFromText( wfMsgForContentNoTrans( "$msg-link" ) ); |
| 712 | + $msgText = "[[{$title->getFullText()}|$msgText]]"; |
| 713 | + } |
| 714 | + |
| 715 | + $msg2 = "pfunc-convert-unit-{$dimensionNames[1]}-{$this->unitName[1]}"; |
| 716 | + $msg2Text = wfMsgExt( "$msg2$abbr", array( 'parsemag', 'content' ), 1 ); # Singular for denominator |
| 717 | + if( $link && !wfEmptyMsg( "$msg2-link" ) ){ |
| 718 | + $title = Title::newFromText( wfMsgForContentNoTrans( "$msg2-link" ) ); |
| 719 | + if( $title instanceof Title ){ |
| 720 | + $msg2Text = "[[{$title->getFullText()}|$msg2Text]]"; |
| 721 | + } |
| 722 | + } |
| 723 | + $msgText = "$msgText/$msg2Text"; |
| 724 | + } |
| 725 | + |
| 726 | + return $msgText; |
| 727 | + } |
| 728 | + |
| 729 | + /** |
| 730 | + * Get the default (usually SI) unit associated with this particular dimension |
| 731 | + * @return ConvertUnit |
| 732 | + */ |
| 733 | + public function getDefaultUnit(){ |
| 734 | + return new ConvertUnit( self::$defaultUnit[$this->dimension->value] ); |
| 735 | + } |
| 736 | +} |
Property changes on: trunk/extensions/ParserFunctions/Convert.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 737 | + native |
Index: trunk/extensions/ParserFunctions/ParserFunctions.i18n.magic.php |
— | — | @@ -22,6 +22,13 @@ |
23 | 23 | 'timel' => array( 0, 'timel' ), |
24 | 24 | 'rel2abs' => array( 0, 'rel2abs' ), |
25 | 25 | 'titleparts' => array( 0, 'titleparts' ), |
| 26 | + 'convert' => array( 0, 'convert' ), |
| 27 | + 'sourceunit' => array( 0, '#sourceunit' ), |
| 28 | + 'targetunit' => array( 0, '#targetunit' ), |
| 29 | + 'linkunit' => array( 0, '#linkunit' ), |
| 30 | + 'decimalplaces' => array( 0, '#dp' ), |
| 31 | + 'significantfigures' => array( 0, '#sf' ), |
| 32 | + 'abbreviate' => array( 0, '#abbreviate' ), |
26 | 33 | 'len' => array( 0, 'len' ), |
27 | 34 | 'pos' => array( 0, 'pos' ), |
28 | 35 | 'rpos' => array( 0, 'rpos' ), |
Index: trunk/extensions/ParserFunctions/ParserFunctions_body.php |
— | — | @@ -512,6 +512,29 @@ |
513 | 513 | } |
514 | 514 | } |
515 | 515 | |
| 516 | + /** |
| 517 | + * Get a ConvertParser object |
| 518 | + * @return ConvertParser |
| 519 | + */ |
| 520 | + protected function &getConvertParser() { |
| 521 | + if ( !isset( $this->mConvertParser ) ) { |
| 522 | + if ( !class_exists( 'ConvertParser' ) ) { |
| 523 | + require( dirname( __FILE__ ) . '/Convert.php' ); |
| 524 | + } |
| 525 | + $this->mConvertParser = new ConvertParser; |
| 526 | + } |
| 527 | + return $this->mConvertParser; |
| 528 | + } |
| 529 | + |
| 530 | + public function convert( /*...*/ ) { |
| 531 | + try { |
| 532 | + $args = func_get_args(); |
| 533 | + return $this->getConvertParser()->execute( $args ); |
| 534 | + } catch ( ConvertError $e ) { |
| 535 | + return $e->getMessage(); |
| 536 | + } |
| 537 | + } |
| 538 | + |
516 | 539 | // Verifies parameter is less than max string length. |
517 | 540 | private function checkLength( $text ) { |
518 | 541 | global $wgPFStringLengthLimit; |
Index: trunk/extensions/ParserFunctions/ParserFunctions.i18n.php |
— | — | @@ -27,7 +27,244 @@ |
28 | 28 | 'pfunc_expr_invalid_argument_ln' => 'Invalid argument for ln: <= 0', |
29 | 29 | 'pfunc_expr_unknown_error' => 'Expression error: Unknown error ($1)', |
30 | 30 | 'pfunc_expr_not_a_number' => 'In $1: result is not a number', |
31 | | - 'pfunc_string_too_long' => 'Error: String exceeds $1 character limit', |
| 31 | + 'pfunc_string_too_long' => 'Error: string exceeds $1 character limit', |
| 32 | + 'pfunc-convert-dimensionmismatch' => 'Error: cannot convert between units of "$1" and "$2"', |
| 33 | + 'pfunc-convert-unknownunit' => 'Error: unknown unit "$1"', |
| 34 | + 'pfunc-convert-unknowndimension' => 'Error: unknown dimension "$1"', |
| 35 | + 'pfunc-convert-invalidcompoundunit' => 'Error: invalid compound unit "$1"', |
| 36 | + 'pfunc-convert-nounit' => 'Error: no source unit given', |
| 37 | + 'pfunc-convert-doublecompoundunit' => 'Error: cannot parse double compound units like "$1"', |
| 38 | + |
| 39 | + # DIMENSION NAMES |
| 40 | + 'pfunc-convert-dimension-length' => 'length', |
| 41 | + 'pfunc-convert-dimension-area' => 'area', |
| 42 | + 'pfunc-convert-dimension-volume' => 'volume', |
| 43 | + 'pfunc-convert-dimension-time' => 'time', |
| 44 | + 'pfunc-convert-dimension-timesquared' => 'time<sup>2</sup>', |
| 45 | + 'pfunc-convert-dimension-mass' => 'mass', |
| 46 | + 'pfunc-convert-dimension-speed' => 'speed', |
| 47 | + 'pfunc-convert-dimension-temperature' => 'temperature', |
| 48 | + 'pfunc-convert-dimension-acceleration' => 'acceleration', |
| 49 | + 'pfunc-convert-dimension-force' => 'force', |
| 50 | + 'pfunc-convert-dimension-torque' => 'torque', |
| 51 | + 'pfunc-convert-dimension-energy' => 'energy', |
| 52 | + 'pfunc-convert-dimension-power' => 'power', |
| 53 | + 'pfunc-convert-dimension-pressure' => 'pressure', |
| 54 | + 'pfunc-convert-dimension-density' => 'density', |
| 55 | + 'pfunc-convert-dimension-fuelefficiencypositive' => 'fuelefficiencypositive', |
| 56 | + 'pfunc-convert-dimension-fuelefficiencynegative' => 'fuelefficiencynegative', |
| 57 | + |
| 58 | + # LENGTH |
| 59 | + 'pfunc-convert-unit-length-gigametre' => '{{PLURAL:$1|gigametre|gigametres}}', |
| 60 | + 'pfunc-convert-unit-length-megametre' => '{{PLURAL:$1|megametre|megametres}}', |
| 61 | + 'pfunc-convert-unit-length-kilometre' => '{{PLURAL:$1|kilometre|kilometres}}', |
| 62 | + 'pfunc-convert-unit-length-hectometre' => '{{PLURAL:$1|hectometre|hectometres}}', |
| 63 | + 'pfunc-convert-unit-length-decametre' => '{{PLURAL:$1|decametre|decametres}}', |
| 64 | + 'pfunc-convert-unit-length-metre' => '{{PLURAL:$1|metre|metres}}', |
| 65 | + 'pfunc-convert-unit-length-decimetre' => '{{PLURAL:$1|decimetre|decimetres}}', |
| 66 | + 'pfunc-convert-unit-length-centimetre' => '{{PLURAL:$1|centimetre|centimetres}}', |
| 67 | + 'pfunc-convert-unit-length-millimetre' => '{{PLURAL:$1|millimetre|millimetres}}', |
| 68 | + 'pfunc-convert-unit-length-micrometre' => '{{PLURAL:$1|micrometre|micrometres}}', |
| 69 | + 'pfunc-convert-unit-length-nanometre' => '{{PLURAL:$1|nanometre|nanometres}}', |
| 70 | + 'pfunc-convert-unit-length-angstrom' => '{{PLURAL:$1|angstrom|angstroms}}', |
| 71 | + 'pfunc-convert-unit-length-mile' => '{{PLURAL:$1|mile|miles}}', |
| 72 | + 'pfunc-convert-unit-length-furlong' => '{{PLURAL:$1|furlong|furlongs}}', |
| 73 | + 'pfunc-convert-unit-length-chain' => '{{PLURAL:$1|chain|chains}}', |
| 74 | + 'pfunc-convert-unit-length-rod' => '{{PLURAL:$1|rod|rods}}', |
| 75 | + 'pfunc-convert-unit-length-fathom' => '{{PLURAL:$1|fathom|fathoms}}', |
| 76 | + 'pfunc-convert-unit-length-yard' => '{{PLURAL:$1|yard|yards}}', |
| 77 | + 'pfunc-convert-unit-length-foot' => '{{PLURAL:$1|foot|feet}}', |
| 78 | + 'pfunc-convert-unit-length-hand' => '{{PLURAL:$1|hand|hands}}', |
| 79 | + 'pfunc-convert-unit-length-inch' => '{{PLURAL:$1|inch|inches}}', |
| 80 | + 'pfunc-convert-unit-length-nauticalmile' => '{{PLURAL:$1|nautical mile|nautical miles}}', |
| 81 | + 'pfunc-convert-unit-length-nauticalmileuk' => '{{PLURAL:$1|nautical mile (pre-1970 British)|nautical miles (pre-1970 British)}}', |
| 82 | + 'pfunc-convert-unit-length-nauticalmileus' => '{{PLURAL:$1|nautical mile (pre-1954 US)|nautical miles (pre-1954 US)}}', |
| 83 | + 'pfunc-convert-unit-length-gigaparsec' => '{{PLURAL:$1|gigaparsec|gigaparsecs}}', |
| 84 | + 'pfunc-convert-unit-length-megaparsec' => '{{PLURAL:$1|megaparsec|megaparsecs}}', |
| 85 | + 'pfunc-convert-unit-length-kiloparsec' => '{{PLURAL:$1|kiloparsec|kiloparsecs}}', |
| 86 | + 'pfunc-convert-unit-length-parsec' => '{{PLURAL:$1|parsec|parsecs}}', |
| 87 | + 'pfunc-convert-unit-length-gigalightyear' => '{{PLURAL:$1|gigalightyear|gigalightyears}}', |
| 88 | + 'pfunc-convert-unit-length-mrgalightyear' => '{{PLURAL:$1|megalightyear|megalightyears}}', |
| 89 | + 'pfunc-convert-unit-length-kilolightyear' => '{{PLURAL:$1|kilolightyear|kilolightyears}}', |
| 90 | + 'pfunc-convert-unit-length-lightyear' => '{{PLURAL:$1|lightyear|lightyears}}', |
| 91 | + 'pfunc-convert-unit-length-astronomicalunit' => '{{PLURAL:$1|astronomical unit|astronomical units}}', |
| 92 | + |
| 93 | + 'pfunc-convert-unit-length-gigametre-abbr' => 'Gm', |
| 94 | + 'pfunc-convert-unit-length-megametre-abbr' => 'Mm', |
| 95 | + 'pfunc-convert-unit-length-kilometre-abbr' => 'km', |
| 96 | + 'pfunc-convert-unit-length-hectometre-abbr' => 'hm', |
| 97 | + 'pfunc-convert-unit-length-decametre-abbr' => 'dam', |
| 98 | + 'pfunc-convert-unit-length-metre-abbr' => 'm', |
| 99 | + 'pfunc-convert-unit-length-decimetre-abbr' => 'dm', |
| 100 | + 'pfunc-convert-unit-length-centimetre-abbr' => 'cm', |
| 101 | + 'pfunc-convert-unit-length-milimetre-abbr' => 'mm', |
| 102 | + 'pfunc-convert-unit-length-micrometre-abbr' => 'μm', |
| 103 | + 'pfunc-convert-unit-length-nanometre-abbr' => 'nm', |
| 104 | + 'pfunc-convert-unit-length-angstrom-abbr' => 'Å', |
| 105 | + 'pfunc-convert-unit-length-mile-abbr' => 'mi', |
| 106 | + 'pfunc-convert-unit-length-furlong-abbr' => 'furlong', |
| 107 | + 'pfunc-convert-unit-length-chain-abbr' => 'chain', |
| 108 | + 'pfunc-convert-unit-length-rod-abbr' => 'rd', |
| 109 | + 'pfunc-convert-unit-length-fathom-abbr' => 'fathom', |
| 110 | + 'pfunc-convert-unit-length-yard-abbr' => 'yd', |
| 111 | + 'pfunc-convert-unit-length-foot-abbr' => 'ft', |
| 112 | + 'pfunc-convert-unit-length-hand-abbr' => 'h', |
| 113 | + 'pfunc-convert-unit-length-inch-abbr' => 'in', |
| 114 | + 'pfunc-convert-unit-length-nauticalmile-abbr' => 'nmi', |
| 115 | + 'pfunc-convert-unit-length-nauticalmileuk-abbr' => 'nmi (Brit)', |
| 116 | + 'pfunc-convert-unit-length-nauticalmileus-abbr' => 'nmi (pre-1954 US)', |
| 117 | + 'pfunc-convert-unit-length-gigaparsec-abbr' => 'Gpc', |
| 118 | + 'pfunc-convert-unit-length-megaparsec-abbr' => 'Mpc', |
| 119 | + 'pfunc-convert-unit-length-kiloparsec-abbr' => 'kpc', |
| 120 | + 'pfunc-convert-unit-length-parsec-abbr' => 'pc', |
| 121 | + 'pfunc-convert-unit-length-gigalightyear-abbr' => 'Gly', |
| 122 | + 'pfunc-convert-unit-length-mrgalightyear-abbr' => 'Mly', |
| 123 | + 'pfunc-convert-unit-length-kilolightyear-abbr' => 'kly', |
| 124 | + 'pfunc-convert-unit-length-lightyear-abbr' => 'ly', |
| 125 | + 'pfunc-convert-unit-length-astronomicalunit-abbr' => 'AU', |
| 126 | + |
| 127 | + # AREA # |
| 128 | + 'pfunc-convert-unit-area-squarekilometre' => '{{PLURAL:$1|square kilometre|square kilometres}}', |
| 129 | + 'pfunc-convert-unit-area-squaremetre' => '{{PLURAL:$1|square metre|square metres}}', |
| 130 | + 'pfunc-convert-unit-area-squarecentimetre' => '{{PLURAL:$1|square centimetre|square centimetres}}', |
| 131 | + 'pfunc-convert-unit-area-squaremillimetre' => '{{PLURAL:$1|square millimetre|square millimetres}}', |
| 132 | + 'pfunc-convert-unit-area-hectare' => '{{PLURAL:$1|hectare|hectares}}', |
| 133 | + 'pfunc-convert-unit-area-squaremile' => '{{PLURAL:$1|square mile|square miles}}', |
| 134 | + 'pfunc-convert-unit-area-acre' => '{{PLURAL:$1|acre|acres}}', |
| 135 | + 'pfunc-convert-unit-area-squareyard' => '{{PLURAL:$1|square yard|square yards}}', |
| 136 | + 'pfunc-convert-unit-area-squarefoot' => '{{PLURAL:$1|square foot|square feet}}', |
| 137 | + 'pfunc-convert-unit-area-squareinch' => '{{PLURAL:$1|square inch|square inches}}', |
| 138 | + 'pfunc-convert-unit-area-squarenauticalmile' => '{{PLURAL:$1|square nautical mile|square nautical miles}}', |
| 139 | + 'pfunc-convert-unit-area-dunam' => '{{PLURAL:$1|dunam|dunams}}', |
| 140 | + 'pfunc-convert-unit-area-tsubo' => '{{PLURAL:$1|tsubo|tsubo}}', |
| 141 | + |
| 142 | + 'pfunc-convert-unit-area-squarekilometre-abbr' => 'km<sup>2</sup>', |
| 143 | + 'pfunc-convert-unit-area-squaremetre-abbr' => 'm<sup>2</sup>', |
| 144 | + 'pfunc-convert-unit-area-squarecentimetre-abbr' => 'cm<sup>2</sup>', |
| 145 | + 'pfunc-convert-unit-area-squaremillimetre-abbr' => 'mm<sup>2</sup>', |
| 146 | + 'pfunc-convert-unit-area-hectare-abbr' => 'ha', |
| 147 | + 'pfunc-convert-unit-area-squaremile-abbr' => 'sq mi', |
| 148 | + 'pfunc-convert-unit-area-acre-abbr' => 'acre', |
| 149 | + 'pfunc-convert-unit-area-squareyard-abbr' => 'sq yd', |
| 150 | + 'pfunc-convert-unit-area-squarefoot-abbr' => 'sq ft', |
| 151 | + 'pfunc-convert-unit-area-squareinch-abbr' => 'sq in', |
| 152 | + 'pfunc-convert-unit-area-squarenauticalmile-abbr' => 'sq nmi', |
| 153 | + 'pfunc-convert-unit-area-dunam-abbr' => 'dunam', |
| 154 | + 'pfunc-convert-unit-area-tsubo-abbr' => 'tsubo', |
| 155 | + |
| 156 | + # TIME # |
| 157 | + 'pfunc-convert-unit-time-second' => '{{PLURAL:$1|second|seconds}}', |
| 158 | + 'pfunc-convert-unit-time-year' => '{{PLURAL:$1|year|years}}', |
| 159 | + 'pfunc-convert-unit-time-day' => '{{PLURAL:$1|day|days}}', |
| 160 | + 'pfunc-convert-unit-time-hour' => '{{PLURAL:$1|hour|hours}}', |
| 161 | + 'pfunc-convert-unit-time-minute' => '{{PLURAL:$1|minute|minutes}}', |
| 162 | + |
| 163 | + 'pfunc-convert-unit-time-second-abbr' => 's', |
| 164 | + 'pfunc-convert-unit-time-year-abbr' => 'yr', |
| 165 | + 'pfunc-convert-unit-time-day-abbr' => 'day', |
| 166 | + 'pfunc-convert-unit-time-hour-abbr' => 'hr', |
| 167 | + 'pfunc-convert-unit-time-minute-abbr' => 'min', |
| 168 | + |
| 169 | + # VOLUME # |
| 170 | + 'pfunc-convert-unit-volume-cubicmetre' => '{{PLURAL:$1|cubic metre|cubic metres}}', |
| 171 | + 'pfunc-convert-unit-volume-cubiccentimetre' => '{{PLURAL:$1|cubic centimetre|cubic centimetres}}', |
| 172 | + 'pfunc-convert-unit-volume-cubicmillimetre' => '{{PLURAL:$1|cubic millimetre|cubic millimetres}}', |
| 173 | + 'pfunc-convert-unit-volume-kilolitre' => '{{PLURAL:$1|kilolitre|kilolitres}}', |
| 174 | + 'pfunc-convert-unit-volume-litre' => '{{PLURAL:$1|litre|litres}}', |
| 175 | + 'pfunc-convert-unit-volume-centilitre' => '{{PLURAL:$1|centilitre|centilitres}}', |
| 176 | + 'pfunc-convert-unit-volume-millilitre' => '{{PLURAL:$1|millilitre|millilitres}}', |
| 177 | + 'pfunc-convert-unit-volume-cubicyard' => '{{PLURAL:$1|cubic yard|cubic yards}}', |
| 178 | + 'pfunc-convert-unit-volume-cubicfoot' => '{{PLURAL:$1|cubic foot|cubic feet}}', |
| 179 | + 'pfunc-convert-unit-volume-cubicinch' => '{{PLURAL:$1|cubic inch|cubic inches}}', |
| 180 | + 'pfunc-convert-unit-volume-barrel' => '{{PLURAL:$1|barrel|barrels}}', |
| 181 | + 'pfunc-convert-unit-volume-bushel' => '{{PLURAL:$1|bushel|bushels}}', |
| 182 | + 'pfunc-convert-unit-volume-gallon' => '{{PLURAL:$1|gallon|gallons}}', |
| 183 | + 'pfunc-convert-unit-volume-quart' => '{{PLURAL:$1|quart|quarts}}', |
| 184 | + 'pfunc-convert-unit-volume-pint' => '{{PLURAL:$1|pint|pints}}', |
| 185 | + 'pfunc-convert-unit-volume-fluidounce' => '{{PLURAL:$1|fluid ounce|fluid ounces}}', |
| 186 | + 'pfunc-convert-unit-volume-barrelus' => '{{PLURAL:$1|US barrel|US barrels}}', |
| 187 | + 'pfunc-convert-unit-volume-barreloil' => '{{PLURAL:$1|barrel|barrel}}', |
| 188 | + 'pfunc-convert-unit-volume-barrelbeer' => '{{PLURAL:$1|barrel|barrel}}', |
| 189 | + 'pfunc-convert-unit-volume-usgallon' => '{{PLURAL:$1|US gallon|US gallons}}', |
| 190 | + 'pfunc-convert-unit-volume-usquart' => '{{PLURAL:$1|US quart|US quarts}}', |
| 191 | + 'pfunc-convert-unit-volume-uspint' => '{{PLURAL:$1|US pint|US pints}}', |
| 192 | + 'pfunc-convert-unit-volume-usfluidounce' => '{{PLURAL:$1|US fluid ounce|US fluid ounces}}', |
| 193 | + 'pfunc-convert-unit-volume-usdrybarrel' => '{{PLURAL:$1|US dry barrel|US dry barrels}}', |
| 194 | + 'pfunc-convert-unit-volume-usbushel' => '{{PLURAL:$1|US bushel|US bushels}}', |
| 195 | + 'pfunc-convert-unit-volume-usdrygallon' => '{{PLURAL:$1|US dry gallon|US dry gallons}}', |
| 196 | + 'pfunc-convert-unit-volume-usdryquart' => '{{PLURAL:$1|US dry quart|US dry quarts}}', |
| 197 | + 'pfunc-convert-unit-volume-usdrypint' => '{{PLURAL:$1|US dry pint|US dry pints}}', |
| 198 | + |
| 199 | + 'pfunc-convert-unit-volume-cubicmetre-abbr' => 'm<sup>3</sup>', |
| 200 | + 'pfunc-convert-unit-volume-cubiccentimetre-abbr' => 'cm<sup>3</sup>', |
| 201 | + 'pfunc-convert-unit-volume-cubicmillimetre-abbr' => 'mm<sup>3</sup>', |
| 202 | + 'pfunc-convert-unit-volume-kilolitre-abbr' => 'kl', |
| 203 | + 'pfunc-convert-unit-volume-litre-abbr' => 'l', |
| 204 | + 'pfunc-convert-unit-volume-centilitre-abbr' => 'cl', |
| 205 | + 'pfunc-convert-unit-volume-millilitre-abbr' => 'ml', |
| 206 | + 'pfunc-convert-unit-volume-cubicyard-abbr' => 'cu yd', |
| 207 | + 'pfunc-convert-unit-volume-cubicfoot-abbr' => 'cu ft', |
| 208 | + 'pfunc-convert-unit-volume-cubicinch-abbr' => 'cu in', |
| 209 | + 'pfunc-convert-unit-volume-barrel-abbr' => 'bbl', |
| 210 | + 'pfunc-convert-unit-volume-bushel-abbr' => 'bsh', |
| 211 | + 'pfunc-convert-unit-volume-gallon-abbr' => 'gal', |
| 212 | + 'pfunc-convert-unit-volume-quart-abbr' => 'qt', |
| 213 | + 'pfunc-convert-unit-volume-pint-abbr' => 'pt', |
| 214 | + 'pfunc-convert-unit-volume-fluidounce-abbr' => 'fl oz', |
| 215 | + 'pfunc-convert-unit-volume-barrelus-abbr' => 'US bbl', |
| 216 | + 'pfunc-convert-unit-volume-barreloil-abbr' => 'bbl', |
| 217 | + 'pfunc-convert-unit-volume-barrelbeer-abbr' => 'bbl', |
| 218 | + 'pfunc-convert-unit-volume-usgallon-abbr' => 'US gal', |
| 219 | + 'pfunc-convert-unit-volume-usquart-abbr' => 'US qt', |
| 220 | + 'pfunc-convert-unit-volume-uspint-abbr' => 'US pt', |
| 221 | + 'pfunc-convert-unit-volume-usfluidounce-abbr' => 'US fl oz', |
| 222 | + 'pfunc-convert-unit-volume-usdrybarrel-abbr' => 'US bbl', |
| 223 | + 'pfunc-convert-unit-volume-usbushel-abbr' => 'US bsh', |
| 224 | + 'pfunc-convert-unit-volume-usdrygallon-abbr' => 'US dry gal', |
| 225 | + 'pfunc-convert-unit-volume-usdryquart-abbr' => 'US dry qt', |
| 226 | + 'pfunc-convert-unit-volume-usdrypint-abbr' => 'US dry pt', |
| 227 | + |
| 228 | + # SPEED |
| 229 | + 'pfunc-convert-unit-speed-mile-hour' => 'miles per hour', |
| 230 | + 'pfunc-convert-unit-speed-speedoflight' => 'c', |
| 231 | + |
| 232 | + 'pfunc-convert-unit-speed-mile-hour-abbr' => 'mph', |
| 233 | + 'pfunc-convert-unit-speed-speedoflight-abbr' => 'c', |
| 234 | + |
| 235 | + # PRESSURE |
| 236 | + 'pfunc-convert-unit-pressure-gigapascal' => '{{PLURAL:$1|gigapascal|gigapascals}}', |
| 237 | + 'pfunc-convert-unit-pressure-megapascal' => '{{PLURAL:$1|megapascal|megapascals}}', |
| 238 | + 'pfunc-convert-unit-pressure-kilopascal' => '{{PLURAL:$1|kilopascal|kilopascals}}', |
| 239 | + 'pfunc-convert-unit-pressure-hectopascal' => '{{PLURAL:$1|hectopascal|hectopascals}}', |
| 240 | + 'pfunc-convert-unit-pressure-pascal' => '{{PLURAL:$1|pascal|pascals}}', |
| 241 | + 'pfunc-convert-unit-pressure-millipascal' => '{{PLURAL:$1|millipascal|millipascals}}', |
| 242 | + 'pfunc-convert-unit-pressure-bar' => 'bar', |
| 243 | + 'pfunc-convert-unit-pressure-decibar' => 'decibar', |
| 244 | + 'pfunc-convert-unit-pressure-millibar' => 'millibar', |
| 245 | + 'pfunc-convert-unit-pressure-kilobarye' => 'kilobarye', |
| 246 | + 'pfunc-convert-unit-pressure-barye' => 'barye', |
| 247 | + 'pfunc-convert-unit-pressure-atmosphere' => '{{PLURAL:$1|atmosphere|atmospheres}}', |
| 248 | + 'pfunc-convert-unit-pressure-torr' => '{{PLURAL:$1|Torr|Torr}}', |
| 249 | + 'pfunc-convert-unit-pressure-mmhg' => '{{PLURAL:$1|milimetre of mercury|milimetres of mercury}}', |
| 250 | + 'pfunc-convert-unit-pressure-inhg' => '{{PLURAL:$1|inch of mercury|inches of mercury}}', |
| 251 | + 'pfunc-convert-unit-pressure-psi' => '{{PLURAL:$1|pound per square-inch|pounds per square-inch}}', |
| 252 | + |
| 253 | + 'pfunc-convert-unit-pressure-gigapascal-abbr' => 'GPa', |
| 254 | + 'pfunc-convert-unit-pressure-megapascal-abbr' => 'MPa', |
| 255 | + 'pfunc-convert-unit-pressure-kilopascal-abbr' => 'kPa', |
| 256 | + 'pfunc-convert-unit-pressure-hectopascal-abbr' => 'hPa', |
| 257 | + 'pfunc-convert-unit-pressure-pascal-abbr' => 'Pa', |
| 258 | + 'pfunc-convert-unit-pressure-millipascal-abbr' => 'mPa', |
| 259 | + 'pfunc-convert-unit-pressure-bar-abbr' => 'bar', |
| 260 | + 'pfunc-convert-unit-pressure-decibar-abbr' => 'dbar', |
| 261 | + 'pfunc-convert-unit-pressure-milibar-abbr' => 'mbar', |
| 262 | + 'pfunc-convert-unit-pressure-kilobarye-abbr' => 'kBa', |
| 263 | + 'pfunc-convert-unit-pressure-barye-abbr' => 'Ba', |
| 264 | + 'pfunc-convert-unit-pressure-atmosphere-abbr' => 'atm', |
| 265 | + 'pfunc-convert-unit-pressure-torr-abbr' => 'Torr', |
| 266 | + 'pfunc-convert-unit-pressure-mmhg-abbr' => 'mmHg', |
| 267 | + 'pfunc-convert-unit-pressure-inhg-abbr' => 'inHg', |
| 268 | + 'pfunc-convert-unit-pressure-psi-abbr' => 'psi', |
32 | 269 | ); |
33 | 270 | |
34 | 271 | /** Message documentation (Message documentation) |
Index: trunk/extensions/ParserFunctions/ParserFunctions.php |
— | — | @@ -46,6 +46,7 @@ |
47 | 47 | |
48 | 48 | $wgParserTestFiles[] = dirname( __FILE__ ) . "/funcsParserTests.txt"; |
49 | 49 | $wgParserTestFiles[] = dirname( __FILE__ ) . "/stringFunctionTests.txt"; |
| 50 | +$wgParserTestFiles[] = dirname( __FILE__ ) . "/convertTests.txt"; |
50 | 51 | |
51 | 52 | function wfSetupParserFunctions() { |
52 | 53 | global $wgPFHookStub, $wgHooks; |
— | — | @@ -89,6 +90,7 @@ |
90 | 91 | $parser->setFunctionHook( 'timel', array( &$this, 'localTime' ) ); |
91 | 92 | $parser->setFunctionHook( 'rel2abs', array( &$this, 'rel2abs' ) ); |
92 | 93 | $parser->setFunctionHook( 'titleparts', array( &$this, 'titleparts' ) ); |
| 94 | + $parser->setFunctionHook( 'convert', array( &$this, 'convert' ) ); |
93 | 95 | |
94 | 96 | // String Functions |
95 | 97 | if ( $wgPFEnableStringFunctions ) { |