Skip to content

Commit

Permalink
Merge pull request #21 from longitude-one/20-longitude-onedoctrine-sp…
Browse files Browse the repository at this point in the history
…atial-needs-code-error-on-range-exception

Range exception enhancement done
Fix #20
  • Loading branch information
Alexandre-T authored May 22, 2024
2 parents b6a1e30 + 02e1b7e commit 8b851e9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 20 deletions.
27 changes: 27 additions & 0 deletions lib/LongitudeOne/Geo/String/Exception/RangeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,31 @@
*/
class RangeException extends \RangeException implements ExceptionInterface
{
public const DEFAULT_MESSAGE = 'Unknown range exception';
public const LATITUDE_MESSAGE = 'Latitude must be between -90 and 90';
public const LATITUDE_OUT_OF_RANGE = 90;
public const LONGITUDE_MESSAGE = 'Longitude must be between -180 and 180';
public const LONGITUDE_OUT_OF_RANGE = 180;
public const MINUTES_MESSAGE = 'Minutes must be between 0 and 59';
public const MINUTES_OUT_OF_RANGE = 3600;
public const SECONDS_MESSAGE = 'Seconds must be between 0 and 59';
public const SECONDS_OUT_OF_RANGE = 60;

public function __construct(string $value, int $code, ?\Throwable $previous = null)
{
$message = sprintf('[RangeException] %s, got "%s".', $this->setMessage($code), $value);

parent::__construct($message, $code, $previous);
}

private function setMessage(int $code): string
{
return match ($code) {
self::LATITUDE_OUT_OF_RANGE => self::LATITUDE_MESSAGE,
self::LONGITUDE_OUT_OF_RANGE => self::LONGITUDE_MESSAGE,
self::SECONDS_OUT_OF_RANGE => self::SECONDS_MESSAGE,
self::MINUTES_OUT_OF_RANGE => self::MINUTES_MESSAGE,
default => self::DEFAULT_MESSAGE,
};
}
}
26 changes: 10 additions & 16 deletions lib/LongitudeOne/Geo/String/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ private function cardinal(int|float $value): int|float

// Throw exception if value is out of range
if ($value > $range) {
throw $this->rangeError('Degrees', $range, -1 * $range);
$code = RangeException::LATITUDE_OUT_OF_RANGE;
if (180 === $range) {
$code = RangeException::LONGITUDE_OUT_OF_RANGE;
}

throw new RangeException($this->input, $code);
}

// Return value with sign
Expand Down Expand Up @@ -248,7 +253,7 @@ private function minutes(): string|int

// Throw exception if minutes are greater than 60
if ($readMinutes > 60) {
throw $this->rangeError('Minutes', 60);
throw new RangeException($this->input, RangeException::MINUTES_OUT_OF_RANGE);
}

// Get fractional minutes
Expand All @@ -266,13 +271,13 @@ private function minutes(): string|int
return (string) ((float) $minutes + (float) $this->seconds());
}

// If minutes is a float there will be no seconds
// If minutes is a float, there will be no seconds
if ($this->lexer->isNextToken(Lexer::T_FLOAT)) {
$minutes = $this->match(Lexer::T_FLOAT);

// Throw exception if minutes are greater than 60
if ($minutes > 60) {
throw $this->rangeError('Minutes', 60);
throw new RangeException($this->input, RangeException::MINUTES_OUT_OF_RANGE);
}

// Get fractional minutes
Expand Down Expand Up @@ -344,17 +349,6 @@ private function point(): float|int|array
return [$x, $y];
}

/**
* Create out of range exception.
*/
private function rangeError(string $type, int $high, ?int $low = null): RangeException
{
$range = null === $low ? sprintf('greater than %d', $high) : sprintf('out of range %d to %d', $low, $high);
$message = sprintf('[Range Error] Error: %s %s in value "%s"', $type, $range, $this->input);

return new RangeException($message);
}

/**
* Match and return seconds value.
*
Expand All @@ -368,7 +362,7 @@ private function seconds(): int|string

// Throw exception if seconds are greater than 60
if ($seconds > 60) {
throw $this->rangeError('Seconds', 60);
throw new RangeException($this->input, RangeException::SECONDS_OUT_OF_RANGE);
}

// Get fractional seconds
Expand Down
9 changes: 5 additions & 4 deletions tests/LongitudeOne/Geo/String/Tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ public static function dataSourceBad(): \Generator
yield ['55:34:22°', UnexpectedValueException::class, '[Syntax Error] line 0, col 8: Error: Expected LongitudeOne\Geo\String\Lexer::T_INTEGER or LongitudeOne\Geo\String\Lexer::T_FLOAT, got "°" in value "55:34:22°"'];
yield ['55:34.22', UnexpectedValueException::class, '[Syntax Error] line 0, col 3: Error: Expected LongitudeOne\Geo\String\Lexer::T_INTEGER, got "34.22" in value "55:34.22"'];
yield ['55#34.22', UnexpectedValueException::class, '[Syntax Error] line 0, col 2: Error: Expected LongitudeOne\Geo\String\Lexer::T_INTEGER or LongitudeOne\Geo\String\Lexer::T_FLOAT, got "#" in value "55#34.22"'];
yield ['200N', RangeException::class, '[Range Error] Error: Degrees out of range -90 to 90 in value "200N"'];
yield ['55:200:32', RangeException::class, '[Range Error] Error: Minutes greater than 60 in value "55:200:32"'];
yield ['55:20:99', RangeException::class, '[Range Error] Error: Seconds greater than 60 in value "55:20:99"'];
yield ['55°70.99\'', RangeException::class, '[Range Error] Error: Minutes greater than 60 in value "55°70.99\'"'];
yield ['100N', RangeException::class, '[RangeException] Latitude must be between -90 and 90, got "100N".'];
yield ['190W', RangeException::class, '[RangeException] Longitude must be between -180 and 180, got "190W".'];
yield ['55:200:32', RangeException::class, '[RangeException] Minutes must be between 0 and 59, got "55:200:32".'];
yield ['55:20:99', RangeException::class, '[RangeException] Seconds must be between 0 and 59, got "55:20:99".'];
yield ['55°70.99\'', RangeException::class, '[RangeException] Minutes must be between 0 and 59, got "55°70.99\'".'];
}

/**
Expand Down

0 comments on commit 8b851e9

Please sign in to comment.