LocationParser::newInstance()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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