Skip to content

Commit

Permalink
Fix columns that their cast is Geometry (#127)
Browse files Browse the repository at this point in the history
* fix geometry types

* fixes
  • Loading branch information
MatanYadaev authored Aug 3, 2024
1 parent 9f17fd8 commit e3308f5
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/GeometryCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,27 @@ public function set($model, string $key, $value, array $attributes): ?Expression
return $value;
}

if (! ($value instanceof $this->className) || get_class($value) !== $this->className) {
if (! $this->isCorrectGeometryType($value)) {
$geometryType = is_object($value) ? $value::class : gettype($value);
throw new InvalidArgumentException(
sprintf('Expected %s, %s given.', $this->className, $geometryType)
);
}

/** @var Geometry $value */

return $value->toSqlExpression($model->getConnection());
}

private function isCorrectGeometryType(mixed $value): bool
{
if ($this->className === Geometry::class && $value instanceof Geometry) {
return true;
}

return $value instanceof $this->className && get_class($value) === $this->className;
}

private function extractWktFromExpression(ExpressionContract $expression, Connection $connection): string
{
$grammar = $connection->getQueryGrammar();
Expand Down
96 changes: 96 additions & 0 deletions tests/Objects/GeometryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
use MatanYadaev\EloquentSpatial\Enums\Srid;
use MatanYadaev\EloquentSpatial\GeometryExpression;
use MatanYadaev\EloquentSpatial\Objects\Geometry;
use MatanYadaev\EloquentSpatial\Objects\GeometryCollection;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\MultiLineString;
use MatanYadaev\EloquentSpatial\Objects\MultiPoint;
use MatanYadaev\EloquentSpatial\Objects\MultiPolygon;
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 {
Expand Down Expand Up @@ -135,3 +140,94 @@
LineString::fromArray($pointGeoJsonArray);
})->toThrow(InvalidArgumentException::class);
});

it('creates a model record with geometry (point)', function (): void {
// Arrange
$point = Point::fromJson('{"type":"Point","coordinates":[0,180]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $point]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(Point::class);
expect($testPlace->geometry)->toEqual($point);
});

it('creates a model record with geometry (line string)', function (): void {
// Arrange
$lineString = LineString::fromJson('{"type":"LineString","coordinates":[[180,0],[179,1]]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $lineString]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(LineString::class);
expect($testPlace->geometry)->toEqual($lineString);
});

it('creates a model record with geometry (multi point)', function (): void {
// Arrange
$multiPoint = MultiPoint::fromJson('{"type":"MultiPoint","coordinates":[[180,0],[179,1]]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $multiPoint]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(MultiPoint::class);
expect($testPlace->geometry)->toEqual($multiPoint);
});

it('creates a model record with geometry (multi line string)', function (): void {
// Arrange
$multiLineString = MultiLineString::fromJson('{"type":"MultiLineString","coordinates":[[[180,0],[179,1]]]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $multiLineString]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(MultiLineString::class);
expect($testPlace->geometry)->toEqual($multiLineString);
});

it('creates a model record with geometry (polygon)', function (): void {
// Arrange
$polygon = Polygon::fromJson('{"type":"Polygon","coordinates":[[[180,0],[179,1],[180,1],[180,0]]]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $polygon]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(Polygon::class);
expect($testPlace->geometry)->toEqual($polygon);
});

it('creates a model record with geometry (multi polygon)', function (): void {
// Arrange
$multiPolygon = MultiPolygon::fromJson('{"type":"MultiPolygon","coordinates":[[[[180,0],[179,1],[180,1],[180,0]]]]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $multiPolygon]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(MultiPolygon::class);
expect($testPlace->geometry)->toEqual($multiPolygon);
});

it('creates a model record with geometry (geometry collection)', function (): void {
// Arrange
$geometryCollection = GeometryCollection::fromJson('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[0,180]}]}');

// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::factory()->create(['geometry' => $geometryCollection]);

// Assert
expect($testPlace->geometry)->toBeInstanceOf(GeometryCollection::class);
expect($testPlace->geometry)->toEqual($geometryCollection);
});
4 changes: 4 additions & 0 deletions tests/TestModels/TestPlace.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use MatanYadaev\EloquentSpatial\Objects\Geometry;
use MatanYadaev\EloquentSpatial\Objects\GeometryCollection;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\MultiLineString;
Expand All @@ -15,6 +16,7 @@
use MatanYadaev\EloquentSpatial\Traits\HasSpatial;

/**
* @property Geometry $geometry
* @property Point $point
* @property MultiPoint $multi_point
* @property LineString $line_string
Expand All @@ -35,6 +37,7 @@ class TestPlace extends Model

protected $fillable = [
'address',
'geometry',
'point',
'multi_point',
'line_string',
Expand All @@ -46,6 +49,7 @@ class TestPlace extends Model
];

protected $casts = [
'geometry' => Geometry::class,
'point' => Point::class,
'multi_point' => MultiPoint::class,
'line_string' => LineString::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public function up(): void
$table->timestamps();
$table->string('name');
$table->string('address');
$table->geometry('geometry')->nullable();
$table->point('point')->isGeometry()->nullable();
$table->multiPoint('multi_point')->isGeometry()->nullable();
$table->lineString('line_string')->isGeometry()->nullable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public function up(): void
$table->timestamps();
$table->string('name');
$table->string('address');
$table->geometry('geometry', subtype: 'geometry')->nullable();
$table->geometry('point', subtype: 'point')->nullable();
$table->geometry('multi_point', subtype: 'multipoint')->nullable();
$table->geometry('line_string', subtype: 'linestring')->nullable();
Expand Down

0 comments on commit e3308f5

Please sign in to comment.