Skip to content

Commit d11470b

Browse files
authored
Fix SRID not being optional for expression in GeometryCast (#124)
* Add test case to illustrate problems with regex to convert WKT to geometry * Adjust GeometryCast regex to support geometry expression without SRID * Formatting
1 parent 31c6882 commit d11470b

File tree

2 files changed

+36
-16
lines changed

2 files changed

+36
-16
lines changed

src/GeometryCast.php

+8-16
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ public function get($model, string $key, $value, array $attributes): ?Geometry
3636
}
3737

3838
if ($value instanceof ExpressionContract) {
39-
$wkt = $this->extractWktFromExpression($value, $model->getConnection());
40-
$srid = $this->extractSridFromExpression($value, $model->getConnection());
39+
$expressionValues = $this->extractFromExpression($value, $model->getConnection());
4140

42-
return $this->className::fromWkt($wkt, $srid);
41+
return $this->className::fromWkt($expressionValues['wkt'], $expressionValues['srid']);
4342
}
4443

4544
return $this->className::fromWkb($value);
@@ -87,23 +86,16 @@ private function isCorrectGeometryType(mixed $value): bool
8786
return $value instanceof $this->className && get_class($value) === $this->className;
8887
}
8988

90-
private function extractWktFromExpression(ExpressionContract $expression, Connection $connection): string
91-
{
92-
$grammar = $connection->getQueryGrammar();
93-
$expressionValue = $expression->getValue($grammar);
94-
95-
preg_match('/ST_GeomFromText\(\'(.+)\', .+(, .+)?\)/', (string) $expressionValue, $match);
96-
97-
return $match[1];
98-
}
99-
100-
private function extractSridFromExpression(ExpressionContract $expression, Connection $connection): int
89+
/**
90+
* @return array{wkt: string, srid: int}
91+
*/
92+
private function extractFromExpression(ExpressionContract $expression, Connection $connection): array
10193
{
10294
$grammar = $connection->getQueryGrammar();
10395
$expressionValue = $expression->getValue($grammar);
10496

105-
preg_match('/ST_GeomFromText\(\'.+\', (.+)(, .+)?\)/', (string) $expressionValue, $match);
97+
preg_match("/ST_GeomFromText\(\s*'([^']+)'\s*(?:,\s*(\d+))?\s*(?:,\s*'([^']+)')?\s*\)/", (string) $expressionValue, $matches);
10698

107-
return (int) $match[1];
99+
return ['wkt' => $matches[1], 'srid' => (int) ($matches[2] ?? 0)];
108100
}
109101
}

tests/GeometryCastTest.php

+28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
use Illuminate\Support\Facades\DB;
4+
use MatanYadaev\EloquentSpatial\AxisOrder;
45
use MatanYadaev\EloquentSpatial\Enums\Srid;
56
use MatanYadaev\EloquentSpatial\GeometryExpression;
67
use MatanYadaev\EloquentSpatial\Objects\LineString;
@@ -189,3 +190,30 @@
189190

190191
expect($testPlace->isDirty())->toBeFalse();
191192
});
193+
194+
it('handles ST_GeomFromText optional values on a raw expression', function (string $expression): void {
195+
// Arrange
196+
$testPlace = TestPlace::factory()->create(['point' => DB::raw($expression)]);
197+
198+
// Act
199+
$testPlace->point = null;
200+
201+
// Assert
202+
// Will trigger 'point' attribute to cast raw expression to a Point object
203+
expect($testPlace->isDirty())->toBeTrue();
204+
})->with([
205+
'without SRID' => "ST_GeomFromText('POINT(12.38057 55.73406)')",
206+
'with SRID' => "ST_GeomFromText('POINT(12.38057 55.73406)', 4326)",
207+
]);
208+
209+
it('handles ST_GeomFromText option for mysql on a raw expression', function (): void {
210+
// Arrange
211+
$testPlace = TestPlace::factory()->create(['point' => DB::raw("ST_GeomFromText('POINT(12.38057 55.73406)', 4326, 'axis-order=long-lat')")]);
212+
213+
// Act
214+
$testPlace->point = null;
215+
216+
// Assert
217+
// Will trigger 'point' attribute to cast raw expression to a Point object
218+
expect($testPlace->isDirty())->toBeTrue();
219+
})->skip(fn () => ! AxisOrder::supported(DB::connection()));

0 commit comments

Comments
 (0)