r63845 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r63844‎ | r63845 | r63846 >
Date:23:24, 16 March 2010
Author:jeroendedauw
Status:deferred
Tags:
Comment:
Restructured geocoords support.
* Moved proximity query from SMW to SM
Modified paths:
  • /trunk/extensions/SemanticMaps/GeoCoords (added) (history)
  • /trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoords.php (added) (history)
  • /trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValue.php (added) (history)
  • /trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValueDescription.php (added) (history)
  • /trunk/extensions/SemanticMaps/SM_GeoCoordsValue.php (deleted) (history)
  • /trunk/extensions/SemanticMaps/SM_Settings.php (modified) (history)
  • /trunk/extensions/SemanticMaps/SemanticMaps.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMaps/SM_GeoCoordsValue.php
@@ -1,335 +0,0 @@
2 -<?php
3 -/**
4 - * File holding the SMGeoCoordsValue class.
5 - *
6 - * @file SM_GeoCoordsValue.php
7 - * @ingroup SMWDataValues
8 - *
9 - * @author Markus Krötzsch
10 - * @author Jeroen De Dauw
11 - */
12 -
13 -// / Unicode symbols for coordinate minutes and seconds;
14 -// / may not display in every font ...
15 -define( 'SM_GEO_MIN', '′' );
16 -define( 'SM_GEO_SEC', '″' );
17 -
18 -/**
19 - * Implementation of datavalues that are geographic coordinates.
20 - *
21 - * @author Markus Krötzsch
22 - * @author Jeroen De Dauw
23 - *
24 - * @ingroup SemanticMaps
25 - */
26 -class SMGeoCoordsValue extends SMWDataValue {
27 -
28 - protected $m_N = false; // cache for localised direction labels
29 - protected $m_E = false; // cache for localised direction labels
30 - protected $m_W = false; // cache for localised direction labels
31 - protected $m_S = false; // cache for localised direction labels
32 -
33 - protected $m_wikivalue;
34 - protected $m_lat; // decimal latitude of current value
35 - protected $m_long; // decimal longitude of current value
36 - protected $m_latparts; // latitude array of four entries: degrees, minutes, seconds, direction
37 - protected $m_longparts; // longitude array of four entries: degrees, minutes, seconds, direction
38 - // Note: signs are used as e.g. on Google maps, i.e. S and W are negative numbers.
39 -
40 - protected function parseUserValue( $value ) {
41 - $this->m_lat = false;
42 - $this->m_long = false;
43 - $this->m_latparts = false;
44 - $this->m_longparts = false;
45 - $this->m_wikivalue = $value;
46 -
47 - // first normalise some typical symbols
48 - $this->initDirectionLabels();
49 - $value = str_replace( array( '&nbsp;', $this->m_N, $this->m_E, $this->m_W, $this->m_S, ),
50 - array( ' ', 'N', 'E', 'W', 'S' ), $value );
51 - $value = str_replace( array( '&#176;', '&deg;' ), '°', $value );
52 - $value = str_replace( array( '&acute;', '&#180;' ), '´', $value );
53 - $value = str_replace( array( '&#8243;', '&Prime;', "''", '"', '´´', SM_GEO_MIN . SM_GEO_MIN ), SM_GEO_SEC, $value );
54 - $value = str_replace( array( '&#8242;', '&prime;', "'", '´' ), SM_GEO_MIN, $value );
55 - // now split the string
56 - $parts = preg_split( '/\s*(°|' . SM_GEO_MIN . '|' . SM_GEO_SEC . '|N|E|W|S|;)\s*/u', str_replace( ', ', ';', $value ) . ';', - 1, PREG_SPLIT_DELIM_CAPTURE );
57 - $curnum = false;
58 - $angles = array( false, false, false ); // temporary values for deg, min, sec
59 - foreach ( $parts as $part ) {
60 - switch ( $part ) {
61 - case '°':
62 - if ( ( $angles[0] !== false ) && ( $this->m_lat === false ) ) { // work off values found earlier
63 - $this->setAngleValues( 'N', $angles );
64 - } // else: we do not accept interchange of order (lat must be first), so there are just too many °s
65 - if ( $curnum !== false ) {
66 - $angles[0] = $curnum;
67 - $curnum = false;
68 - } else {
69 - $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) );
70 - }
71 - break;
72 - case SM_GEO_MIN:
73 - if ( ( $curnum !== false ) && ( $angles[1] === false ) ) {
74 - $angles[1] = $curnum;
75 - if ( $angles[0] === false ) $angles[0] = 0;
76 - $curnum = false;
77 - } else {
78 - $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) );
79 - }
80 - break;
81 - case SM_GEO_SEC:
82 - if ( ( $curnum !== false ) && ( $angles[2] === false ) ) {
83 - $angles[2] = $curnum;
84 - if ( $angles[0] === false ) $angles[0] = 0;
85 - if ( $angles[1] === false ) $angles[1] = 0;
86 - $curnum = false;
87 - } else {
88 - $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) );
89 - }
90 - break;
91 - case 'N': case 'S': // interpret findings as latitude
92 - if ( $curnum !== false ) { // work off number without °
93 - if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain
94 - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
95 - break;
96 - } else {
97 - $angles[0] = $curnum;
98 - $curnum = false;
99 - }
100 - }
101 - if ( ( $this->m_lat === false ) && ( $angles[0] !== false ) ) {
102 - $this->setAngleValues( $part, $angles );
103 - } else {
104 - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
105 - }
106 - break;
107 - case 'E': case 'W': // interpret findings as longitude
108 - if ( $curnum !== false ) { // work off number without °
109 - if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain
110 - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
111 - break;
112 - } else {
113 - $angles[0] = $curnum;
114 - $curnum = false;
115 - }
116 - }
117 - if ( ( $this->m_long === false ) && ( $angles[0] !== false ) ) {
118 - $this->setAngleValues( $part, $angles );
119 - } else {
120 - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
121 - }
122 - break;
123 - case ';': // interpret findings as latitude
124 - if ( $curnum !== false ) { // work off number without °
125 - if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain
126 - $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
127 - break;
128 - } else {
129 - $angles[0] = $curnum;
130 - $curnum = false;
131 - }
132 - }
133 - if ( ( $this->m_lat === false ) && ( $angles[0] !== false ) ) {
134 - $this->setAngleValues( 'N', $angles );
135 - } // else: ignore ";" without complaining
136 - break;
137 - case '': break; // ignore
138 - default: // should be a number (if not, errors appear elsewhere)
139 - // no kiloseps in coordinates, use as decsep as a convenience to some users (Bug 11808):
140 - $curnum = str_replace( wfMsgForContent( 'smw_kiloseparator' ), wfMsgForContent( 'smw_decseparator' ), $part );
141 - break;
142 - }
143 - }
144 -
145 - if ( ( $this->m_lat !== false ) && ( $this->m_long === false ) && ( $angles[0] !== false ) ) { // no final E or W?
146 - $this->setAngleValues( 'E', $angles );
147 - }
148 - if ( ( $angles[0] !== false ) || ( $curnum !== false ) ) { // unprocessed chunk, error
149 -
150 - }
151 -
152 - if ( $this->m_caption === false ) {
153 - $this->m_caption = $value;
154 - }
155 - return true;
156 - }
157 -
158 - protected function parseDBkeys( $args ) {
159 - $this->m_lat = false;
160 - $this->m_long = false;
161 - $this->m_latparts = false;
162 - $this->m_longparts = false;
163 -
164 - list( $this->m_lat, $this->m_long ) = explode( ',', $args[0] );
165 - $this->m_caption = $this->formatAngleValues( true ) . ', ' . $this->formatAngleValues( false ); // this is our output text
166 - $this->m_wikivalue = $this->m_caption;
167 - }
168 -
169 - public function getShortWikiText( $linked = null ) {
170 - if ( $this->isValid() && ( $linked !== null ) && ( $linked !== false ) ) {
171 - SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
172 - return '<span class="smwttinline">' . $this->m_caption . '<span class="smwttcontent">' .
173 - wfMsgForContent( 'semanticmaps_label_latitude' ) . ' ' . $this->formatAngleValues( true ) . '<br />' .
174 - wfMsgForContent( 'semanticmaps_label_longitude' ) . ' ' . $this->formatAngleValues( false ) .
175 - '</span></span>';
176 - } else {
177 - return $this->m_caption;
178 - }
179 - }
180 -
181 - public function getShortHTMLText( $linker = null ) {
182 - return $this->getShortWikiText( $linker ); // should be save (based on xsdvalue)
183 - }
184 -
185 - public function getLongWikiText( $linked = null ) {
186 - if ( !$this->isValid() ) {
187 - return $this->getErrorText();
188 - } else {
189 - return $this->formatAngleValues( true ) . ', ' . $this->formatAngleValues( false );
190 - }
191 - }
192 -
193 - public function getLongHTMLText( $linker = null ) {
194 - return $this->getLongWikiText( $linker );
195 - }
196 -
197 - public function getDBkeys() {
198 - $this->unstub();
199 - return array( $this->m_lat . ',' . $this->m_long );
200 - }
201 -
202 - public function getWikiValue() {
203 - $this->unstub();
204 - return $this->m_wikivalue;
205 - }
206 -
207 - public function getExportData() {
208 - if ( $this->isValid() ) {
209 - $lit = new SMWExpLiteral( $this->formatAngleValues( true, false ) . ', ' . $this->formatAngleValues( false, false ), $this, 'http://www.w3.org/2001/XMLSchema#string' );
210 - return new SMWExpData( $lit );
211 - } else {
212 - return null;
213 - }
214 - }
215 -
216 - /**
217 - * Get and cache localised direction labels. Just for convenience.
218 - */
219 - protected function initDirectionLabels() {
220 - $this->m_N = wfMsgForContent( 'semanticmaps_abb_north' );
221 - $this->m_E = wfMsgForContent( 'semanticmaps_abb_east' );
222 - $this->m_W = wfMsgForContent( 'semanticmaps_abb_west' );
223 - $this->m_S = wfMsgForContent( 'semanticmaps_abb_south' );
224 - }
225 -
226 - /**
227 - * Helper function: read a possibly incomplete array of angles for one coordinate.
228 - * The direction is one of N, E, W, S, and $angles is an array of three values,
229 - * each possibly false if unset.
230 - */
231 - protected function setAngleValues( $direction, &$angles ) {
232 - $numvalue = SMWDataValueFactory::newTypeIDValue( '_num' );
233 - $res = 0;
234 - $factor = 1;
235 - for ( $i = 0; $i < 3; $i++ ) {
236 - if ( $angles[$i] !== false ) {
237 - $numvalue->setUserValue( $angles[$i] );
238 - if ( $numvalue->isValid() && ( $numvalue->getUnit() == '' ) ) {
239 - $res += $numvalue->getNumericValue() / $factor;
240 - } else {
241 - $this->addError( wfMsgForContent( 'smw_nofloat', $angles[$i] ) );
242 - }
243 - }
244 - $factor = $factor * 60;
245 - }
246 - switch ( $direction ) {
247 - case 'N': $this->m_lat = $res; break;
248 - case 'S': $this->m_lat = - 1 * $res; break;
249 - case 'E': $this->m_long = $res; break;
250 - case 'W': $this->m_long = - 1 * $res; break;
251 - }
252 - if ( ( ( $direction == 'E' ) || ( $direction == 'W' ) ) &&
253 - ( ( $this->m_long > 180 ) || ( $this->m_long <= - 180 ) ) ) { // bring values back into [180, -180)
254 - $this->m_long += ( $this->m_long < 0 ) ? ( round( abs( $this->m_long ) / 360 ) * 360 ):( round( $this->m_long / 360 ) * - 360 );
255 - }
256 - // /TODO: also make such a normalisation for lat ...
257 - $angles = array( false, false, false );
258 - }
259 -
260 - /**
261 - * Return array with four entries for deg, min, sec, direction,
262 - * that corresponds to the current latitude or longitude.
263 - */
264 - protected function getAngleValues( $lat = true ) {
265 - if ( $lat ) {
266 - if ( $this->m_latparts !== false ) {
267 - return $this->m_latparts;
268 - }
269 - $num = abs( $this->m_lat );
270 - $d = ( $this->m_lat < 0 ) ? 'S':'N';
271 - } else {
272 - if ( $this->m_longparts !== false ) {
273 - return $this->m_longparts;
274 - }
275 - $num = abs( $this->m_long );
276 - $d = ( $this->m_long < 0 ) ? 'W':'E';
277 - }
278 - $result = array( 0, 0, 0, $d );
279 - $result[0] = floor( $num );
280 - $num = ( $num - $result[0] ) * 60;
281 - $result[1] = floor( $num );
282 - $result[2] = ( $num - $result[1] ) * 60;
283 - if ( abs( $result[2] ) < 0.001 ) { // limit precission, avoid conversion generated junk and EXP notation in coords
284 - $result[2] = 0;
285 - }
286 - if ( $lat ) {
287 - $this->m_latparts = $result;
288 - } else {
289 - $this->m_longparts = $result;
290 - }
291 - return $result;
292 - }
293 -
294 - /**
295 - * Format the current latitude or longitude. The parameter $content states
296 - * whether the result is for content printout. Alternatively, a language-
297 - * independent result is generated.
298 - */
299 - protected function formatAngleValues( $lat = true, $content = true ) {
300 - $values = $this->getAngleValues( $lat );
301 - if ( $content ) {
302 - $this->initDirectionLabels();
303 - $result = smwfNumberFormat( $values[0] ) . '°' . smwfNumberFormat( $values[1] ) . SM_GEO_MIN .
304 - smwfNumberFormat( $values[2] ) . SM_GEO_SEC;
305 - switch ( $values[3] ) {
306 - case 'N': return $result . $this->m_N;
307 - case 'E': return $result . $this->m_E;
308 - case 'W': return $result . $this->m_W;
309 - case 'S': return $result . $this->m_S;
310 - }
311 - } else {
312 - return smwfNumberFormat( $values[0] ) . '°' . smwfNumberFormat( $values[1] ) . SM_GEO_MIN .
313 - smwfNumberFormat( $values[2] ) . SM_GEO_SEC . $values[3];
314 - }
315 - }
316 -
317 - protected function getServiceLinkParams() {
318 - // Create links to mapping services based on a wiki-editable message. The parameters
319 - // available to the message are:
320 - // $1: latitude integer degrees, $2: longitude integer degrees
321 - // $3: latitude integer minutes, $4: longitude integer minutes
322 - // $5: latitude integer seconds, $6: longitude integer seconds,
323 - // $7: latitude direction string (N or S), $8: longitude direction string (W or E)
324 - // $9: latitude in decimal degrees, $10: longitude in decimal degrees
325 - // $11: sign (- if south) for latitude, $12: sign (- if west) for longitude
326 - $latvals = $this->getAngleValues( true );
327 - $longvals = $this->getAngleValues( false );
328 - return array( $latvals[0], $longvals[0],
329 - $latvals[1], $longvals[1],
330 - round( $latvals[2] ), round( $longvals[2] ),
331 - $latvals[3], $longvals[3],
332 - abs( $this->m_lat ), abs( $this->m_long ),
333 - $latvals[3] == 'S' ? '-':'', $longvals[3] == 'W' ? '-':'' );
334 - }
335 -
336 -}
Index: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValue.php
@@ -0,0 +1,413 @@
 2+<?php
 3+/**
 4+ * File holding the SMGeoCoordsValue class.
 5+ *
 6+ * @file SM_GeoCoordsValue.php
 7+ * @ingroup SMWDataValues
 8+ * @ingroup SemanticMaps
 9+ *
 10+ * @author Markus Krötzsch
 11+ * @author Jeroen De Dauw
 12+ */
 13+
 14+if ( !defined( 'MEDIAWIKI' ) ) {
 15+ die( 'Not an entry point.' );
 16+}
 17+
 18+// / Unicode symbols for coordinate minutes and seconds;
 19+// / may not display in every font ...
 20+define( 'SM_GEO_MIN', '′' );
 21+define( 'SM_GEO_SEC', '″' );
 22+
 23+/**
 24+ * Implementation of datavalues that are geographic coordinates.
 25+ *
 26+ * @author Markus Krötzsch
 27+ * @author Jeroen De Dauw
 28+ *
 29+ * @ingroup SemanticMaps
 30+ *
 31+ * TODO: this class should be integrated with Maps's handling of coordinates, as not to have redundant code.
 32+ */
 33+class SMGeoCoordsValue extends SMWDataValue {
 34+
 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
 39+
 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+ /**
 48+ * @see SMWDataValue::parseUserValue
 49+ */
 50+ protected function parseUserValue( $value ) {
 51+ return $this->parseUserValueOrQuery( $value, false );
 52+ }
 53+
 54+ /**
 55+ * Overwrite SMWDataValue::getQueryDescription() to be able to process
 56+ * comparators between all values.
 57+ *
 58+ * @return SMGeoCoordsValueDescription
 59+ */
 60+ public function getQueryDescription( $value ) {
 61+ return $this->parseUserValueOrQuery( $value, true );
 62+ }
 63+
 64+ /**
 65+ * TODO: support $isQuery=true
 66+ */
 67+ protected function parseUserValueOrQuery( $value, $isQuery ) {
 68+ if ( $value == '' ) {
 69+ $this->addError( wfMsg( 'smw_novalues' ) );
 70+ return $isQuery ? new SMWThingDescription() : true;
 71+ }
 72+
 73+ $this->m_lat = false;
 74+ $this->m_long = false;
 75+ $this->m_latparts = false;
 76+ $this->m_longparts = false;
 77+ $this->m_wikivalue = $value;
 78+
 79+ // first normalise some typical symbols
 80+ $this->initDirectionLabels();
 81+ $value = str_replace( array( '&nbsp;', $this->m_N, $this->m_E, $this->m_W, $this->m_S, ),
 82+ array( ' ', 'N', 'E', 'W', 'S' ), $value );
 83+ $value = str_replace( array( '&#176;', '&deg;' ), '°', $value );
 84+ $value = str_replace( array( '&acute;', '&#180;' ), '´', $value );
 85+ $value = str_replace( array( '&#8243;', '&Prime;', "''", '"', '´´', SM_GEO_MIN . SM_GEO_MIN ), SM_GEO_SEC, $value );
 86+ $value = str_replace( array( '&#8242;', '&prime;', "'", '´' ), SM_GEO_MIN, $value );
 87+
 88+ // now split the string
 89+ $parts = preg_split( '/\s*(°|' . SM_GEO_MIN . '|' . SM_GEO_SEC . '|N|E|W|S|;)\s*/u', str_replace( ', ', ';', $value ) . ';', - 1, PREG_SPLIT_DELIM_CAPTURE );
 90+ $curnum = false;
 91+ $angles = array( false, false, false ); // temporary values for deg, min, sec
 92+
 93+ foreach ( $parts as $part ) {
 94+ switch ( $part ) {
 95+ case '°':
 96+ if ( ( $angles[0] !== false ) && ( $this->m_lat === false ) ) { // work off values found earlier
 97+ $this->setAngleValues( 'N', $angles );
 98+ } // else: we do not accept interchange of order (lat must be first), so there are just too many °s
 99+ if ( $curnum !== false ) {
 100+ $angles[0] = $curnum;
 101+ $curnum = false;
 102+ } else {
 103+ $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) );
 104+ }
 105+ break;
 106+ case SM_GEO_MIN:
 107+ if ( ( $curnum !== false ) && ( $angles[1] === false ) ) {
 108+ $angles[1] = $curnum;
 109+ if ( $angles[0] === false ) $angles[0] = 0;
 110+ $curnum = false;
 111+ } else {
 112+ $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) );
 113+ }
 114+ break;
 115+ case SM_GEO_SEC:
 116+ if ( ( $curnum !== false ) && ( $angles[2] === false ) ) {
 117+ $angles[2] = $curnum;
 118+ if ( $angles[0] === false ) $angles[0] = 0;
 119+ if ( $angles[1] === false ) $angles[1] = 0;
 120+ $curnum = false;
 121+ } else {
 122+ $this->addError( wfMsgForContent( 'semanticmaps_lonely_unit', $part ) );
 123+ }
 124+ break;
 125+ case 'N': case 'S': // interpret findings as latitude
 126+ if ( $curnum !== false ) { // work off number without °
 127+ if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain
 128+ $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
 129+ break;
 130+ } else {
 131+ $angles[0] = $curnum;
 132+ $curnum = false;
 133+ }
 134+ }
 135+ if ( ( $this->m_lat === false ) && ( $angles[0] !== false ) ) {
 136+ $this->setAngleValues( $part, $angles );
 137+ } else {
 138+ $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
 139+ }
 140+ break;
 141+ case 'E': case 'W': // interpret findings as longitude
 142+ if ( $curnum !== false ) { // work off number without °
 143+ if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain
 144+ $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
 145+ break;
 146+ } else {
 147+ $angles[0] = $curnum;
 148+ $curnum = false;
 149+ }
 150+ }
 151+ if ( ( $this->m_long === false ) && ( $angles[0] !== false ) ) {
 152+ $this->setAngleValues( $part, $angles );
 153+ } else {
 154+ $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
 155+ }
 156+ break;
 157+ case ';': // interpret findings as latitude
 158+ if ( $curnum !== false ) { // work off number without °
 159+ if ( $angles[0] !== false ) { // "12° 34" as coordinate, complain
 160+ $this->addError( wfMsgForContent( 'semanticmaps_bad_latlong' ) );
 161+ break;
 162+ } else {
 163+ $angles[0] = $curnum;
 164+ $curnum = false;
 165+ }
 166+ }
 167+ if ( ( $this->m_lat === false ) && ( $angles[0] !== false ) ) {
 168+ $this->setAngleValues( 'N', $angles );
 169+ } // else: ignore ";" without complaining
 170+ break;
 171+ case '': break; // ignore
 172+ default: // should be a number (if not, errors appear elsewhere)
 173+ // no kiloseps in coordinates, use as decsep as a convenience to some users (Bug 11808):
 174+ $curnum = str_replace( wfMsgForContent( 'smw_kiloseparator' ), wfMsgForContent( 'smw_decseparator' ), $part );
 175+ break;
 176+ }
 177+ }
 178+
 179+ if ( ( $this->m_lat !== false ) && ( $this->m_long === false ) && ( $angles[0] !== false ) ) { // no final E or W?
 180+ $this->setAngleValues( 'E', $angles );
 181+ }
 182+
 183+ if ( ( $angles[0] !== false ) || ( $curnum !== false ) ) { // unprocessed chunk, error
 184+
 185+ }
 186+
 187+ if ( $this->m_caption === false ) {
 188+ $this->m_caption = $value;
 189+ }
 190+
 191+ if ( $isQuery ) {
 192+ return new SMGeoCoordsValueDescription( ); // TODO
 193+ } else {
 194+ return true;
 195+ }
 196+ }
 197+
 198+ /**
 199+ * @see SMWDataValue::parseDBkeys
 200+ */
 201+ protected function parseDBkeys( $args ) {
 202+ $this->m_lat = false;
 203+ $this->m_long = false;
 204+ $this->m_latparts = false;
 205+ $this->m_longparts = false;
 206+
 207+ list( $this->m_lat, $this->m_long ) = explode( ',', $args[0] );
 208+
 209+ $this->m_caption = $this->formatAngleValues( true ) . ', ' . $this->formatAngleValues( false ); // this is our output text
 210+ $this->m_wikivalue = $this->m_caption;
 211+ }
 212+
 213+ /**
 214+ * @see SMWDataValue::getShortWikiText
 215+ */
 216+ public function getShortWikiText( $linked = null ) {
 217+ if ( $this->isValid() && ( $linked !== null ) && ( $linked !== false ) ) {
 218+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
 219+ return '<span class="smwttinline">' . $this->m_caption . '<span class="smwttcontent">' .
 220+ wfMsgForContent( 'semanticmaps_label_latitude' ) . ' ' . $this->formatAngleValues( true ) . '<br />' .
 221+ wfMsgForContent( 'semanticmaps_label_longitude' ) . ' ' . $this->formatAngleValues( false ) .
 222+ '</span></span>';
 223+ } else {
 224+ return $this->m_caption;
 225+ }
 226+ }
 227+
 228+ /**
 229+ * @see SMWDataValue::getShortHTMLText
 230+ */
 231+ public function getShortHTMLText( $linker = null ) {
 232+ return $this->getShortWikiText( $linker ); // should be save (based on xsdvalue)
 233+ }
 234+
 235+ /**
 236+ * @see SMWDataValue::getLongWikiText
 237+ */
 238+ public function getLongWikiText( $linked = null ) {
 239+ if ( !$this->isValid() ) {
 240+ return $this->getErrorText();
 241+ } else {
 242+ return $this->formatAngleValues( true ) . ', ' . $this->formatAngleValues( false );
 243+ }
 244+ }
 245+
 246+ /**
 247+ * @see SMWDataValue::getLongHTMLText
 248+ */
 249+ public function getLongHTMLText( $linker = null ) {
 250+ return $this->getLongWikiText( $linker );
 251+ }
 252+
 253+ /**
 254+ * @see SMWDataValue::getDBkeys
 255+ */
 256+ public function getDBkeys() {
 257+ $this->unstub();
 258+ return array( $this->m_lat . ',' . $this->m_long );
 259+ }
 260+
 261+ /**
 262+ * @see SMWDataValue::getWikiValue
 263+ */
 264+ public function getWikiValue() {
 265+ $this->unstub();
 266+ return $this->m_wikivalue;
 267+ }
 268+
 269+ /**
 270+ * @see SMWDataValue::getExportData
 271+ */
 272+ public function getExportData() {
 273+ if ( $this->isValid() ) {
 274+ $lit = new SMWExpLiteral( $this->formatAngleValues( true, false ) . ', ' . $this->formatAngleValues( false, false ), $this, 'http://www.w3.org/2001/XMLSchema#string' );
 275+ return new SMWExpData( $lit );
 276+ } else {
 277+ return null;
 278+ }
 279+ }
 280+
 281+ /**
 282+ * Get and cache localised direction labels. Just for convenience.
 283+ */
 284+ protected function initDirectionLabels() {
 285+ $this->m_N = wfMsgForContent( 'semanticmaps_abb_north' );
 286+ $this->m_E = wfMsgForContent( 'semanticmaps_abb_east' );
 287+ $this->m_W = wfMsgForContent( 'semanticmaps_abb_west' );
 288+ $this->m_S = wfMsgForContent( 'semanticmaps_abb_south' );
 289+ }
 290+
 291+ /**
 292+ * Helper function: read a possibly incomplete array of angles for one coordinate.
 293+ * The direction is one of N, E, W, S, and $angles is an array of three values,
 294+ * each possibly false if unset.
 295+ */
 296+ protected function setAngleValues( $direction, &$angles ) {
 297+ $numvalue = SMWDataValueFactory::newTypeIDValue( '_num' );
 298+ $res = 0;
 299+ $factor = 1;
 300+
 301+ for ( $i = 0; $i < 3; $i++ ) {
 302+ if ( $angles[$i] !== false ) {
 303+ $numvalue->setUserValue( $angles[$i] );
 304+ if ( $numvalue->isValid() && ( $numvalue->getUnit() == '' ) ) {
 305+ $res += $numvalue->getNumericValue() / $factor;
 306+ } else {
 307+ $this->addError( wfMsgForContent( 'smw_nofloat', $angles[$i] ) );
 308+ }
 309+ }
 310+ $factor = $factor * 60;
 311+ }
 312+
 313+ switch ( $direction ) {
 314+ case 'N': $this->m_lat = $res; break;
 315+ case 'S': $this->m_lat = - 1 * $res; break;
 316+ case 'E': $this->m_long = $res; break;
 317+ case 'W': $this->m_long = - 1 * $res; break;
 318+ }
 319+
 320+ if ( ( ( $direction == 'E' ) || ( $direction == 'W' ) ) &&
 321+ ( ( $this->m_long > 180 ) || ( $this->m_long <= - 180 ) ) ) { // bring values back into [180, -180)
 322+ $this->m_long += ( $this->m_long < 0 ) ? ( round( abs( $this->m_long ) / 360 ) * 360 ):( round( $this->m_long / 360 ) * - 360 );
 323+ }
 324+ // TODO: also make such a normalisation for lat ...
 325+
 326+ $angles = array( false, false, false );
 327+ }
 328+
 329+ /**
 330+ * Return array with four entries for deg, min, sec, direction,
 331+ * that corresponds to the current latitude or longitude.
 332+ *
 333+ * @param Boolean $lat When true, latitude will be used, otherwise longitude will be.
 334+ */
 335+ protected function getAngleValues( $lat = true ) {
 336+ if ( $lat ) {
 337+ if ( $this->m_latparts !== false ) {
 338+ return $this->m_latparts;
 339+ }
 340+ $num = abs( $this->m_lat );
 341+ $d = ( $this->m_lat < 0 ) ? 'S':'N';
 342+ } else {
 343+ if ( $this->m_longparts !== false ) {
 344+ return $this->m_longparts;
 345+ }
 346+ $num = abs( $this->m_long );
 347+ $d = ( $this->m_long < 0 ) ? 'W':'E';
 348+ }
 349+ $result = array( 0, 0, 0, $d );
 350+ $result[0] = floor( $num );
 351+ $num = ( $num - $result[0] ) * 60;
 352+ $result[1] = floor( $num );
 353+ $result[2] = ( $num - $result[1] ) * 60;
 354+ if ( abs( $result[2] ) < 0.001 ) { // limit precission, avoid conversion generated junk and EXP notation in coords
 355+ $result[2] = 0;
 356+ }
 357+ if ( $lat ) {
 358+ $this->m_latparts = $result;
 359+ } else {
 360+ $this->m_longparts = $result;
 361+ }
 362+ return $result;
 363+ }
 364+
 365+ /**
 366+ * Format the current latitude or longitude. The parameter $content states
 367+ * whether the result is for content printout. Alternatively, a language-
 368+ * independent result is generated.
 369+ *
 370+ * @param Boolean $lat When true, latitude will be used, otherwise longitude will be.
 371+ * @param Boolean $content
 372+ */
 373+ protected function formatAngleValues( $lat = true, $content = true ) {
 374+ $values = $this->getAngleValues( $lat );
 375+
 376+ if ( $content ) {
 377+ $this->initDirectionLabels();
 378+ $result = smwfNumberFormat( $values[0] ) . '°' . smwfNumberFormat( $values[1] ) . SM_GEO_MIN .
 379+ smwfNumberFormat( $values[2] ) . SM_GEO_SEC;
 380+ switch ( $values[3] ) {
 381+ case 'N': return $result . $this->m_N;
 382+ case 'E': return $result . $this->m_E;
 383+ case 'W': return $result . $this->m_W;
 384+ case 'S': return $result . $this->m_S;
 385+ }
 386+ } else {
 387+ return smwfNumberFormat( $values[0] ) . '°' . smwfNumberFormat( $values[1] ) . SM_GEO_MIN .
 388+ smwfNumberFormat( $values[2] ) . SM_GEO_SEC . $values[3];
 389+ }
 390+ }
 391+
 392+ /**
 393+ * Create links to mapping services based on a wiki-editable message. The parameters
 394+ * available to the message are:
 395+ *
 396+ * $1: latitude integer degrees, $2: longitude integer degrees
 397+ * $3: latitude integer minutes, $4: longitude integer minutes
 398+ * $5: latitude integer seconds, $6: longitude integer seconds,
 399+ * $7: latitude direction string (N or S), $8: longitude direction string (W or E)
 400+ * $9: latitude in decimal degrees, $10: longitude in decimal degrees
 401+ * $11: sign (- if south) for latitude, $12: sign (- if west) for longitude
 402+ */
 403+ protected function getServiceLinkParams() {
 404+ $latvals = $this->getAngleValues( true );
 405+ $longvals = $this->getAngleValues( false );
 406+ return array( $latvals[0], $longvals[0],
 407+ $latvals[1], $longvals[1],
 408+ round( $latvals[2] ), round( $longvals[2] ),
 409+ $latvals[3], $longvals[3],
 410+ abs( $this->m_lat ), abs( $this->m_long ),
 411+ $latvals[3] == 'S' ? '-':'', $longvals[3] == 'W' ? '-':'' );
 412+ }
 413+
 414+}
