Completed
Push — fix-displaymap-geoservice ( 878215 )
by Jeroen De
03:18
created

LocationParser   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 80%

Importance

Changes 0
Metric Value
wmc 21
c 0
b 0
f 0
lcom 1
cbo 6
dl 0
loc 133
ccs 52
cts 65
cp 0.8
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
C stringParse() 0 37 8
A setTitleOrLink() 0 8 2
A isLink() 0 3 1
A setLink() 0 4 1
A getExpandedLink() 0 13 3
A stringToLatLongValue() 0 15 3
A isAddress() 0 12 2
1
<?php
2
3
namespace Maps;
4
5
use DataValues\Geo\Parsers\GeoCoordinateParser;
6
use DataValues\Geo\Values\LatLongValue;
7
use Maps\Elements\Location;
8
use MWException;
9
use Title;
10
use ValueParsers\ParserOptions;
11
use ValueParsers\ParseException;
12
use ValueParsers\StringValueParser;
13
14
/**
15
 * ValueParser that parses the string representation of a location.
16
 *
17
 * @since 3.0
18
 *
19
 * @licence GNU GPL v2+
20
 * @author Jeroen De Dauw < [email protected] >
21
 */
22
class LocationParser extends StringValueParser {
23
24
	/**
25
	 * @param ParserOptions|null $options
26
	 */
27 26
	public function __construct( ParserOptions $options = null ) {
28 26
		parent::__construct( $options );
29
30 26
		$this->defaultOption( 'useaddressastitle', false );
31 26
		$this->defaultOption( 'geoService', '' );
32 26
	}
33
34
	/**
35
	 * @see StringValueParser::stringParse
36
	 *
37
	 * @since 3.0
38
	 *
39
	 * @param string $value
40
	 *
41
	 * @return Location
42
	 * @throws ParseException
43
	 */
44 19
	public function stringParse( $value ) {
45 19
		$separator = '~';
46
47 19
		$useaddressastitle = $this->getOption( 'useaddressastitle' );
48
49 19
		$metaData = explode( $separator, $value );
50
51 19
		$coordinatesOrAddress = array_shift( $metaData );
52 19
		$coordinates = $this->stringToLatLongValue( $coordinatesOrAddress );
53
54 19
		$location = new Location( $coordinates );
55
56 19
		if ( $metaData !== [] ) {
57 10
			$this->setTitleOrLink( $location, array_shift( $metaData ) );
58 10
		}
59 9
		else if ( $useaddressastitle && $this->isAddress( $coordinatesOrAddress ) ) {
60 1
			$location->setTitle( $coordinatesOrAddress );
61 1
		}
62
63 19
		if ( $metaData !== [] ) {
64 1
			$location->setText( array_shift( $metaData ) );
65 1
		}
66
67 19
		if ( $metaData !== [] ) {
68
			$location->setIcon( array_shift( $metaData ) );
69
		}
70
71 19
		if ( $metaData !== [] ) {
72
			$location->setGroup( array_shift( $metaData ) );
73
		}
74
75 19
		if ( $metaData !== [] ) {
76
			$location->setInlineLabel( array_shift( $metaData ) );
77
		}
78
79 19
		return $location;
80
	}
81
82 10
	private function setTitleOrLink( Location $location, $titleOrLink ) {
83 10
		if ( $this->isLink( $titleOrLink ) ) {
84 3
			$this->setLink( $location, $titleOrLink );
85 3
		}
86
		else {
87 7
			$location->setTitle( $titleOrLink );
88
		}
89 10
	}
90
91 10
	private function isLink( $value ) {
92 10
		return strpos( $value , 'link:' ) === 0;
93
	}
94
95 3
	private function setLink( Location $location, $link ) {
96 3
		$link = substr( $link, 5 );
97 3
		$location->setLink( $this->getExpandedLink( $link ) );
98 3
	}
99
100 3
	private function getExpandedLink( $link ) {
101 3
		if ( filter_var( $link , FILTER_VALIDATE_URL , FILTER_FLAG_SCHEME_REQUIRED ) ) {
102 3
			return $link;
103
		}
104
105
		$title = Title::newFromText( $link );
106
107
		if ( $title === null ) {
108
			return '';
109
		}
110
111
		return $title->getFullURL();
112
	}
113
114
	/**
115
	 * @param string $location
116
	 *
117
	 * @return LatLongValue
118
	 * @throws ParseException
119
	 */
120 19
	private function stringToLatLongValue( $location ) {
121 19
		if ( Geocoders::canGeocode() ) {
122 19
			$latLongValue = Geocoders::attemptToGeocode( $location, $this->getOption( 'geoService' ) );
123
124 19
			if ( $latLongValue === false ) {
125
				throw new ParseException( 'Failed to parse or geocode' );
126
			}
127
128 19
			assert( $latLongValue instanceof LatLongValue );
129 19
			return $latLongValue;
130
		}
131
132
		$parser = new GeoCoordinateParser( new \ValueParsers\ParserOptions() );
133
		return $parser->parse( $location );
134
	}
135
136
	/**
137
	 * @param string $coordsOrAddress
138
	 *
139
	 * @return boolean
140
	 */
141 2
	private function isAddress( $coordsOrAddress ) {
142 2
		$coordinateParser = new GeoCoordinateParser( new \ValueParsers\ParserOptions() );
143
144
		try {
145 2
			$coordinateParser->parse( $coordsOrAddress );
146
		}
147 2
		catch ( ParseException $parseException ) {
148 1
			return true;
149
		}
150
151 1
		return false;
152
	}
153
154
}
155