Completed
Push — leaflet-attribution ( 0121c0 )
by Peter
04:35
created

LocationParser::parse()   D

Complexity

Conditions 9
Paths 49

Size

Total Lines 40
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
rs 4.909
c 0
b 0
f 0
cc 9
eloc 22
nc 49
nop 1
1
<?php
2
3
namespace Maps;
4
5
use DataValues\Geo\Parsers\LatLongParser;
6
use Jeroen\SimpleGeocoder\Geocoder;
7
use Maps\Elements\Location;
8
use Title;
9
use ValueParsers\ParseException;
10
use ValueParsers\StringValueParser;
11
use ValueParsers\ValueParser;
12
13
/**
14
 * ValueParser that parses the string representation of a location.
15
 *
16
 * @since 3.0
17
 *
18
 * @licence GNU GPL v2+
19
 * @author Jeroen De Dauw < [email protected] >
20
 */
21
class LocationParser implements ValueParser {
22
23
	private $geocoder;
24
	private $useAddressAsTitle;
25
26
	/**
27
	 * @deprecated Use newInstance instead
28
	 */
29
	public function __construct( $enableLegacyCrud = true ) {
30
		if ( $enableLegacyCrud ) {
31
			$this->geocoder = MapsFactory::newDefault()->newGeocoder();
32
			$this->useAddressAsTitle = false;
33
		}
34
	}
35
36
	public static function newInstance( Geocoder $geocoder, bool $useAddressAsTitle = false ): self {
37
		$instance = new self( false );
38
		$instance->geocoder = $geocoder;
39
		$instance->useAddressAsTitle = $useAddressAsTitle;
40
		return $instance;
41
	}
42
43
	/**
44
	 * @see StringValueParser::stringParse
45
	 *
46
	 * @since 3.0
47
	 *
48
	 * @param string $value
49
	 *
50
	 * @return Location
51
	 * @throws ParseException
52
	 */
53
	public function parse( $value ) {
54
		$separator = '~';
55
56
		$metaData = explode( $separator, $value );
57
58
		$coordinatesOrAddress = array_shift( $metaData );
59
		$coordinates = $this->geocoder->geocode( $coordinatesOrAddress );
60
61
		if ( $coordinates === null ) {
62
			throw new ParseException( 'Location is not a parsable coordinate and not a geocodable address' );
63
		}
64
65
		$location = new Location( $coordinates );
66
67
		if ( $metaData !== [] ) {
68
			$this->setTitleOrLink( $location, array_shift( $metaData ) );
69
		} else {
70
			if ( $this->useAddressAsTitle && $this->isAddress( $coordinatesOrAddress ) ) {
71
				$location->setTitle( $coordinatesOrAddress );
72
			}
73
		}
74
75
		if ( $metaData !== [] ) {
76
			$location->setText( array_shift( $metaData ) );
77
		}
78
79
		if ( $metaData !== [] ) {
80
			$location->setIcon( array_shift( $metaData ) );
81
		}
82
83
		if ( $metaData !== [] ) {
84
			$location->setGroup( array_shift( $metaData ) );
85
		}
86
87
		if ( $metaData !== [] ) {
88
			$location->setInlineLabel( array_shift( $metaData ) );
89
		}
90
91
		return $location;
92
	}
93
94
	private function setTitleOrLink( Location $location, $titleOrLink ) {
95
		if ( $this->isLink( $titleOrLink ) ) {
96
			$this->setLink( $location, $titleOrLink );
97
		} else {
98
			$location->setTitle( $titleOrLink );
99
		}
100
	}
101
102
	private function isLink( $value ) {
103
		return strpos( $value, 'link:' ) === 0;
104
	}
105
106
	private function setLink( Location $location, $link ) {
107
		$link = substr( $link, 5 );
108
		$location->setLink( $this->getExpandedLink( $link ) );
109
	}
110
111
	private function getExpandedLink( $link ) {
112
		if ( filter_var( $link, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED ) ) {
113
			return $link;
114
		}
115
116
		$title = Title::newFromText( $link );
117
118
		if ( $title === null ) {
119
			return '';
120
		}
121
122
		return $title->getFullURL();
123
	}
124
125
	/**
126
	 * @param string $coordsOrAddress
127
	 *
128
	 * @return boolean
129
	 */
130
	private function isAddress( $coordsOrAddress ) {
131
		$coordinateParser = new LatLongParser();
132
133
		try {
134
			$coordinateParser->parse( $coordsOrAddress );
135
		}
136
		catch ( ParseException $parseException ) {
137
			return true;
138
		}
139
140
		return false;
141
	}
142
143
}
144