Skip to content

Commit

Permalink
fix geometry types
Browse files Browse the repository at this point in the history
  • Loading branch information
MatanYadaev committed Aug 3, 2024
1 parent 9f17fd8 commit 85c2e7f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/GeometryCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ 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)
Expand All @@ -76,6 +76,15 @@ public function set($model, string $key, $value, array $attributes): ?Expression
return $value->toSqlExpression($model->getConnection());

Check failure on line 76 in src/GeometryCast.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3)

Cannot call method toSqlExpression() on mixed.

Check failure on line 76 in src/GeometryCast.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2)

Cannot call method toSqlExpression() on mixed.
}

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 @@ -8,6 +8,11 @@
use MatanYadaev\EloquentSpatial\GeometryExpression;
use MatanYadaev\EloquentSpatial\Objects\Geometry;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\MultiPoint;
use MatanYadaev\EloquentSpatial\Objects\MultiLineString;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
use MatanYadaev\EloquentSpatial\Objects\MultiPolygon;
use MatanYadaev\EloquentSpatial\Objects\GeometryCollection;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Tests\TestModels\TestPlace;

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')->isGeometry()->nullable();

Check failure on line 16 in tests/database/migrations-laravel-<=10/0000_00_00_000000_create_test_places_table.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3)

Call to an undefined method Illuminate\Database\Schema\ColumnDefinition::isGeometry().

Check failure on line 16 in tests/database/migrations-laravel-<=10/0000_00_00_000000_create_test_places_table.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2)

Call to an undefined method Illuminate\Database\Schema\ColumnDefinition::isGeometry().
$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 85c2e7f

Please sign in to comment.