1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Spinen\Geometry; |
4
|
|
|
|
5
|
|
|
use Exception; |
6
|
|
|
use geoPHP; |
7
|
|
|
use Illuminate\Contracts\Foundation\Application; |
8
|
|
|
use InvalidArgumentException; |
9
|
|
|
use RuntimeException; |
10
|
|
|
use Spinen\Geometry\Support\TypeMapper; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class Geometry |
14
|
|
|
* |
15
|
|
|
* @package Spinen\Geometry |
16
|
|
|
* |
17
|
|
|
* @method mixed parseEwkb(mixed $data) Parses data into EWKB format. |
18
|
|
|
* @method mixed parseEwkt(mixed $data) Parses data into EWKT format. |
19
|
|
|
* @method mixed parseGeoHash(mixed $data) Parses data into GeoHash format. |
20
|
|
|
* @method mixed parseGeoJson(mixed $data) Parses data into GeoJSON format. |
21
|
|
|
* @method mixed parseGeoRss(mixed $data) Parses data into GeoRSS format. |
22
|
|
|
* @method mixed parseGoogleGeocode(mixed $data) Parses data into GoogleGeocode format. |
23
|
|
|
* @method mixed parseGpx(mixed $data) Parses data into GPX format. |
24
|
|
|
* @method mixed parseJson(mixed $data) Parses data into GeoJSON format. |
25
|
|
|
* @method mixed parseKml(mixed $data) Parses data into KML format. |
26
|
|
|
* @method mixed parseWkb(mixed $data) Parses data into WKB format. |
27
|
|
|
* @method mixed parseWkt(mixed $data) Parses data into WKT format. |
28
|
|
|
*/ |
29
|
|
|
class Geometry |
30
|
|
|
{ |
31
|
|
|
/** |
32
|
|
|
* The Laravel application. |
33
|
|
|
* |
34
|
|
|
* @var Application|null |
35
|
|
|
*/ |
36
|
|
|
protected $app; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Instance of geoPHP. |
40
|
|
|
* |
41
|
|
|
* @var geoPHP |
42
|
|
|
*/ |
43
|
|
|
protected $geoPhp; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Instance of TypeMapper. |
47
|
|
|
* |
48
|
|
|
* @var TypeMapper |
49
|
|
|
*/ |
50
|
|
|
protected $mapper; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Geometry constructor. |
54
|
|
|
* |
55
|
|
|
* @param geoPHP $geoPhp |
56
|
|
|
* @param TypeMapper $mapper |
57
|
|
|
* @param Application|null $app |
58
|
|
|
*/ |
59
|
14 |
|
public function __construct(geoPHP $geoPhp, TypeMapper $mapper, $app = null) |
60
|
|
|
{ |
61
|
14 |
|
$this->geoPhp = $geoPhp; |
62
|
14 |
|
$this->mapper = $mapper; |
63
|
14 |
|
$this->app = $app; |
64
|
14 |
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Magic method to allow methods that are not specifically defined. |
68
|
|
|
* |
69
|
|
|
* Allow parseStudlyCaseOfType i.e. parseWkt or parseGeoJson to be called & mapped to the load method. |
70
|
|
|
* |
71
|
|
|
* @param string $name Name of the undefined method |
72
|
|
|
* @param array $arguments |
73
|
|
|
* |
74
|
|
|
* @return bool|\GeometryCollection|mixed |
75
|
|
|
* @throws RuntimeException |
76
|
|
|
*/ |
77
|
10 |
|
public function __call($name, $arguments) |
78
|
|
|
{ |
79
|
|
|
// Sugar to make parse<Format>() work |
80
|
10 |
View Code Duplication |
if (preg_match("/^parse([A-Z][A-z]*)/u", $name, $parts) && 1 === count($arguments)) { |
|
|
|
|
81
|
9 |
|
return $this->parse($arguments[0], $parts[1]); |
82
|
|
|
} |
83
|
|
|
|
84
|
1 |
|
throw new RuntimeException(sprintf("Call to undefined method %s::%s().", __CLASS__, $name)); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Build the name to the proxy geometry class. |
89
|
|
|
* |
90
|
|
|
* @param $geometry |
91
|
|
|
* |
92
|
|
|
* @return string |
93
|
|
|
* @throws InvalidArgumentException|RuntimeException |
94
|
|
|
*/ |
95
|
11 |
|
public function buildGeometryClassName($geometry) |
96
|
|
|
{ |
97
|
11 |
|
if (is_null($geometry)) { |
98
|
1 |
|
throw new InvalidArgumentException("The geometry object cannot be null when building the name to the proxy class."); |
99
|
|
|
} |
100
|
|
|
|
101
|
10 |
|
$class = __NAMESPACE__ . '\Geometries\\' . get_class($geometry); |
102
|
|
|
|
103
|
10 |
|
if (class_exists($class)) { |
104
|
9 |
|
return $class; |
105
|
|
|
} |
106
|
|
|
|
107
|
1 |
|
throw new RuntimeException(sprintf("There proxy class [%s] is not defined.", $class)); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Call geoPHP to load the data. |
112
|
|
|
* |
113
|
|
|
* @param string|object $data |
114
|
|
|
* @param string|null $type |
115
|
|
|
* |
116
|
|
|
* @return bool|\GeometryCollection|mixed |
117
|
|
|
* @throws Exception |
118
|
|
|
*/ |
119
|
10 |
|
protected function loadGeometry($data, $type) |
120
|
|
|
{ |
121
|
10 |
|
if (is_null($type)) { |
122
|
1 |
|
return $this->geoPhp->load($data); |
123
|
|
|
} |
124
|
|
|
|
125
|
9 |
|
return $this->geoPhp->load($data, $this->mapper->map($type)); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Pass the data to geoPHP to convert to the correct geometry type. |
130
|
|
|
* |
131
|
|
|
* @param string $data |
132
|
|
|
* @param string $type |
133
|
|
|
* |
134
|
|
|
* @return bool|\GeometryCollection|mixed |
135
|
|
|
* @throws Exception|InvalidArgumentException |
136
|
|
|
*/ |
137
|
10 |
|
public function parse($data, $type = null) |
138
|
|
|
{ |
139
|
10 |
|
$geometry = $this->loadGeometry($data, $type); |
140
|
|
|
|
141
|
10 |
|
if (is_null($geometry)) { |
142
|
1 |
|
throw new InvalidArgumentException("Could not parse the supplied data."); |
143
|
|
|
} |
144
|
|
|
|
145
|
9 |
|
$geometry_class = $this->buildGeometryClassName($geometry); |
146
|
|
|
|
147
|
|
|
// If running in Laravel, then use the IoC |
148
|
9 |
|
if (!is_null($this->app)) { |
149
|
1 |
|
return $this->app->make($geometry_class, [$geometry, $this->mapper]); |
150
|
|
|
} |
151
|
|
|
|
152
|
8 |
|
return new $geometry_class($geometry, $this->mapper); |
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.