Completed
Push — master ( 823036...442710 )
by Marcus
04:04
created

src/Location/Factory/CoordinateFactory.php (4 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Coordinate Factory
4
 *
5
 * @author   Marcus Jaschen <[email protected]>
6
 * @license  https://opensource.org/licenses/GPL-3.0 GPL
7
 * @link     https://github.com/mjaschen/phpgeo
8
 */
9
10
namespace Location\Factory;
11
12
use Location\Coordinate;
13
use Location\Ellipsoid;
14
15
/**
16
 * Coordinate Factory
17
 *
18
 * @author   Marcus Jaschen <[email protected]>
19
 * @license  https://opensource.org/licenses/GPL-3.0 GPL
20
 * @link     https://github.com/mjaschen/phpgeo
21
 */
22
class CoordinateFactory implements GeometryFactoryInterface
23
{
24
    /**
25
     * Creates a Coordinate instance from the given string.
26
     *
27
     * The string is parsed by a regular expression for a known
28
     * format of geographical coordinates.
29
     *
30
     * @param string $string formatted geographical coordinate
31
     * @param \Location\Ellipsoid $ellipsoid
32
     *
33
     * @return \Location\Coordinate
34
     */
35
    public static function fromString($string, Ellipsoid $ellipsoid = null)
36
    {
37
        $result = static::parseDecimalMinutesWithoutCardinalLetters($string, $ellipsoid);
0 ignored issues
show
Since parseDecimalMinutesWithoutCardinalLetters() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of parseDecimalMinutesWithoutCardinalLetters() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
38
39
        if ($result instanceof Coordinate) {
40
            return $result;
41
        }
42
43
        $result = static::parseDecimalMinutesWithCardinalLetters($string, $ellipsoid);
0 ignored issues
show
Since parseDecimalMinutesWithCardinalLetters() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of parseDecimalMinutesWithCardinalLetters() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
44
45
        if ($result instanceof Coordinate) {
46
            return $result;
47
        }
48
49
        $result = static::parseDecimalDegreesWithoutCardinalLetters($string, $ellipsoid);
0 ignored issues
show
Since parseDecimalDegreesWithoutCardinalLetters() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of parseDecimalDegreesWithoutCardinalLetters() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
50
51
        if ($result instanceof Coordinate) {
52
            return $result;
53
        }
54
55
        $result = static::parseDecimalDegreesWithCardinalLetters($string, $ellipsoid);
0 ignored issues
show
Since parseDecimalDegreesWithCardinalLetters() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of parseDecimalDegreesWithCardinalLetters() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
56
57
        if ($result instanceof Coordinate) {
58
            return $result;
59
        }
60
61
        throw new \InvalidArgumentException("Format of coordinates was not recognized");
62
    }
63
64
    private static function parseDecimalMinutesWithoutCardinalLetters($string, $ellipsoid)
65
    {
66
        // Decimal minutes without cardinal letters, e. g. "52 12.345, 13 23.456",
67
        // "52° 12.345, 13° 23.456", "52° 12.345′, 13° 23.456′", "52 12.345 N, 13 23.456 E",
68
        // "N52° 12.345′ E13° 23.456′"
69
        if (preg_match('/(-?\d{1,2})°?\s+(\d{1,2}\.?\d*)[\'′]?[, ]\s*(-?\d{1,3})°?\s+(\d{1,2}\.?\d*)[\'′]?/ui', $string, $match)) {
70
            $latitude = $match[1] >= 0 ? $match[1] + $match[2] / 60 : $match[1] - $match[2] / 60;
71
            $longitude = $match[3] >= 0 ? $match[3] + $match[4] / 60 : $match[3] - $match[4] / 60;
72
73
            return new Coordinate($latitude, $longitude, $ellipsoid);
74
        }
75
76
        return null;
77
    }
78
79
    private static function parseDecimalMinutesWithCardinalLetters($string, $ellipsoid)
80
    {
81
        // Decimal minutes with cardinal letters, e. g. "52 12.345, 13 23.456",
82
        // "52° 12.345, 13° 23.456", "52° 12.345′, 13° 23.456′", "52 12.345 N, 13 23.456 E",
83
        // "N52° 12.345′ E13° 23.456′"
84
        if (preg_match('/([NS]?\s*)(\d{1,2})°?\s+(\d{1,2}\.?\d*)[\'′]?(\s*[NS]?)[, ]\s*([EW]?\s*)(\d{1,3})°?\s+(\d{1,2}\.?\d*)[\'′]?(\s*[EW]?)/ui', $string, $match)) {
85
            $latitude = $match[2] + $match[3] / 60;
86 View Code Duplication
            if (trim(strtoupper($match[1])) === 'S' || trim(strtoupper($match[4])) === 'S') {
87
                $latitude = - $latitude;
88
            }
89
            $longitude = $match[6] + $match[7] / 60;
90 View Code Duplication
            if (trim(strtoupper($match[5])) === 'W' || trim(strtoupper($match[8])) === 'W') {
91
                $longitude = - $longitude;
92
            }
93
94
            return new Coordinate($latitude, $longitude, $ellipsoid);
95
        }
96
97
        return null;
98
    }
99
100
    private static function parseDecimalDegreesWithoutCardinalLetters($string, $ellipsoid)
101
    {
102
        // The most simple format: decimal degrees without cardinal letters,
103
        // e. g. "52.5, 13.5" or "53.25732 14.24984"
104
        if (preg_match('/(-?\d{1,2}\.?\d*)°?[, ]\s*(-?\d{1,3}\.?\d*)°?/u', $string, $match)) {
105
            return new Coordinate($match[1], $match[2], $ellipsoid);
106
        }
107
108
        return null;
109
    }
110
111
    private static function parseDecimalDegreesWithCardinalLetters($string, $ellipsoid)
112
    {
113
        // Decimal degrees with cardinal letters, e. g. "N52.5, E13.5",
114
        // "40.2S, 135.3485W", or "56.234°N, 157.245°W"
115
        if (preg_match('/([NS]?\s*)(\d{1,2}\.?\d*)°?(\s*[NS]?)[, ]\s*([EW]?\s*)(\d{1,3}\.?\d*)°?(\s*[EW]?)/ui', $string, $match)) {
116
            $latitude = $match[2];
117 View Code Duplication
            if (trim(strtoupper($match[1])) === 'S' || trim(strtoupper($match[3])) === 'S') {
118
                $latitude = - $latitude;
119
            }
120
            $longitude = $match[5];
121 View Code Duplication
            if (trim(strtoupper($match[4])) === 'W' || trim(strtoupper($match[6])) === 'W') {
122
                $longitude = - $longitude;
123
            }
124
125
            return new Coordinate($latitude, $longitude, $ellipsoid);
126
        }
127
128
        return null;
129
    }
130
}
131