Property changes on: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValue.php
___________________________________________________________________
Name: svn:eol-style
1415 + native
Index: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoords.php
@@ -0,0 +1,71 @@
 2+<?php
 3+
 4+/**
 5+ * File containing the registration and initialization code for the Semantic MediaWiki
 6+ * Geographical Coordinates data type, and things it's dependent on.
 7+ *
 8+ * @file SM_GeoCoords.php
 9+ * @ingroup SemanticMaps
 10+ *
 11+ * @author Jeroen De Dauw
 12+ * @author Markus Krötzsch
 13+ */
 14+
 15+// Registration of the Geographical Coordinate type.
 16+$wgAutoloadClasses['SMGeoCoordsValue'] = $smgDir . 'GeoCoords/SM_GeoCoordsValue.php';
 17+
 18+// Registration of the Geographical Coordinate value description class.
 19+$wgAutoloadClasses['SMGeoCoordsValueDescription'] = $smgDir . 'GeoCoords/SM_GeoCoordsValueDescription.php';
 20+
 21+// Hook for initializing the Geographical Coordinate type.
 22+$wgHooks['smwInitDatatypes'][] = 'smfInitGeoCoordsType';
 23+
 24+// Hook for initializing the Geographical Proximity query support.
 25+$wgHooks['smwGetSQLConditionForValue'][] = 'smfGetGeoProximitySQLCondition';
 26+
 27+/**
 28+ * Adds support for the geographical coordinate data type to Semantic MediaWiki.
 29+ *
 30+ * TODO: i18n keys still need to be moved
 31+ */
 32+function smfInitGeoCoordsType() {
 33+ SMWDataValueFactory::registerDatatype( '_geo', 'SMGeoCoordsValue', 'Geographic coordinate' );
 34+ return true;
 35+}
 36+
 37+/**
 38+ * Custom SQL query extension for matching geographic coordinates.
 39+ *
 40+ * TODO: Parsing latitude and longitude from the DB key of the coordinates
 41+ * value is cleary not a good approach. Instead, the geographic coordinate
 42+ * value object should provide functions to access this data directly.
 43+ *
 44+ * TODO: Add support for a per-coordinate set distance parameter.
 45+ */
 46+function smfGetGeoProximitySQLCondition( &$where, $description, $tablename, $fieldname, $dbs ) {
 47+ $where = '';
 48+ $dv = $description->getDatavalue();
 49+
 50+ if ( ( $dv->getTypeID() != '_geo' )
 51+ || ( !$dv->isValid() )
 52+ || ( $description->getComparator() != SMW_CMP_LIKE )
 53+ ) return true; // Only act on certain query conditions.
 54+
 55+ $keys = $dv->getDBkeys();
 56+ $geoarray = explode( ',', $keys[0] );
 57+
 58+ if ( ( count( $geoarray ) != 2 )
 59+ || ( $geoarray[0] == '' )
 60+ || ( $geoarray[1] == '' )
 61+ ) return true; // There is something wrong with the lat/lon pair
 62+
 63+ $latitude = $dbs->addQuotes( $geoarray[0] );
 64+ $longitude = $dbs->addQuotes( $geoarray[1] );
 65+
 66+ // Compute distances in miles:
 67+ $distance = "ROUND(((ACOS( SIN({$latitude} * PI()/180 ) * SIN(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) + COS({$latitude} * PI()/180 ) * COS(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) * COS(({$longitude} - SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',-1)) * PI()/180))*180/PI())*60*1.1515),6)";
 68+
 69+ $where = "{$distance} <= " . $dbs->addQuotes( "5" );
 70+
 71+ return true;
 72+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoords.php
___________________________________________________________________
Name: svn:eol-style
173 + native
Index: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValueDescription.php
@@ -0,0 +1,32 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the SMGeoCoordsValueDescription class.
 6+ *
 7+ * @file SM_GeoCoordsValueDescription.php
 8+ * @ingroup SemanticMaps
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Description of one data value of type Goegraphical Coordinates.
 19+ *
 20+ * @author Jeroen De Dauw
 21+ *
 22+ * @ingroup SemanticMaps
 23+ */
 24+class SMGeoCoordsValueDescription extends SMWValueDescription {
 25+
 26+ protected $m_distance;
 27+
 28+ public function __construct( SMGeoCoordsValue $datavalue, $distance, $comparator = SMW_CMP_EQ ) {
 29+ parent::__construct( $datavalue, $comparator );
 30+ $this->m_distance = $distance;
 31+ }
 32+
 33+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticMaps/GeoCoords/SM_GeoCoordsValueDescription.php
___________________________________________________________________
Name: svn:eol-style
134 + native
Index: trunk/extensions/SemanticMaps/SM_Settings.php
@@ -60,6 +60,17 @@
6161
6262
6363
 64+
 65+# Geographical Coordinate data type settings
 66+
 67+# Integer. The default distance value to be used in geographical distance queries.
 68+# This value will only be used when the user does not provide one.
 69+$smgGeoCoordDistance = 5;
 70+
 71+
 72+
 73+
 74+
6475 # Query Printers
6576
6677 # Boolean. The default value for the forceshow parameter. Will force a map to be shown even when there are no query results
Index: trunk/extensions/SemanticMaps/SemanticMaps.php
@@ -35,7 +35,7 @@
3636
3737 // Only initialize the extension when all dependencies are present.
3838 if ( defined( 'Maps_VERSION' ) && defined( 'SMW_VERSION' ) ) {
39 - define( 'SM_VERSION', '0.5.5 a1' );
 39+ define( 'SM_VERSION', '0.5.5 a2' );
4040
4141 $smgScriptPath = ( isset( $wgExtensionAssetsPath ) && $wgExtensionAssetsPath ? $wgExtensionAssetsPath : $wgScriptPath . '/extensions' ) . '/SemanticMaps';
4242 $smgDir = dirname( __FILE__ ) . '/';
@@ -51,9 +51,8 @@
5252
5353 $wgExtensionMessagesFiles['SemanticMaps'] = $smgDir . 'SemanticMaps.i18n.php';
5454
55 - // Registration of the Geographical Coordinate type.
56 - $wgAutoloadClasses['SMGeoCoordsValue'] = $smgDir . 'SM_GeoCoordsValue.php';
57 - $wgHooks['smwInitDatatypes'][] = 'smfInitGeoCoordsType';
 55+ // Include the GeoCoords SMW data type file.
 56+ require_once( $smgDir . '/GeoCoords/SM_GeoCoords.php' );
5857 }
5958
6059 /**
@@ -80,20 +79,13 @@
8180 'description' => wfMsgExt( 'semanticmaps_desc', 'parsemag', $services_list ),
8281 );
8382
 83+ // TODO: only add this file when it's required.
8484 $wgOut->addScriptFile( $smgScriptPath . '/SMUtilityFunctions.js' );
8585
8686 return true;
8787 }
8888
8989 /**
90 - * Adds support for the geographical coordinate data type to Semantic MediaWiki.
91 - */
92 -function smfInitGeoCoordsType() {
93 - SMWDataValueFactory::registerDatatype( '_geo', 'SMGeoCoordsValue', 'Geographic coordinate' );
94 - return true;
95 -}
96 -
97 -/**
9890 * Adds a link to Admin Links page.
9991 */
10092 function smfAddToAdminLinks( &$admin_links_tree ) {

Follow-up revisions

RevisionCommit summaryAuthorDate
r63862Follow up to r63845jeroendedauw13:28, 17 March 2010

Status & tagging log