Completed
Push — master ( f04bbc...eab9d5 )
by Jeroen De
07:09
created

SemanticMaps/src/SM_GeoCoordsValue.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use DataValues\Geo\Formatters\GeoCoordinateFormatter;
4
use DataValues\Geo\Parsers\GeoCoordinateParser;
5
use DataValues\Geo\Values\LatLongValue;
6
use ValueParsers\ParseException;
7
8
/**
9
 * Implementation of datavalues that are geographic coordinates.
10
 * 
11
 * @since 0.6
12
 * 
13
 * @file SM_GeoCoordsValue.php
14
 * @ingroup SemanticMaps
15
 * @ingroup SMWDataValues
16
 * 
17
 * @licence GNU GPL v2+
18
 * @author Jeroen De Dauw < [email protected] >
19
 * @author Markus Krötzsch
20
 */
21
class SMGeoCoordsValue extends SMWDataValue {
22
23
	protected $wikiValue;
24
25
	/**
26
	 * @see SMWDataValue::setDataItem
27
	 * 
28
	 * @since 1.0
29
	 * 
30
	 * @param SMWDataItem $dataItem
31
	 * 
32
	 * @return boolean
33
	 */
34
	protected function loadDataItem( SMWDataItem $dataItem ) {
35
		if ( $dataItem instanceof SMWDIGeoCoord ) {
0 ignored issues
show
The class SMWDIGeoCoord does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
36
			 $formattedValue = $this->getFormattedCoord( $dataItem );
37
38
			if ( $formattedValue !== null ) {
39
				$this->wikiValue = $formattedValue;
40
				$this->m_dataitem = $dataItem;
41
				return true;
42
			}
43
		}
44
45
		return false;
46
	}
47
48
	/**
49
	 * @since 3.0
50
	 *
51
	 * @param SMWDIGeoCoord $dataItem
52
	 * @param string|null $format
53
	 *
54
	 * @return string|null
55
	 */
56
	protected function getFormattedCoord( SMWDIGeoCoord $dataItem, $format = null ) {
57
		global $smgQPCoodFormat;
58
59
		$options = new \ValueFormatters\FormatterOptions( [
60
			GeoCoordinateFormatter::OPT_FORMAT => $format === null ? $smgQPCoodFormat : $format, // TODO
61
		] );
62
63
		// TODO: $smgQPCoodDirectional
64
65
		$coordinateFormatter = new GeoCoordinateFormatter( $options );
66
67
		$value = new LatLongValue(
68
			$dataItem->getLatitude(),
69
			$dataItem->getLongitude()
70
		);
71
72
		return $coordinateFormatter->format( $value );
73
	}
74
	
75
	/**
76
	 * Overwrite SMWDataValue::getQueryDescription() to be able to process
77
	 * comparators between all values.
78
	 * 
79
	 * @since 0.6
80
	 * 
81
	 * @param string $value
82
	 * 
83
	 * @return SMWDescription
84
	 * @throws InvalidArgumentException
85
	 */
86
	public function getQueryDescription( $value ) {
87
		if ( !is_string( $value ) ) {
88
			throw new InvalidArgumentException( '$value needs to be a string' );
89
		}
90
91
		list( $distance, $comparator ) = $this->parseUserValue( $value );
92
		$distance = $this->parserDistance( $distance );
93
94
		$this->setUserValue( $value );
95
96
		switch ( true ) {
97
			case !$this->isValid() :
98
				return new SMWThingDescription();
99
			case $distance !== false :
100
				return new SMAreaValueDescription( $this->getDataItem(), $comparator, $distance );
101
			default :
102
				return new SMGeoCoordsValueDescription( $this->getDataItem(), null, $comparator );
103
		}
104
	}
105
106
	protected function parserDistance( $distance ) {
107
		if ( $distance !== false ) {
108
			$distance = substr( trim( $distance ), 0, -1 );
109
110
			if ( !MapsDistanceParser::isDistance( $distance ) ) {
111
				$this->addError( wfMessage( 'semanticmaps-unrecognizeddistance', $distance )->text() );
112
				$distance = false;
113
			}
114
		}
115
116
		return $distance;
117
	}
118
119
	/**
120
	 * @see SMWDataValue::parseUserValue
121
	 *
122
	 * @since 0.6
123
	 */
124
	protected function parseUserValue( $value ) {
125
		if ( !is_string( $value ) ) {
126
			throw new InvalidArgumentException( '$value needs to be a string' );
127
		}
128
129
		$this->wikiValue = $value;
130
131
		$comparator = SMW_CMP_EQ;
132
		$distance = false;
133
134
		if ( $value === '' ) {
135
			$this->addError( wfMessage( 'smw_novalues' )->text() );
136
		} else {
137
			SMWDataValue::prepareValue( $value, $comparator );
138
139
			list( $coordinates, $distance ) = $this->findValueParts( $value );
140
141
			$this->tryParseAndSetDataItem( $coordinates );
142
		}
143
144
		return [ $distance, $comparator ];
145
	}
146
147
	protected function findValueParts( $value ) {
148
		$parts = explode( '(', $value );
149
150
		$coordinates = trim( array_shift( $parts ) );
151
		$distance = count( $parts ) > 0 ? trim( array_shift( $parts ) ) : false;
152
153
		return [ $coordinates, $distance ];
154
	}
155
156
	/**
157
	 * @param string $coordinates
158
	 */
159
	protected function tryParseAndSetDataItem( $coordinates ) {
160
		$options = new \ValueParsers\ParserOptions();
161
		$parser = new GeoCoordinateParser( $options );
162
163
		try {
164
			$value = $parser->parse( $coordinates );
165
			$this->m_dataitem = new SMWDIGeoCoord( $value->getLatitude(), $value->getLongitude() );
166
		}
167
		catch ( ParseException $parseException ) {
168
			$this->addError( wfMessage( 'maps_unrecognized_coords', $coordinates, 1 )->text() );
169
170
			// Make sure this is always set
171
			// TODO: Why is this needed?!
172
			$this->m_dataitem = new SMWDIGeoCoord( [ 'lat' => 0, 'lon' => 0 ] );
173
		}
174
	}
175
176
	/**
177
	 * @see SMWDataValue::getShortWikiText
178
	 * 
179
	 * @since 0.6
180
	 */
181
	public function getShortWikiText( $linked = null ) {
182
		if ( $this->isValid() ) {
183
			if ( $this->m_caption === false ) {
184
				return $this->getFormattedCoord( $this->m_dataitem );
185
			}
186
			else {
187
				return $this->m_caption; 
188
			}
189
		}
190
		else {
191
			return $this->getErrorText();
192
		}
193
	}
194
	
195
	/**
196
	 * @see SMWDataValue::getShortHTMLText
197
	 * 
198
	 * @since 0.6
199
	 */
200
	public function getShortHTMLText( $linker = null ) {
201
		return $this->getShortWikiText( $linker );
202
	}
203
	
204
	/**
205
	 * @see SMWDataValue::getLongWikiText
206
	 * 
207
	 * @since 0.6
208
	 */
209
	public function getLongWikiText( $linked = null ) {
210
		if ( $this->isValid() ) {
211
			SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
212
213
			// TODO: fix lang keys so they include the space and coordinates.
214
			$coordinateSet = $this->m_dataitem->getCoordinateSet();
215
			
216
			$text = $this->getFormattedCoord( $this->m_dataitem );
217
218
			$lines = [
219
				wfMessage( 'semanticmaps-latitude', $coordinateSet['lat'] )->inContentLanguage()->escaped(),
220
				wfMessage( 'semanticmaps-longitude', $coordinateSet['lon'] )->inContentLanguage()->escaped(),
221
			];
222
			
223
			if ( array_key_exists( 'alt', $coordinateSet ) ) {
224
				$lines[] = wfMessage( 'semanticmaps-altitude', $coordinateSet['alt'] )->inContentLanguage()->escaped();
225
			}
226
			
227
			return 	'<span class="smwttinline">' . htmlspecialchars( $text ) . '<span class="smwttcontent">' .
228
		        	 	implode( '<br />', $lines ) .
229
		        	'</span></span>';
230
		} else {
231
			return $this->getErrorText();
232
		}		
233
	}
234
235
	/**
236
	 * @see SMWDataValue::getLongHTMLText
237
	 * 
238
	 * @since 0.6
239
	 */
240
	public function getLongHTMLText( $linker = null ) {
241
		return $this->getLongWikiText( $linker );
242
	}
243
244
	/**
245
	 * @see SMWDataValue::getWikiValue
246
	 * 
247
	 * @since 0.6
248
	 */
249
	public function getWikiValue() {
250
		return $this->wikiValue;
251
	}
252
253
	/**
254
	 * Create links to mapping services based on a wiki-editable message. The parameters
255
	 * available to the message are:
256
	 * 
257
	 * $1: The location in non-directional float notation.
258
	 * $2: The location in directional DMS notation.
259
	 * $3: The latitude in non-directional float notation.
260
	 * $4 The longitude in non-directional float notation.
261
	 * 
262
	 * @since 0.6.4
263
	 * 
264
	 * @return array
265
	 */
266
	protected function getServiceLinkParams() {
267
		$coordinateSet = $this->m_dataitem->getCoordinateSet();
268
		return [
269
			$this->getFormattedCoord( $this->m_dataitem, 'float' ), // TODO
270
			$this->getFormattedCoord( $this->m_dataitem, 'dms' ), // TODO
271
			$coordinateSet['lat'],
272
			$coordinateSet['lon']
273
		];
274
	}
275
276
}
277