Passed
Push — master ( 9bfee7...008502 )
by no
03:35 queued 01:22
created

DmCoordinateParser::areValidCoordinates()   B

Complexity

Conditions 8
Paths 33

Size

Total Lines 61
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 8

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 61
ccs 32
cts 32
cp 1
rs 7.0047
cc 8
eloc 37
nc 33
nop 1
crap 8

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace DataValues\Geo\Parsers;
4
5
use ValueParsers\ParseException;
6
use ValueParsers\ParserOptions;
7
8
/**
9
 * Parser for geographical coordinates in Decimal Minute notation.
10
 *
11
 * @since 0.1
12
 *
13
 * @license GPL-2.0-or-later
14
 * @author Jeroen De Dauw < [email protected] >
15
 * @author H. Snater < [email protected] >
16
 */
17
class DmCoordinateParser extends DdCoordinateParser {
18
19
	const FORMAT_NAME = 'dm-coordinate';
20
21
	/**
22
	 * The symbols representing minutes.
23
	 * @since 0.1
24
	 */
25
	const OPT_MINUTE_SYMBOL = 'minute';
26
27
	/**
28
	 * @param ParserOptions|null $options
29
	 */
30 21
	public function __construct( ParserOptions $options = null ) {
31 21
		$options = $options ?: new ParserOptions();
32 21
		$options->defaultOption( self::OPT_MINUTE_SYMBOL, "'" );
33
34 21
		parent::__construct( $options );
35
36 21
		$this->defaultDelimiters = [ $this->getOption( self::OPT_MINUTE_SYMBOL ) ];
0 ignored issues
show
Documentation Bug introduced by
It seems like array($this->getOption(self::OPT_MINUTE_SYMBOL)) of type array<integer,*,{"0":"*"}> is incompatible with the declared type array<integer,string> of property $defaultDelimiters.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
37 21
	}
38
39
	/**
40
	 * @see LatLongParserBase::areValidCoordinates
41
	 *
42
	 * @param string[] $normalizedCoordinateSegments
43
	 *
44
	 * @return bool
45
	 */
46 21
	protected function areValidCoordinates( array $normalizedCoordinateSegments ) {
47
		// At least one coordinate segment needs to have minutes specified.
48
		$regExpStrict = '\d{1,3}'
49 21
			. preg_quote( $this->getOption( self::OPT_DEGREE_SYMBOL ) )
50
			// TODO: Implement localized decimal separator.
51 21
			. '(\d{1,2}(\.\d{1,20})?'
52 21
			. preg_quote( $this->getOption( self::OPT_MINUTE_SYMBOL ) )
53 21
			. ')';
54 21
		$regExpLoose = $regExpStrict . '?';
55
56
		// Cache whether minutes have been detected within the coordinate:
57 21
		$detectedMinute = false;
58
59
		// Cache whether the coordinates are specified in directional format (a mixture of
60
		// directional and non-directional is regarded invalid).
61 21
		$directional = false;
62
63 21
		foreach ( $normalizedCoordinateSegments as $i => $segment ) {
64
			$direction = '('
65 21
				. $this->getOption( self::OPT_NORTH_SYMBOL ) . '|'
66 21
				. $this->getOption( self::OPT_SOUTH_SYMBOL ) . ')';
67
68 21
			if ( $i === 1 ) {
69
				$direction = '('
70 16
					. $this->getOption( self::OPT_EAST_SYMBOL ) . '|'
71 16
					. $this->getOption( self::OPT_WEST_SYMBOL ) . ')';
72
			}
73
74 21
			$match = preg_match(
75 21
				'/^(' . $regExpStrict . $direction . '|' . $direction . $regExpStrict . ')$/i',
76 21
				$segment
77
			);
78
79 21
			if ( $match ) {
80 6
				$detectedMinute = true;
81
			} else {
82 15
				$match = preg_match(
83 15
					'/^(' . $regExpLoose . $direction . '|' . $direction . $regExpLoose . ')$/i',
84 15
					$segment
85
				);
86
			}
87
88 21
			if ( $match ) {
89 6
				$directional = true;
90 15
			} elseif ( !$directional ) {
91 15
				$match = preg_match( '/^(-)?' . $regExpStrict . '$/i', $segment );
92
93 15
				if ( $match ) {
94 10
					$detectedMinute = true;
95
				} else {
96 5
					$match = preg_match( '/^(-)?' . $regExpLoose . '$/i', $segment );
97
				}
98
			}
99
100 21
			if ( !$match ) {
101 21
				return false;
102
			}
103
		}
104
105 16
		return $detectedMinute;
106
	}
107
108
	/**
109
	 * @see DdCoordinateParser::getNormalizedNotation
110
	 *
111
	 * @param string $coordinates
112
	 *
113
	 * @return string
114
	 */
115 21
	protected function getNormalizedNotation( $coordinates ) {
116 21
		$minute = $this->getOption( self::OPT_MINUTE_SYMBOL );
117
118 21
		$coordinates = str_replace( [ '&#8242;', '&prime;', '´', '′' ], $minute, $coordinates );
119
120 21
		$coordinates = parent::getNormalizedNotation( $coordinates );
121
122 21
		$coordinates = $this->removeInvalidChars( $coordinates );
123
124 21
		return $coordinates;
125
	}
126
127
	/**
128
	 * @see DdCoordinateParser::parseCoordinate
129
	 *
130
	 * @param string $coordinateSegment
131
	 *
132
	 * @return float
133
	 */
134 16
	protected function parseCoordinate( $coordinateSegment ) {
135 16
		$isNegative = substr( $coordinateSegment, 0, 1 ) === '-';
136
137 16
		if ( $isNegative ) {
138 5
			$coordinateSegment = substr( $coordinateSegment, 1 );
139
		}
140
141 16
		$degreeSymbol = $this->getOption( self::OPT_DEGREE_SYMBOL );
142 16
		$exploded = explode( $degreeSymbol, $coordinateSegment );
143
144 16
		if ( count( $exploded ) !== 2 ) {
145
			throw new ParseException(
146
				'Unable to explode coordinate segment by degree symbol (' . $degreeSymbol . ')',
147
				$coordinateSegment,
148
				self::FORMAT_NAME
149
			);
150
		}
151
152 16
		list( $degrees, $minutes ) = $exploded;
153
154 16
		$minutes = substr( $minutes, 0, -1 );
155
156 16
		$coordinateSegment = $degrees + $minutes / 60;
157
158 16
		if ( $isNegative ) {
159 5
			$coordinateSegment *= -1;
160
		}
161
162 16
		return (float)$coordinateSegment;
163
	}
164
165
}
166