Skip to content

Commit 4ca6a89

Browse files
grimzyChrissi2812
authored andcommitted
Added fromJson($geoJson) to GeometryInterface (#23)
(cherry picked from commit 8e0119e)
1 parent 6337d15 commit 4ca6a89

20 files changed

+465
-6
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Grimzy\LaravelMysqlSpatial\Exceptions;
4+
5+
class InvalidGeoJsonException extends \RuntimeException
6+
{
7+
}

src/Types/Geometry.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

55
use GeoIO\WKB\Parser\Parser;
6+
use GeoJson\GeoJson;
67
use Grimzy\LaravelMysqlSpatial\Exceptions\UnknownWKTTypeException;
78
use Illuminate\Contracts\Support\Jsonable;
89

@@ -71,6 +72,23 @@ public static function fromWKT($wkt)
7172
return static::fromString($wktArgument);
7273
}
7374

75+
public static function fromJson($geoJson) {
76+
if(is_string($geoJson)) {
77+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
78+
}
79+
80+
if($geoJson->getType() === 'FeatureCollection') {
81+
return GeometryCollection::fromJson($geoJson);
82+
}
83+
84+
if($geoJson->getType() === 'Feature') {
85+
$geoJson = $geoJson->getGeometry();
86+
}
87+
88+
$type = '\Grimzy\LaravelMysqlSpatial\Types\\'.$geoJson->getType();
89+
return $type::fromJson($geoJson);
90+
}
91+
7492
public function toJson($options = 0)
7593
{
7694
return json_encode($this, $options);

src/Types/GeometryCollection.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
use ArrayAccess;
66
use ArrayIterator;
77
use Countable;
8+
use GeoJson\Feature\FeatureCollection;
9+
use GeoJson\GeoJson;
10+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
811
use Illuminate\Contracts\Support\Arrayable;
912
use InvalidArgumentException;
1013
use IteratorAggregate;
@@ -107,6 +110,24 @@ public function count()
107110
return count($this->items);
108111
}
109112

