diff --git a/API.md b/API.md index 3aa9b33..2b17063 100644 --- a/API.md +++ b/API.md @@ -13,6 +13,7 @@ Geometry classes can be also created by these static methods: * `fromJson(string $geoJson, int $srid = 0)` - Creates a geometry object from a [GeoJSON](https://en.wikipedia.org/wiki/GeoJSON) string. +* `fromArray(array $geometry)` - Creates a geometry object from a array. Reverse to `->toArray()` method. * `fromWkt(string $wkt, int $srid = 0)` - Creates a geometry object from a [WKT](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry). * `fromWkb(string $wkb, int $srid = 0)` - Creates a geometry object from a [WKB](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary). diff --git a/src/GeometryCast.php b/src/GeometryCast.php index 4339c92..62102a8 100644 --- a/src/GeometryCast.php +++ b/src/GeometryCast.php @@ -62,6 +62,10 @@ public function set($model, string $key, $value, array $attributes): Expression| return null; } + if (is_array($value)) { + $value = Geometry::fromArray($value); + } + if (! ($value instanceof $this->className)) { $geometryType = is_object($value) ? $value::class : gettype($value); throw new InvalidArgumentException( diff --git a/src/Objects/Geometry.php b/src/Objects/Geometry.php index 6e6b438..c02e243 100644 --- a/src/Objects/Geometry.php +++ b/src/Objects/Geometry.php @@ -106,26 +106,35 @@ public static function fromWkt(string $wkt, int $srid = 0): static return $geometry; } - /** - * @param string $geoJson - * @param int $srid - * @return static - * - * @throws InvalidArgumentException - */ - public static function fromJson(string $geoJson, int $srid = 0): static - { - $geometry = Factory::parse($geoJson); - $geometry->srid = $srid; - - if (! ($geometry instanceof static)) { - throw new InvalidArgumentException( - sprintf('Expected %s, %s given.', static::class, $geometry::class) - ); + /** + * @param string $geoJson + * @param int $srid + * @return static + * + * @throws InvalidArgumentException + */ + public static function fromJson(string $geoJson, int $srid = 0): static + { + $geometry = Factory::parse($geoJson); + $geometry->srid = $srid; + + if (! ($geometry instanceof static)) { + throw new InvalidArgumentException( + sprintf('Expected %s, %s given.', static::class, $geometry::class) + ); + } + + return $geometry; } - return $geometry; - } + /** + * @param array $geometry + * @return static + */ + public static function fromArray(array $geometry): static + { + return static::fromJson(json_encode($geometry)); + } /** * @return array diff --git a/tests/Objects/GeometryCollectionTest.php b/tests/Objects/GeometryCollectionTest.php index 8f7a9e8..423007e 100644 --- a/tests/Objects/GeometryCollectionTest.php +++ b/tests/Objects/GeometryCollectionTest.php @@ -52,22 +52,22 @@ }); it('creates geometry collection from JSON', function (): void { - $geometryCollection = new GeometryCollection([ - new Polygon([ - new LineString([ - new Point(0, 180), - new Point(1, 179), - new Point(2, 178), - new Point(3, 177), - new Point(0, 180), + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(0, 180), + new Point(1, 179), + new Point(2, 178), + new Point(3, 177), + new Point(0, 180), + ]), ]), - ]), - new Point(0, 180), - ]); + new Point(0, 180), + ]); - $geometryCollectionFromJson = GeometryCollection::fromJson('{"type":"GeometryCollection","geometries":[{"type":"Polygon","coordinates":[[[180,0],[179,1],[178,2],[177,3],[180,0]]]},{"type":"Point","coordinates":[180,0]}]}'); + $geometryCollectionFromJson = GeometryCollection::fromJson('{"type":"GeometryCollection","geometries":[{"type":"Polygon","coordinates":[[[180,0],[179,1],[178,2],[177,3],[180,0]]]},{"type":"Point","coordinates":[180,0]}]}'); - expect($geometryCollectionFromJson)->toEqual($geometryCollection); + expect($geometryCollectionFromJson)->toEqual($geometryCollection); }); it('creates geometry collection with SRID from JSON', function (): void { diff --git a/tests/Objects/GeometryTest.php b/tests/Objects/GeometryTest.php index 06fc3b6..2a900b6 100644 --- a/tests/Objects/GeometryTest.php +++ b/tests/Objects/GeometryTest.php @@ -3,8 +3,11 @@ use Illuminate\Database\QueryException; use Illuminate\Support\Facades\DB; use MatanYadaev\EloquentSpatial\AxisOrder; +use MatanYadaev\EloquentSpatial\Objects\Geometry; +use MatanYadaev\EloquentSpatial\Objects\GeometryCollection; use MatanYadaev\EloquentSpatial\Objects\LineString; use MatanYadaev\EloquentSpatial\Objects\Point; +use MatanYadaev\EloquentSpatial\Objects\Polygon; use MatanYadaev\EloquentSpatial\Tests\TestModels\TestPlace; it('throws exception when generating geometry from other geometry WKB', function (): void { @@ -78,3 +81,45 @@ LineString::fromJson($pointJson); })->toThrow(InvalidArgumentException::class); }); + +it('creates geometry collection from array (serialized model)', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(0, 180), + new Point(1, 179), + new Point(2, 178), + new Point(3, 177), + new Point(0, 180), + ]), + ]), + new Point(0, 180), + ]); + $geometryCollectionArray = $geometryCollection->toArray(); + + $geometryCollectionFromArray = GeometryCollection::fromArray($geometryCollectionArray); + + expect($geometryCollectionFromArray)->toEqual($geometryCollection); +}); + +it('throws exception when generating geometry from wrong array', function (): void { + expect(function (): void { + $geometryCollectionArray = [ + 'type' => 'Point2', + 'coordinates' => [0, 180], + ]; + + Geometry::fromArray($geometryCollectionArray); + })->toThrow(InvalidArgumentException::class); +}); + +it('throws exception when generating geometry from other geometry array', function (): void { + expect(function (): void { + $geometryCollectionArray = [ + 'type' => 'Point', + 'coordinates' => [0, 180], + ]; + + LineString::fromArray($geometryCollectionArray); + })->toThrow(InvalidArgumentException::class); +});