Index: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValue.php |
— | — | @@ -26,30 +26,19 @@ |
27 | 27 | * @author Jeroen De Dauw |
28 | 28 | * |
29 | 29 | * @ingroup SemanticMaps |
30 | | - * |
31 | | - * TODO: this class should be integrated with Maps's handling of coordinates, as not to have redundant code. |
32 | 30 | */ |
33 | 31 | class SMGeoCoordsValue extends SMWDataValue { |
34 | 32 | |
35 | | - protected $m_N = false; // cache for localised direction labels |
36 | | - protected $m_E = false; // cache for localised direction labels |
37 | | - protected $m_W = false; // cache for localised direction labels |
38 | | - protected $m_S = false; // cache for localised direction labels |
| 33 | + protected $mCoordinateSet; |
| 34 | + protected $mWikivalue; |
39 | 35 | |
40 | | - protected $m_wikivalue; |
41 | | - protected $m_lat; // decimal latitude of current value |
42 | | - protected $m_long; // decimal longitude of current value |
43 | | - protected $m_latparts; // latitude array of four entries: degrees, minutes, seconds, direction |
44 | | - protected $m_longparts; // longitude array of four entries: degrees, minutes, seconds, direction |
45 | | - // Note: signs are used as e.g. on Google maps, i.e. S and W are negative numbers. |
46 | | - |
47 | 36 | /** |
48 | 37 | * Adds support for the geographical coordinate data type to Semantic MediaWiki. |
49 | 38 | * |
50 | 39 | * TODO: i18n keys still need to be moved |
51 | 40 | */ |
52 | | - function InitGeoCoordsType() { |
53 | | - SMWDataValueFactory::registerDatatype( '_geo', 'SMGeoCoordsValue', 'Geographic coordinate' ); |
| 41 | + public static function InitGeoCoordsType() { |
| 42 | + SMWDataValueFactory::registerDatatype( '_geo', __CLASS__, 'Geographic coordinate' ); |
54 | 43 | return true; |
55 | 44 | } |
56 | 45 | |
— | — | @@ -57,7 +46,20 @@ |
58 | 47 | * @see SMWDataValue::parseUserValue |
59 | 48 | */ |
60 | 49 | protected function parseUserValue( $value ) { |
61 | | - return $this->parseUserValueOrQuery( $value, false ); |
| 50 | + if ( $value == '' ) { |
| 51 | + $this->addError( wfMsg( 'smw_novalues' ) ); |
| 52 | + } else { |
| 53 | + $coordinates = MapsCoordinateParser::formatCoordinates( $value ); |
| 54 | + if ( $coordinates ) { |
| 55 | + $this->mCoordinateSet = $coordinates; |
| 56 | + |
| 57 | + if ( $this->m_caption === false ) { |
| 58 | + $this->m_caption = $value; |
| 59 | + } |
| 60 | + } else { |
| 61 | + $this->addError( wfMsgExt( 'maps_unrecognized_coords', array( 'parsemag' ), $value, 1 ) ); |
| 62 | + } |
| 63 | + } |
62 | 64 | } |
63 | 65 | |
64 | 66 | /** |
— | — | @@ -67,162 +69,26 @@ |
68 | 70 | * @return SMGeoCoordsValueDescription |
69 | 71 | */ |
70 | 72 | public function getQueryDescription( $value ) { |
71 | | - return $this->parseUserValueOrQuery( $value, true ); |
72 | | - } |
73 | | - |
74 | | - /** |
75 | | - * TODO: support $isQuery=true |
76 | | - */ |
77 | | - protected function parseUserValueOrQuery( $value, $isQuery ) { |
78 | | - if ( $value == '' ) { |
79 | | - $this->addError( wfMsg( 'smw_novalues' ) ); |
80 | | - return $isQuery ? new SMWThingDescription() : true; |
81 | | - } |
82 | | - |
83 | | - $this->m_lat = false; |
84 | | - $this->m_long = false; |
85 | | - $this->m_latparts = false; |
86 | | - $this->m_longparts = false; |
87 | | - $this->m_wikivalue = $value; |
88 | | - |
89 | | - // Normalize the notation. |
90 | | - $this->initDirectionLabels(); |
91 | | - $value = str_replace( array( ' ', $this->m_N, $this->m_E, $this->m_W, $this->m_S, ), |
92 | | - array( ' ', 'N', 'E', 'W', 'S' ), $value ); |
93 | | - $value = str_replace( array( '°', '°' ), '°', $value ); |
94 | | - $value = str_replace( array( '´', '´' ), '´', $value ); |
95 | | - $value = str_replace( array( '″', '″', "''", '"', '´´', SM_GEO_MIN . SM_GEO_MIN ), SM_GEO_SEC, $value ); |
96 | | - $value = str_replace( array( '′', '′', "'", '´' ), SM_GEO_MIN, $value ); |
97 | | - |
98 | | - // Split the value string. |
99 | | - $parts = preg_split( |
100 | | - '/\s*(°|' . SM_GEO_MIN . '|' . SM_GEO_SEC . '|N|E|W|S|;)\s*/u', |
101 | | - str_replace( ', ', ';', $value ) . ';', |
102 | | - - 1, |
103 | | - PREG_SPLIT_DELIM_CAPTURE |
104 | | - ); |
105 | | - $curnum = false; |
106 | | - $angles = array( false, false, false ); // Temporary values for deg, min, sec |
107 | | - |
108 | | - foreach ( $parts as $part ) { |
109 | | - switch ( $part ) { |
110 | | - case '°': |
111 | | - if ( ( $angles[0] !== false ) && ( $this->m_lat === false ) ) { // work off values found earlier |
112 | | - $this->setAngleValues( 'N', $angles ); |
113 | | - } // else: we do not accept interchange of order (lat must be first), so there are just too many °s |
114 | | - if ( $curnum !== false ) { |
115 | | - $angles[0] = $curnum; |
116 | | - $curnum = false; |
117 | | - } else { |
118 | | - $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) ); |
119 | | - } |
120 | | - break; |
121 | | - case SM_GEO_MIN: |
122 | | - if ( ( $curnum !== false ) && ( $angles[1] === false ) ) { |
123 | | - $angles[1] = $curnum; |
124 | | - if ( $angles[0] === false ) $angles[0] = 0; |
125 | | - $curnum = false; |
126 | | - } else { |
127 | | - $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) ); |
128 | | - } |
129 | | - break; |
130 | | - case SM_GEO_SEC: |
131 | | - if ( ( $curnum !== false ) && ( $angles[2] === false ) ) { |
132 | | - $angles[2] = $curnum; |
133 | | - if ( $angles[0] === false ) $angles[0] = 0; |
134 | | - if ( $angles[1] === false ) $angles[1] = 0; |
135 | | - $curnum = false; |
136 | | - } else { |
137 | | - $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) ); |
138 | | - } |
139 | | - break; |
140 | | - case 'N': case 'S': // interpret findings as latitude |
141 | | - if ( $curnum !== false ) { // work off number without ° |
142 | | - if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain |
143 | | - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) ); |
144 | | - break; |
145 | | - } else { |
146 | | - $angles[0] = $curnum; |
147 | | - $curnum = false; |
148 | | - } |
149 | | - } |
150 | | - if ( ( $this->m_lat === false ) && ( $angles[0] !== false ) ) { |
151 | | - $this->setAngleValues( $part, $angles ); |
152 | | - } else { |
153 | | - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) ); |
154 | | - } |
155 | | - break; |
156 | | - case 'E': case 'W': // interpret findings as longitude |
157 | | - if ( $curnum !== false ) { // work off number without ° |
158 | | - if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain |
159 | | - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) ); |
160 | | - break; |
161 | | - } else { |
162 | | - $angles[0] = $curnum; |
163 | | - $curnum = false; |
164 | | - } |
165 | | - } |
166 | | - if ( ( $this->m_long === false ) && ( $angles[0] !== false ) ) { |
167 | | - $this->setAngleValues( $part, $angles ); |
168 | | - } else { |
169 | | - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) ); |
170 | | - } |
171 | | - break; |
172 | | - case ';': // interpret findings as latitude |
173 | | - if ( $curnum !== false ) { // work off number without ° |
174 | | - if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain |
175 | | - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) ); |
176 | | - break; |
177 | | - } else { |
178 | | - $angles[0] = $curnum; |
179 | | - $curnum = false; |
180 | | - } |
181 | | - } |
182 | | - if ( ( $this->m_lat === false ) && ( $angles[0] !== false ) ) { |
183 | | - $this->setAngleValues( 'N', $angles ); |
184 | | - } // else: ignore ";" without complaining |
185 | | - break; |
186 | | - case '': break; // ignore |
187 | | - default: // should be a number (if not, errors appear elsewhere) |
188 | | - // no kiloseps in coordinates, use as decsep as a convenience to some users (Bug 11808): |
189 | | - $curnum = str_replace( wfMsgForContent( 'smw_kiloseparator' ), wfMsgForContent( 'smw_decseparator' ), $part ); |
190 | | - break; |
191 | | - } |
192 | | - } |
193 | | - |
194 | | - if ( ( $this->m_lat !== false ) && ( $this->m_long === false ) && ( $angles[0] !== false ) ) { // no final E or W? |
195 | | - $this->setAngleValues( 'E', $angles ); |
196 | | - } |
197 | | - |
198 | | - if ( ( $angles[0] !== false ) || ( $curnum !== false ) ) { // unprocessed chunk, error |
199 | | - |
200 | | - } |
201 | | - |
202 | | - if ( $this->m_caption === false ) { |
203 | | - $this->m_caption = $value; |
204 | | - } |
205 | | - |
206 | | - if ( $isQuery ) { |
207 | | - return new SMGeoCoordsValueDescription( ); // TODO |
208 | | - } else { |
209 | | - return true; |
210 | | - } |
| 73 | + // TODO |
211 | 74 | } |
212 | 75 | |
213 | 76 | /** |
214 | 77 | * @see SMWDataValue::parseDBkeys |
215 | 78 | */ |
216 | 79 | protected function parseDBkeys( $args ) { |
217 | | - $this->m_lat = false; |
218 | | - $this->m_long = false; |
219 | | - $this->m_latparts = false; |
220 | | - $this->m_longparts = false; |
221 | | - |
222 | | - list( $this->m_lat, $this->m_long ) = explode( ',', $args[0] ); |
| 80 | + list( $this->mCoordinateSet['lat'], $this->mCoordinateSet['lon'] ) = explode( ',', $args[0] ); |
223 | 81 | |
224 | | - $this->m_caption = $this->formatAngleValues( true ) . ', ' . $this->formatAngleValues( false ); // this is our output text |
225 | | - $this->m_wikivalue = $this->m_caption; |
| 82 | + $this->m_caption = $this->mCoordinateSet['lat'] . ', ' . $this->mCoordinateSet['lon']; |
| 83 | + $this->mWikivalue = $this->m_caption; |
226 | 84 | } |
| 85 | + |
| 86 | + /** |
| 87 | + * @see SMWDataValue::getDBkeys |
| 88 | + */ |
| 89 | + public function getDBkeys() { |
| 90 | + $this->unstub(); |
| 91 | + return array( $this->mCoordinateSet['lat'] . ',' . $this->mCoordinateSet['lon'] ); |
| 92 | + } |
227 | 93 | |
228 | 94 | /** |
229 | 95 | * @see SMWDataValue::getShortWikiText |
— | — | @@ -231,8 +97,8 @@ |
232 | 98 | if ( $this->isValid() && ( $linked !== null ) && ( $linked !== false ) ) { |
233 | 99 | SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP ); |
234 | 100 | return '<span class="smwttinline">' . $this->m_caption . '<span class="smwttcontent">' . |
235 | | - wfMsgForContent( 'semanticmaps_label_latitude' ) . ' ' . $this->formatAngleValues( true ) . '<br />' . |
236 | | - wfMsgForContent( 'semanticmaps_label_longitude' ) . ' ' . $this->formatAngleValues( false ) . |
| 101 | + wfMsgForContent( 'maps-latitude' ) . ' ' . $this->mCoordinateSet['lat'] . '<br />' . |
| 102 | + wfMsgForContent( 'maps-longitude' ) . ' ' . $this->mCoordinateSet['lon'] . |
237 | 103 | '</span></span>'; |
238 | 104 | } else { |
239 | 105 | return $this->m_caption; |
— | — | @@ -243,7 +109,8 @@ |
244 | 110 | * @see SMWDataValue::getShortHTMLText |
245 | 111 | */ |
246 | 112 | public function getShortHTMLText( $linker = null ) { |
247 | | - return $this->getShortWikiText( $linker ); // should be save (based on xsdvalue) |
| 113 | + // TODO: parse to HTML? |
| 114 | + return $this->getShortWikiText( $linker ); |
248 | 115 | } |
249 | 116 | |
250 | 117 | /** |
— | — | @@ -253,7 +120,7 @@ |
254 | 121 | if ( !$this->isValid() ) { |
255 | 122 | return $this->getErrorText(); |
256 | 123 | } else { |
257 | | - return $this->formatAngleValues( true ) . ', ' . $this->formatAngleValues( false ); |
| 124 | + return $this->mCoordinateSet['lat'] . ', ' . $this->mCoordinateSet['lon']; |
258 | 125 | } |
259 | 126 | } |
260 | 127 | |
— | — | @@ -261,23 +128,16 @@ |
262 | 129 | * @see SMWDataValue::getLongHTMLText |
263 | 130 | */ |
264 | 131 | public function getLongHTMLText( $linker = null ) { |
| 132 | + // TODO: parse to HTML? |
265 | 133 | return $this->getLongWikiText( $linker ); |
266 | 134 | } |
267 | 135 | |
268 | 136 | /** |
269 | | - * @see SMWDataValue::getDBkeys |
270 | | - */ |
271 | | - public function getDBkeys() { |
272 | | - $this->unstub(); |
273 | | - return array( $this->m_lat . ',' . $this->m_long ); |
274 | | - } |
275 | | - |
276 | | - /** |
277 | 137 | * @see SMWDataValue::getWikiValue |
278 | 138 | */ |
279 | 139 | public function getWikiValue() { |
280 | 140 | $this->unstub(); |
281 | | - return $this->m_wikivalue; |
| 141 | + return $this->mWikivalue; |
282 | 142 | } |
283 | 143 | |
284 | 144 | /** |
— | — | @@ -293,136 +153,13 @@ |
294 | 154 | } |
295 | 155 | |
296 | 156 | /** |
297 | | - * Get and cache localised direction labels. Just for convenience. |
298 | | - */ |
299 | | - protected function initDirectionLabels() { |
300 | | - $this->m_N = wfMsgForContent( 'semanticmaps_abb_north' ); |
301 | | - $this->m_E = wfMsgForContent( 'semanticmaps_abb_east' ); |
302 | | - $this->m_W = wfMsgForContent( 'semanticmaps_abb_west' ); |
303 | | - $this->m_S = wfMsgForContent( 'semanticmaps_abb_south' ); |
304 | | - } |
305 | | - |
306 | | - /** |
307 | | - * Helper function: read a possibly incomplete array of angles for one coordinate. |
308 | | - * The direction is one of N, E, W, S, and $angles is an array of three values, |
309 | | - * each possibly false if unset. |
310 | | - */ |
311 | | - protected function setAngleValues( $direction, &$angles ) { |
312 | | - $numvalue = SMWDataValueFactory::newTypeIDValue( '_num' ); |
313 | | - $res = 0; |
314 | | - $factor = 1; |
315 | | - |
316 | | - for ( $i = 0; $i < 3; $i++ ) { |
317 | | - if ( $angles[$i] !== false ) { |
318 | | - $numvalue->setUserValue( $angles[$i] ); |
319 | | - if ( $numvalue->isValid() && ( $numvalue->getUnit() == '' ) ) { |
320 | | - $res += $numvalue->getNumericValue() / $factor; |
321 | | - } else { |
322 | | - $this->addError( wfMsgForContent( 'smw_nofloat', $angles[$i] ) ); |
323 | | - } |
324 | | - } |
325 | | - $factor = $factor * 60; |
326 | | - } |
327 | | - |
328 | | - switch ( $direction ) { |
329 | | - case 'N': $this->m_lat = $res; break; |
330 | | - case 'S': $this->m_lat = - 1 * $res; break; |
331 | | - case 'E': $this->m_long = $res; break; |
332 | | - case 'W': $this->m_long = - 1 * $res; break; |
333 | | - } |
334 | | - |
335 | | - if ( ( ( $direction == 'E' ) || ( $direction == 'W' ) ) && |
336 | | - ( ( $this->m_long > 180 ) || ( $this->m_long <= - 180 ) ) ) { // bring values back into [180, -180) |
337 | | - $this->m_long += ( $this->m_long < 0 ) ? ( round( abs( $this->m_long ) / 360 ) * 360 ):( round( $this->m_long / 360 ) * - 360 ); |
338 | | - } |
339 | | - // TODO: also make such a normalisation for lat ... |
340 | | - |
341 | | - $angles = array( false, false, false ); |
342 | | - } |
343 | | - |
344 | | - /** |
345 | | - * Return array with four entries for deg, min, sec, direction, |
346 | | - * that corresponds to the current latitude or longitude. |
347 | | - * |
348 | | - * @param Boolean $lat When true, latitude will be used, otherwise longitude will be. |
349 | | - */ |
350 | | - protected function getAngleValues( $lat = true ) { |
351 | | - if ( $lat ) { |
352 | | - if ( $this->m_latparts !== false ) { |
353 | | - return $this->m_latparts; |
354 | | - } |
355 | | - $num = abs( $this->m_lat ); |
356 | | - $d = ( $this->m_lat < 0 ) ? 'S':'N'; |
357 | | - } else { |
358 | | - if ( $this->m_longparts !== false ) { |
359 | | - return $this->m_longparts; |
360 | | - } |
361 | | - $num = abs( $this->m_long ); |
362 | | - $d = ( $this->m_long < 0 ) ? 'W':'E'; |
363 | | - } |
364 | | - $result = array( 0, 0, 0, $d ); |
365 | | - $result[0] = floor( $num ); |
366 | | - $num = ( $num - $result[0] ) * 60; |
367 | | - $result[1] = floor( $num ); |
368 | | - $result[2] = ( $num - $result[1] ) * 60; |
369 | | - if ( abs( $result[2] ) < 0.001 ) { // limit precission, avoid conversion generated junk and EXP notation in coords |
370 | | - $result[2] = 0; |
371 | | - } |
372 | | - if ( $lat ) { |
373 | | - $this->m_latparts = $result; |
374 | | - } else { |
375 | | - $this->m_longparts = $result; |
376 | | - } |
377 | | - return $result; |
378 | | - } |
379 | | - |
380 | | - /** |
381 | | - * Format the current latitude or longitude. The parameter $content states |
382 | | - * whether the result is for content printout. Alternatively, a language- |
383 | | - * independent result is generated. |
384 | | - * |
385 | | - * @param Boolean $lat When true, latitude will be used, otherwise longitude will be. |
386 | | - * @param Boolean $content |
387 | | - */ |
388 | | - protected function formatAngleValues( $lat = true, $content = true ) { |
389 | | - $values = $this->getAngleValues( $lat ); |
390 | | - |
391 | | - if ( $content ) { |
392 | | - $this->initDirectionLabels(); |
393 | | - $result = smwfNumberFormat( $values[0] ) . '°' . smwfNumberFormat( $values[1] ) . SM_GEO_MIN . |
394 | | - smwfNumberFormat( $values[2] ) . SM_GEO_SEC; |
395 | | - switch ( $values[3] ) { |
396 | | - case 'N': return $result . $this->m_N; |
397 | | - case 'E': return $result . $this->m_E; |
398 | | - case 'W': return $result . $this->m_W; |
399 | | - case 'S': return $result . $this->m_S; |
400 | | - } |
401 | | - } else { |
402 | | - return smwfNumberFormat( $values[0] ) . '°' . smwfNumberFormat( $values[1] ) . SM_GEO_MIN . |
403 | | - smwfNumberFormat( $values[2] ) . SM_GEO_SEC . $values[3]; |
404 | | - } |
405 | | - } |
406 | | - |
407 | | - /** |
408 | 157 | * Create links to mapping services based on a wiki-editable message. The parameters |
409 | 158 | * available to the message are: |
410 | 159 | * |
411 | | - * $1: latitude integer degrees, $2: longitude integer degrees |
412 | | - * $3: latitude integer minutes, $4: longitude integer minutes |
413 | | - * $5: latitude integer seconds, $6: longitude integer seconds, |
414 | | - * $7: latitude direction string (N or S), $8: longitude direction string (W or E) |
415 | | - * $9: latitude in decimal degrees, $10: longitude in decimal degrees |
416 | | - * $11: sign (- if south) for latitude, $12: sign (- if west) for longitude |
| 160 | + * |
417 | 161 | */ |
418 | 162 | protected function getServiceLinkParams() { |
419 | | - $latvals = $this->getAngleValues( true ); |
420 | | - $longvals = $this->getAngleValues( false ); |
421 | | - return array( $latvals[0], $longvals[0], |
422 | | - $latvals[1], $longvals[1], |
423 | | - round( $latvals[2] ), round( $longvals[2] ), |
424 | | - $latvals[3], $longvals[3], |
425 | | - abs( $this->m_lat ), abs( $this->m_long ), |
426 | | - $latvals[3] == 'S' ? '-':'', $longvals[3] == 'W' ? '-':'' ); |
| 163 | + return array( ); // TODO |
427 | 164 | } |
428 | 165 | |
429 | 166 | } |
Index: trunk/extensions/SemanticMaps/SemanticMaps.i18n.php |
— | — | @@ -21,16 +21,6 @@ |
22 | 22 | 'semanticmaps_desc' => "Provides the ability to view and edit coordinate data stored through the Semantic MediaWiki extension ([http://wiki.bn2vs.com/wiki/Semantic_Maps demo]). |
23 | 23 | Available map services: $1", |
24 | 24 | |
25 | | - // Geo coord data type |
26 | | - 'semanticmaps_lonely_unit' => 'No number found before the symbol "$1".', // $1 is something like ° |
27 | | - 'semanticmaps_bad_latlong' => 'Latitude and longitude must be given only once, and with valid coordinates.', |
28 | | - 'semanticmaps_abb_north' => 'N', |
29 | | - 'semanticmaps_abb_east' => 'E', |
30 | | - 'semanticmaps_abb_south' => 'S', |
31 | | - 'semanticmaps_abb_west' => 'W', |
32 | | - 'semanticmaps_label_latitude' => 'Latitude:', |
33 | | - 'semanticmaps_label_longitude' => 'Longitude:', |
34 | | - |
35 | 25 | // Forms |
36 | 26 | 'semanticmaps_lookupcoordinates' => 'Look up coordinates', |
37 | 27 | 'semanticmaps_enteraddresshere' => 'Enter address here', |