113+
public static function fromJson ($geoJson)
114+
{
115+
if(is_string($geoJson)) {
116+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
117+
}
118+
119+
if(!is_a($geoJson, FeatureCollection::class)) {
120+
throw new InvalidGeoJsonException('Expected ' . FeatureCollection::class . ', got ' . get_class($geoJson));
121+
}
122+
123+
$set = [];
124+
foreach ($geoJson->getFeatures() as $feature) {
125+
$set[] = parent::fromJson($feature);
126+
}
127+
128+
return new GeometryCollection($set);
129+
}
130+
110131
/**
111132
* Convert to GeoJson GeometryCollection that is jsonable to GeoJSON.
112133
*

src/Types/GeometryInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ public static function fromWKT($wkt);
1111
public function __toString();
1212

1313
public static function fromString($wktArgument);
14+
15+
public static function fromJson($geoJson);
1416
}

src/Types/LineString.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

5+
use GeoJson\GeoJson;
6+
use GeoJson\Geometry\LineString as GeoJsonLineString;
7+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
8+
59
class LineString extends PointCollection
610
{
711
public function toWKT()
@@ -31,6 +35,24 @@ public function __toString()
3135
return $this->toPairList();
3236
}
3337

38+
public static function fromJson ($geoJson)
39+
{
40+
if(is_string($geoJson)) {
41+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
42+
}
43+
44+
if(!is_a($geoJson, GeoJsonLineString::class)) {
45+
throw new InvalidGeoJsonException('Expected ' . GeoJsonLineString::class . ', got ' . get_class($geoJson));
46+
}
47+
48+
$set = [];
49+
foreach($geoJson->getCoordinates() as $coordinate) {
50+
$set[] = new Point($coordinate[1], $coordinate[0]);
51+
}
52+
53+
return new LineString($set);
54+
}
55+
3456
/**
3557
* Convert to GeoJson LineString that is jsonable to GeoJSON.
3658
*
@@ -43,6 +65,6 @@ public function jsonSerialize()
4365
$points[] = $point->jsonSerialize();
4466
}
4567

46-
return new \GeoJson\Geometry\LineString($points);
68+
return new GeoJsonLineString($points);
4769
}
4870
}

src/Types/MultiLineString.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

5+
use GeoJson\GeoJson;
6+
use GeoJson\Geometry\MultiLineString as GeoJsonMultiLineString;
7+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
58
use InvalidArgumentException;
69

710
class MultiLineString extends GeometryCollection
@@ -62,6 +65,28 @@ public function offsetSet($offset, $value)
6265
parent::offsetSet($offset, $value);
6366
}
6467

68+
public static function fromJson ($geoJson)
69+
{
70+
if(is_string($geoJson)) {
71+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
72+
}
73+
74+
if(!is_a($geoJson, GeoJsonMultiLineString::class)) {
75+
throw new InvalidGeoJsonException('Expected ' . GeoJsonMultiLineString::class . ', got ' . get_class($geoJson));
76+
}
77+
78+
$set = [];
79+
foreach($geoJson->getCoordinates() as $coordinates) {
80+
$points = [];
81+
foreach($coordinates as $coordinate) {
82+
$points[] = new Point($coordinate[1], $coordinate[0]);
83+
}
84+
$set[] = new LineString($points);
85+
}
86+
87+
return new MultiLineString($set);
88+
}
89+
6590
/**
6691
* Convert to GeoJson Point that is jsonable to GeoJSON.
6792
*
@@ -75,6 +100,6 @@ public function jsonSerialize()
75100
$lineStrings[] = $lineString->jsonSerialize();
76101
}
77102

78-
return new \GeoJson\Geometry\MultiLineString($lineStrings);
103+
return new GeoJsonMultiLineString($lineStrings);
79104
}
80105
}

src/Types/MultiPoint.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

5+
use GeoJson\GeoJson;
6+
use GeoJson\Geometry\MultiPoint as GeoJsonMultiPoint;
7+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
8+
59
class MultiPoint extends PointCollection
610
{
711
public function toWKT()
@@ -35,6 +39,24 @@ public function __toString()
3539
}, $this->items));
3640
}
3741

42+
public static function fromJson ($geoJson)
43+
{
44+
if(is_string($geoJson)) {
45+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
46+
}
47+
48+
if(!is_a($geoJson, GeoJsonMultiPoint::class)) {
49+
throw new InvalidGeoJsonException('Expected ' . GeoJsonMultiPoint::class . ', got ' . get_class($geoJson));
50+
}
51+
52+
$set = [];
53+
foreach($geoJson->getCoordinates() as $coordinate) {
54+
$set[] = new Point($coordinate[1], $coordinate[0]);
55+
}
56+
57+
return new MultiPoint($set);
58+
}
59+
3860
/**
3961
* Convert to GeoJson MultiPoint that is jsonable to GeoJSON.
4062
*
@@ -47,6 +69,6 @@ public function jsonSerialize()
4769
$points[] = $point->jsonSerialize();
4870
}
4971

50-
return new \GeoJson\Geometry\MultiPoint($points);
72+
return new GeoJsonMultiPoint($points);
5173
}
5274
}

src/Types/MultiPolygon.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

5+
use GeoJson\GeoJson;
6+
use GeoJson\Geometry\MultiPolygon as GeoJsonMultiPolygon;
7+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
58
use InvalidArgumentException;
69

710
class MultiPolygon extends GeometryCollection
@@ -97,6 +100,32 @@ public function offsetSet($offset, $value)
97100
parent::offsetSet($offset, $value);
98101
}
99102

103+
public static function fromJson ($geoJson)
104+
{
105+
if(is_string($geoJson)) {
106+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
107+
}
108+
109+
if(!is_a($geoJson, GeoJsonMultiPolygon::class)) {
110+
throw new InvalidGeoJsonException('Expected ' . GeoJsonMultiPolygon::class . ', got ' . get_class($geoJson));
111+
}
112+
113+
$set = [];
114+
foreach($geoJson->getCoordinates() as $polygonCoordinates) {
115+
$lineStrings = [];
116+
foreach($polygonCoordinates as $lineStringCoordinates) {
117+
$points = [];
118+
foreach($lineStringCoordinates as $lineStringCoordinate) {
119+
$points[] = new Point($lineStringCoordinate[1], $lineStringCoordinate[0]);
120+
}
121+
$lineStrings[] = new LineString($points);
122+
}
123+
$set[] = new Polygon($lineStrings);
124+
}
125+
126+
return new MultiPolygon($set);
127+
}
128+
100129
/**
101130
* Convert to GeoJson MultiPolygon that is jsonable to GeoJSON.
102131
*
@@ -109,6 +138,6 @@ public function jsonSerialize()
109138
$polygons[] = $polygon->jsonSerialize();
110139
}
111140

112-
return new \GeoJson\Geometry\MultiPolygon($polygons);
141+
return new GeoJsonMultiPolygon($polygons);
113142
}
114143
}

src/Types/Point.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

5+
use GeoJson\GeoJson;
6+
use GeoJson\Geometry\Point as GeoJsonPoint;
7+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
8+
59
class Point extends Geometry
610
{
711
protected $lat;
@@ -61,13 +65,31 @@ public function __toString()
6165
return $this->getLng().' '.$this->getLat();
6266
}
6367

68+
/**
69+
* @param $geoJson \GeoJson\Feature\Feature|string
70+
* @return \Grimzy\LaravelMysqlSpatial\Types\Point
71+
*/
72+
public static function fromJson ($geoJson)
73+
{
74+
if(is_string($geoJson)) {
75+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
76+
}
77+
78+
if(!is_a($geoJson, GeoJsonPoint::class)) {
79+
throw new InvalidGeoJsonException('Expected ' . GeoJsonPoint::class . ', got ' . get_class($geoJson));
80+
}
81+
82+
$coordinates = $geoJson->getCoordinates();
83+
return new Point($coordinates[1], $coordinates[0]);
84+
}
85+
6486
/**
6587
* Convert to GeoJson Point that is jsonable to GeoJSON.
6688
*
6789
* @return \GeoJson\Geometry\Point
6890
*/
6991
public function jsonSerialize()
7092
{
71-
return new \GeoJson\Geometry\Point([$this->getLng(), $this->getLat()]);
93+
return new GeoJsonPoint([$this->getLng(), $this->getLat()]);
7294
}
7395
}

