Completed
Push — LocationParsers ( afa02e...666048 )
by Jeroen De
08:17 queued 03:21
created

LocationParser::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.2559

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 5
cp 0.6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2.2559
1
<?php
2
3
namespace Maps;
4
5
use DataValues\Geo\Parsers\LatLongParser;
6
use DataValues\Geo\Values\LatLongValue;
7
use Maps\Elements\Location;
8
use Maps\Geocoders\Geocoder;
9
use Title;
10
use ValueParsers\ParseException;
11
use ValueParsers\StringValueParser;
12
use ValueParsers\ValueParser;
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 implements ValueParser {
23
24
	private $geocoder;
25
	private $useAddressAsTitle;
26
27
	/**
28
	 * @deprecated Use newInstance instead
29
	 */
30 11
	public function __construct( $enableLegacyCrud = true ) {
31 11
		if ( $enableLegacyCrud ) {
32
			$this->geocoder = MapsFactory::newDefault()->newGeocoder();
33
			$this->useAddressAsTitle = false;
34
		}
35 11
	}
36
37
	/**
38
	 * @param Geocoder $geocoder
39
	 * @param bool $useAddressAsTitle
40
	 * @return self
41
	 */
42 11
	public static function newInstance( Geocoder $geocoder, $useAddressAsTitle = false ) {
43 11
		$instance = new self( false );
44 11
		$instance->geocoder = $geocoder;
45 11
		$instance->useAddressAsTitle = $useAddressAsTitle;
46 11
		return $instance;
47
	}
48
49
	/**
50
	 * @see StringValueParser::stringParse
51
	 *
52
	 * @since 3.0
53
	 *
54
	 * @param string $value
55
	 *
56
	 * @return Location
57
	 * @throws ParseException
58
	 */
59 11
	public function parse( $value ) {
60 11
		$separator = '~';
61
62 11
		$metaData = explode( $separator, $value );
63
64 11
		$coordinatesOrAddress = array_shift( $metaData );
65 11
		$coordinates = $this->stringToLatLongValue( $coordinatesOrAddress );
66
67 11
		$location = new Location( $coordinates );
68
69 11
		if ( $metaData !== [] ) {
70 9
			$this->setTitleOrLink( $location, array_shift( $metaData ) );
71
		}
72 2
		else if ( $this->useAddressAsTitle && $this->isAddress( $coordinatesOrAddress ) ) {
73 1
			$location->setTitle( $coordinatesOrAddress );
74
		}
75
76 11
		if ( $metaData !== [] ) {
77
			$location->setText( array_shift( $metaData ) );
78
		}
79
80 11
		if ( $metaData !== [] ) {
81
			$location->setIcon( array_shift( $metaData ) );
82
		}
83
84 11
		if ( $metaData !== [] ) {
85
			$location->setGroup( array_shift( $metaData ) );
86
		}
87
88 11
		if ( $metaData !== [] ) {
89
			$location->setInlineLabel( array_shift( $metaData ) );
90
		}
91
92 11
		return $location;
93
	}
94
95 9
	private function setTitleOrLink( Location $location, $titleOrLink ) {
96 9
		if ( $this->isLink( $titleOrLink ) ) {
97 3
			$this->setLink( $location, $titleOrLink );
98
		}
99
		else {
100 6
			$location->setTitle( $titleOrLink );
101
		}
102 9
	}
103
104 9
	private function isLink( $value ) {
105 9
		return strpos( $value , 'link:' ) === 0;
106
	}
107
108 3
	private function setLink( Location $location, $link ) {
109 3
		$link = substr( $link, 5 );
110 3
		$location->setLink( $this->getExpandedLink( $link ) );
111 3
	}
112
113 3
	private function getExpandedLink( $link ) {
114 3
		if ( filter_var( $link , FILTER_VALIDATE_URL , FILTER_FLAG_SCHEME_REQUIRED ) ) {
115 3
			return $link;
116
		}
117
118
		$title = Title::newFromText( $link );
119
120
		if ( $title === null ) {
121
			return '';
122
		}
123
124
		return $title->getFullURL();
125
	}
126
127
	/**
128
	 * @param string $location
129
	 *
130
	 * @return LatLongValue
131
	 * @throws ParseException
132
	 */
133 11
	private function stringToLatLongValue( $location ) {
134 11
		$parser = new LatLongParser();
135
136
		try {
137 11
			return $parser->parse( $location );
138
		}
139 2
		catch ( ParseException $parseException ) {
140 2
			$latLongValue = $this->geocoder->geocode( $location );
141
142 2
			if ( $latLongValue === null ) {
143
				throw new ParseException( 'Failed to parse or geocode' );
144
			}
145
146 2
			return $latLongValue;
147
		}
148
	}
149
150
	/**
151
	 * @param string $coordsOrAddress
152
	 *
153
	 * @return boolean
154
	 */
155 2
	private function isAddress( $coordsOrAddress ) {
156 2
		$coordinateParser = new LatLongParser();
157
158
		try {
159 2
			$coordinateParser->parse( $coordsOrAddress );
160
		}
161 1
		catch ( ParseException $parseException ) {
162 1
			return true;
163
		}
164
165 1
		return false;
166
	}
167
168
}
169