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

LocationParser::isAddress()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 12
ccs 6
cts 6
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
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
	}
32
33
	/**
34
	 * @see StringValueParser::stringParse
35
	 *
36
	 * @since 3.0
37
	 *
38
	 * @param string $value
39
	 *
40
	 * @return Location
41
	 * @throws MWException
42
	 */
43 19
	public function stringParse( $value ) {
44 19
		$separator = '~';
45
46 19
		$useaddressastitle = $this->getOption( 'useaddressastitle' );
47
48 19
		$metaData = explode( $separator, $value );
49
50 19
		$coordinatesOrAddress = array_shift( $metaData );
51 19
		$coordinates = $this->stringToLatLongValue( $coordinatesOrAddress );
52
53 19
		$location = new Location( $coordinates );
54
55 19
		if ( $metaData !== [] ) {
56 10
			$this->setTitleOrLink( $location, array_shift( $metaData ) );
57 10
		}
58 9
		else if ( $useaddressastitle && $this->isAddress( $coordinatesOrAddress ) ) {
59 1
			$location->setTitle( $coordinatesOrAddress );
60 1
		}
61
62 19
		if ( $metaData !== [] ) {
63 1
			$location->setText( array_shift( $metaData ) );
64 1
		}
65
66 19
		if ( $metaData !== [] ) {
67
			$location->setIcon( array_shift( $metaData ) );
68
		}
69
70 19
		if ( $metaData !== [] ) {
71
			$location->setGroup( array_shift( $metaData ) );
72
		}
73
74 19
		if ( $metaData !== [] ) {
75
			$location->setInlineLabel( array_shift( $metaData ) );
76
		}
77
78 19
		return $location;
79
	}
80
81 10
	private function setTitleOrLink( Location $location, $titleOrLink ) {
82 10
		if ( $this->isLink( $titleOrLink ) ) {
83 3
			$this->setLink( $location, $titleOrLink );
84 3
		}
85
		else {
86 7
			$location->setTitle( $titleOrLink );
87
		}
88 10
	}
89
90 10
	private function isLink( $value ) {
91 10
		return strpos( $value , 'link:' ) === 0;
92
	}
93
94 3
	private function setLink( Location $location, $link ) {
95 3
		$link = substr( $link, 5 );
96 3
		$location->setLink( $this->getExpandedLink( $link ) );
97 3
	}
98
99 3
	private function getExpandedLink( $link ) {
100 3
		if ( filter_var( $link , FILTER_VALIDATE_URL , FILTER_FLAG_SCHEME_REQUIRED ) ) {
101 3
			return $link;
102
		}
103
104
		$title = Title::newFromText( $link );
105
106
		if ( $title === null ) {
107
			return '';
108
		}
109
110
		return $title->getFullURL();
111
	}
112
113
	/**
114
	 * @param string $location
115
	 *
116
	 * @return LatLongValue
117
	 * @throws ParseException
118
	 */
119 19
	private function stringToLatLongValue( $location ) {
120 19
		if ( Geocoders::canGeocode() ) {
121 19
			$latLongValue = Geocoders::attemptToGeocode( $location );
122
123 19
			if ( $latLongValue === false ) {
124
				throw new ParseException( 'Failed to parse or geocode' );
125
			}
126
127 19
			assert( $latLongValue instanceof LatLongValue );
128 19
			return $latLongValue;
129
		}
130
131
		$parser = new GeoCoordinateParser( new \ValueParsers\ParserOptions() );
132
		return $parser->parse( $location );
133
	}
134
135
	/**
136
	 * @param string $coordsOrAddress
137
	 *
138
	 * @return boolean
139
	 */
140 2
	private function isAddress( $coordsOrAddress ) {
141 2
		$coordinateParser = new GeoCoordinateParser( new \ValueParsers\ParserOptions() );
142
143
		try {
144 2
			$coordinateParser->parse( $coordsOrAddress );
145
		}
146 2
		catch ( ParseException $parseException ) {
147 1
			return true;
148
		}
149
150 1
		return false;
151
	}
152
153
}
154