diff --git a/src/GeometryCast.php b/src/GeometryCast.php index fe60b88..3b580c0 100644 --- a/src/GeometryCast.php +++ b/src/GeometryCast.php @@ -36,10 +36,9 @@ public function get($model, string $key, $value, array $attributes): ?Geometry } if ($value instanceof ExpressionContract) { - $wkt = $this->extractWktFromExpression($value, $model->getConnection()); - $srid = $this->extractSridFromExpression($value, $model->getConnection()); + $expressionValues = $this->extractFromExpression($value, $model->getConnection()); - return $this->className::fromWkt($wkt, $srid); + return $this->className::fromWkt($expressionValues['wkt'], $expressionValues['srid']); } return $this->className::fromWkb($value); @@ -87,23 +86,16 @@ private function isCorrectGeometryType(mixed $value): bool return $value instanceof $this->className && get_class($value) === $this->className; } - private function extractWktFromExpression(ExpressionContract $expression, Connection $connection): string - { - $grammar = $connection->getQueryGrammar(); - $expressionValue = $expression->getValue($grammar); - - preg_match('/ST_GeomFromText\(\'(.+)\', .+(, .+)?\)/', (string) $expressionValue, $match); - - return $match[1]; - } - - private function extractSridFromExpression(ExpressionContract $expression, Connection $connection): int + /** + * @return array{wkt: string, srid: int} + */ + private function extractFromExpression(ExpressionContract $expression, Connection $connection): array { $grammar = $connection->getQueryGrammar(); $expressionValue = $expression->getValue($grammar); - preg_match('/ST_GeomFromText\(\'.+\', (.+)(, .+)?\)/', (string) $expressionValue, $match); + preg_match("/ST_GeomFromText\(\s*'([^']+)'\s*(?:,\s*(\d+))?\s*(?:,\s*'([^']+)')?\s*\)/", (string) $expressionValue, $matches); - return (int) $match[1]; + return ['wkt' => $matches[1], 'srid' => (int) ($matches[2] ?? 0)]; } } diff --git a/tests/GeometryCastTest.php b/tests/GeometryCastTest.php index 5f98015..bcd0569 100644 --- a/tests/GeometryCastTest.php +++ b/tests/GeometryCastTest.php @@ -1,6 +1,7 @@ isDirty())->toBeFalse(); }); + +it('handles ST_GeomFromText optional values on a raw expression', function (string $expression): void { + // Arrange + $testPlace = TestPlace::factory()->create(['point' => DB::raw($expression)]); + + // Act + $testPlace->point = null; + + // Assert + // Will trigger 'point' attribute to cast raw expression to a Point object + expect($testPlace->isDirty())->toBeTrue(); +})->with([ + 'without SRID' => "ST_GeomFromText('POINT(12.38057 55.73406)')", + 'with SRID' => "ST_GeomFromText('POINT(12.38057 55.73406)', 4326)", +]); + +it('handles ST_GeomFromText option for mysql on a raw expression', function (): void { + // Arrange + $testPlace = TestPlace::factory()->create(['point' => DB::raw("ST_GeomFromText('POINT(12.38057 55.73406)', 4326, 'axis-order=long-lat')")]); + + // Act + $testPlace->point = null; + + // Assert + // Will trigger 'point' attribute to cast raw expression to a Point object + expect($testPlace->isDirty())->toBeTrue(); +})->skip(fn () => ! AxisOrder::supported(DB::connection()));