Passed
Push — master ( e94f7b...8ef9ba )
by Jeroen De
01:02 queued 11s
created

FloatCoordinateParser::areValidCoordinates()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5.0042

Importance

Changes 0
Metric Value
dl 0
loc 38
ccs 17
cts 18
cp 0.9444
rs 9.0008
c 0
b 0
f 0
cc 5
nc 7
nop 1
crap 5.0042
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace DataValues\Geo\Parsers;
6
7
use ValueParsers\ParseException;
8
9
/**
10
 * @since 0.1
11
 *
12
 * @license GPL-2.0-or-later
13
 * @author Jeroen De Dauw < [email protected] >
14
 * @author H. Snater < [email protected] >
15
 */
16
class FloatCoordinateParser extends LatLongParserBase {
17
18
	public const FORMAT_NAME = 'float-coordinate';
19
20
	/**
21
	 * @see LatLongParserBase::getParsedCoordinate
22
	 *
23
	 * @param string $coordinateSegment
24
	 *
25
	 * @return float
26
	 */
27 18
	protected function getParsedCoordinate( string $coordinateSegment ): float {
28 18
		return (float)$this->resolveDirection( str_replace( ' ', '', $coordinateSegment ) );
29
	}
30
31
	/**
32
	 * @see LatLongParserBase::areValidCoordinates
33
	 *
34
	 * @param string[] $normalizedCoordinateSegments
35
	 *
36
	 * @return bool
37
	 */
38 18
	protected function areValidCoordinates( array $normalizedCoordinateSegments ): bool {
39
		// TODO: Implement localized decimal separator.
40 18
		$baseRegExp = '\d{1,3}(\.\d{1,20})?';
41
42 18
		$match = false;
43
44 18
		foreach ( $normalizedCoordinateSegments as $i => $segment ) {
45 18
			$segment = str_replace( ' ', '', $segment );
46
47
			$direction = '('
48 18
				. $this->getOption( self::OPT_NORTH_SYMBOL ) . '|'
49 18
				. $this->getOption( self::OPT_SOUTH_SYMBOL ) . ')';
50
51 18
			if ( $i === 1 ) {
52
				$direction = '('
53 18
					. $this->getOption( self::OPT_EAST_SYMBOL ) . '|'
54 18
					. $this->getOption( self::OPT_WEST_SYMBOL ) . ')';
55
			}
56
57 18
			$match = preg_match(
58 18
				'/^(' . $baseRegExp . $direction . '|' . $direction . $baseRegExp . ')$/i',
59
				$segment
60
			);
61
62 18
			if ( $match ) {
63 10
				continue;
64
			}
65
66 8
			$match = preg_match( '/^(-)?' . $baseRegExp . '$/i', $segment );
67
68 8
			if ( !$match ) {
69
				// Does neither match directional nor non-directional.
70
				break;
71
			}
72
		}
73
74 18
		return ( 1 === $match );
75
	}
76
77
	/**
78
	 * @see LatLongParserBase::splitString
79
	 *
80
	 * @param string $normalizedCoordinateString
81
	 *
82
	 * @throws ParseException if unable to split input string into two segments
83
	 * @return string[]
84
	 */
85 20
	protected function splitString( string $normalizedCoordinateString ): array {
86 20
		$separator = $this->getOption( self::OPT_SEPARATOR_SYMBOL );
87
88 20
		$normalizedCoordinateSegments = explode( $separator, $normalizedCoordinateString );
89
90 20
		if ( count( $normalizedCoordinateSegments ) !== 2 ) {
91
			// Separator not present within the string, trying to figure out the segments by
92
			// splitting at the the first SPACE after the first direction character or digit:
93 13
			$numberRegEx = '-?\d{1,3}(\.\d{1,20})?';
94
95
			$ns = '('
96 13
				. $this->getOption( self::OPT_NORTH_SYMBOL ) . '|'
97 13
				. $this->getOption( self::OPT_SOUTH_SYMBOL ) .')';
98
99 13
			$latitudeRegEx = '(' . $ns . '\s*)?' . $numberRegEx . '(\s*' . $ns . ')?';
100
101
			$ew = '('
102 13
				. $this->getOption( self::OPT_EAST_SYMBOL ) . '|'
103 13
				. $this->getOption( self::OPT_WEST_SYMBOL ) .')';
104
105 13
			$longitudeRegEx = '(' . $ew . '\s*)?' . $numberRegEx . '(\s*' . $ew . ')?';
106
107 13
			$match = preg_match(
108 13
				'/^(' . $latitudeRegEx . ') (' . $longitudeRegEx . ')$/i',
109
				$normalizedCoordinateString,
110
				$matches
111
			);
112
113 13
			if ( $match ) {
114 11
				$normalizedCoordinateSegments = [ $matches[1], $matches[7] ];
115
			}
116
		}
117
118 20
		if ( count( $normalizedCoordinateSegments ) !== 2 ) {
119 2
			throw new ParseException(
120 2
				'Unable to split input into two coordinate segments',
121
				$normalizedCoordinateString,
122 2
				self::FORMAT_NAME
123
			);
124
		}
125
126 18
		return $normalizedCoordinateSegments;
127
	}
128
129
}
130