src/Types/Polygon.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,39 @@
22

33
namespace Grimzy\LaravelMysqlSpatial\Types;
44

5+
use GeoJson\GeoJson;
6+
use GeoJson\Geometry\Polygon as GeoJsonPolygon;
7+
use Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException;
8+
59
class Polygon extends MultiLineString
610
{
711
public function toWKT()
812
{
913
return sprintf('POLYGON(%s)', (string) $this);
1014
}
1115

16+
public static function fromJson ($geoJson)
17+
{
18+
if(is_string($geoJson)) {
19+
$geoJson = GeoJson::jsonUnserialize(json_decode($geoJson));
20+
}
21+
22+
if(!is_a($geoJson, GeoJsonPolygon::class)) {
23+
throw new InvalidGeoJsonException('Expected ' . GeoJsonPolygon::class . ', got ' . get_class($geoJson));
24+
}
25+
26+
$set = [];
27+
foreach($geoJson->getCoordinates() as $coordinates) {
28+
$points = [];
29+
foreach($coordinates as $coordinate) {
30+
$points[] = new Point($coordinate[1], $coordinate[0]);
31+
}
32+
$set[] = new LineString($points);
33+
}
34+
35+
return new Polygon($set);
36+
}
37+
1238
/**
1339
* Convert to GeoJson Polygon that is jsonable to GeoJSON.
1440
*
@@ -21,6 +47,6 @@ public function jsonSerialize()
2147
$linearRings[] = new \GeoJson\Geometry\LinearRing($lineString->jsonSerialize()->getCoordinates());
2248
}
2349

24-
return new \GeoJson\Geometry\Polygon($linearRings);
50+
return new GeoJsonPolygon($linearRings);
2551
}
2652
}

tests/Unit/Eloquent/SpatialTraitTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use Grimzy\LaravelMysqlSpatial\Exceptions\SpatialFieldsNotDefinedException;
34
use Grimzy\LaravelMysqlSpatial\MysqlConnection;
45
use Grimzy\LaravelMysqlSpatial\Types\Point;
56
use Illuminate\Database\Eloquent\Model;
@@ -191,6 +192,19 @@ public function testInsertUpdateGeometryCollectionHasCorrectSql()
191192
$this->assertContains("GeomFromText('GEOMETRYCOLLECTION(POINT(2 1),LINESTRING(3 2,3 3))')", $this->queries[1]);
192193
}
193194

195+
public function testSettingRawAttributes() {
196+
$attributes['point'] = '0101000000000000000000f03f0000000000000040';
197+
198+
$this->model->setRawAttributes($attributes);
199+
$this->assertInstanceOf(Point::class, ($this->model->point));
200+
}
201+
202+
public function testSpatialFieldsNotDefinedException() {
203+
$model = new TestNoSpatialModel();
204+
$this->setExpectedException(SpatialFieldsNotDefinedException::class);
205+
$model->getSpatialFields();
206+
}
207+
194208
public function testScopeDistance()
195209
{
196210
$point = new Point(1, 2);
@@ -389,6 +403,10 @@ public function testmodels()
389403
}
390404
}
391405

406+
class TestNoSpatialModel extends Model {
407+
use \Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
408+
}
409+
392410
class TestPDO extends PDO
393411
{
394412
public $queries = [];

0 commit comments

Comments
 (0)