Skip to content

Commit ffd5750

Browse files
MatanYadaevMatan Yadaev
and
Matan Yadaev
authored
Improve casting (#39)
* Run PHPInsights on CI * Fix PHPStan * Add `XDEBUG_MODE=coverage` to tests with coverage * Improve casts * Test `fromWkt` * Add tests * Fix PHPInsights * Fix lint * Remove `->fresh()` after model creation * Rename tests * Add update-chanelog action * Remove `prefer-lowest` * fix test Co-authored-by: Matan Yadaev <[email protected]>
1 parent ab2eff9 commit ffd5750

19 files changed

+249
-65
lines changed

.github/workflows/phpinsights.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ jobs:
2121
- name: Install dependencies
2222
run: composer install --prefer-dist --no-interaction
2323

24-
# Package is broken
25-
# - name: Run PHPInsights
26-
# run: ./vendor/bin/phpinsights --no-interaction --ansi --format=github-action
24+
- name: Run PHPInsights
25+
run: ./vendor/bin/phpinsights --no-interaction --ansi --format=github-action
26+

.github/workflows/phpunit.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ jobs:
1313
matrix:
1414
php: [8.1, 8.0]
1515
laravel: [9.*, 8.*]
16-
dependency-version: [prefer-lowest, prefer-stable]
16+
# dependency-version: [prefer-lowest, prefer-stable]
17+
dependency-version: [prefer-stable]
1718
include:
1819
- laravel: 8.*
1920
testbench: ^6.23
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Update Changelog
2+
3+
on:
4+
release:
5+
types: [released]
6+
7+
jobs:
8+
update:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Checkout code
13+
uses: actions/checkout@v2
14+
with:
15+
ref: master
16+
17+
- name: Update Changelog
18+
uses: stefanzweifel/changelog-updater-action@v1
19+
with:
20+
latest-version: ${{ github.event.release.name }}
21+
release-notes: ${{ github.event.release.body }}
22+
23+
- name: Commit updated CHANGELOG
24+
uses: stefanzweifel/git-auto-commit-action@v4
25+
with:
26+
branch: master
27+
commit_message: Update CHANGELOG
28+
file_pattern: CHANGELOG.md

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"php-cs-fixer": "./vendor/bin/php-cs-fixer fix --allow-risky=yes",
3939
"phpstan": "./vendor/bin/phpstan analyse --memory-limit=2G",
4040
"phpunit": "./vendor/bin/phpunit --colors=always",
41-
"phpunit-coverage": "./vendor/bin/phpunit --coverage-html coverage",
41+
"phpunit-coverage": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-html coverage",
4242
"phpinsights": "./vendor/bin/phpinsights",
4343
"phpinsights-fix": "./vendor/bin/phpinsights fix"
4444
},

phpinsights.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
'exclude' => [
118118
'src/Factory.php',
119119
'src/Objects/GeometryCollection.php',
120+
'src/GeometryCast.php',
120121
],
121122
],
122123
],

src/GeometryCast.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
88
use Illuminate\Database\Eloquent\Model;
99
use Illuminate\Database\Query\Expression;
10+
use Illuminate\Support\Facades\DB;
1011
use InvalidArgumentException;
1112
use MatanYadaev\EloquentSpatial\Objects\Geometry;
1213

@@ -26,29 +27,35 @@ public function __construct(string $className)
2627
/**
2728
* @param Model $model
2829
* @param string $key
29-
* @param string|null $wkb
30+
* @param string|Expression|null $wkbOrWKt
3031
* @param array<string, mixed> $attributes
3132
* @return Geometry|null
3233
*/
33-
public function get($model, string $key, $wkb, array $attributes): ?Geometry
34+
public function get($model, string $key, $wkbOrWKt, array $attributes): ?Geometry
3435
{
35-
if (! $wkb) {
36+
if (! $wkbOrWKt) {
3637
return null;
3738
}
3839

39-
return $this->className::fromWkb($wkb);
40+
if ($wkbOrWKt instanceof Expression) {
41+
$wkt = $this->extractWktFromExpression($wkbOrWKt);
42+
43+
return $this->className::fromWkt($wkt);
44+
}
45+
46+
return $this->className::fromWkb($wkbOrWKt);
4047
}
4148

4249
/**
4350
* @param Model $model
4451
* @param string $key
4552
* @param Geometry|mixed|null $geometry
4653
* @param array<string, mixed> $attributes
47-
* @return Expression|string|null
54+
* @return Expression|null
4855
*
4956
* @throws InvalidArgumentException
5057
*/
51-
public function set($model, string $key, $geometry, array $attributes): Expression|string|null
58+
public function set($model, string $key, $geometry, array $attributes): Expression|null
5259
{
5360
if (! $geometry) {
5461
return null;
@@ -61,6 +68,15 @@ public function set($model, string $key, $geometry, array $attributes): Expressi
6168
);
6269
}
6370

64-
return $geometry->toWkt();
71+
$wkt = $geometry->toWkt(withFunction: true);
72+
73+
return DB::raw("ST_GeomFromText('{$wkt}')");
74+
}
75+
76+
private function extractWktFromExpression(Expression $expression): string
77+
{
78+
preg_match('/ST_GeomFromText\(\'(.+)\'\)/', (string) $expression, $match);
79+
80+
return $match[1];
6581
}
6682
}

src/Objects/Geometry.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
99
use Illuminate\Contracts\Support\Arrayable;
1010
use Illuminate\Contracts\Support\Jsonable;
11-
use Illuminate\Database\Query\Expression;
1211
use InvalidArgumentException;
1312
use JsonException;
1413
use JsonSerializable;
@@ -17,7 +16,7 @@
1716

1817
abstract class Geometry implements Castable, Arrayable, Jsonable, JsonSerializable
1918
{
20-
abstract public function toWkt(): Expression;
19+
abstract public function toWkt(bool $withFunction): string;
2120

2221
/**
2322
* @param int $options
@@ -49,6 +48,25 @@ public static function fromWkb(string $wkb): static
4948
return $geometry;
5049
}
5150

51+
/**
52+
* @param string $wkt
53+
* @return static
54+
*
55+
* @throws InvalidArgumentException
56+
*/
57+
public static function fromWkt(string $wkt): static
58+
{
59+
$geometry = Factory::parse($wkt, false);
60+
61+
if (! ($geometry instanceof static)) {
62+
throw new InvalidArgumentException(
63+
sprintf('Expected %s, %s given.', static::class, $geometry::class)
64+
);
65+
}
66+
67+
return $geometry;
68+
}
69+
5270
/**
5371
* @param string $geoJson
5472
* @return static

src/Objects/GeometryCollection.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
namespace MatanYadaev\EloquentSpatial\Objects;
66

77
use ArrayAccess;
8-
use Illuminate\Database\Query\Expression;
98
use Illuminate\Support\Collection;
10-
use Illuminate\Support\Facades\DB;
119
use Illuminate\Support\Str;
1210
use InvalidArgumentException;
1311

1412
/**
1513
* @template TGeometry of Geometry
14+
*
1615
* @implements ArrayAccess<int, TGeometry>
1716
*/
1817
class GeometryCollection extends Geometry implements ArrayAccess
@@ -42,9 +41,17 @@ public function __construct(Collection|array $geometries)
4241
$this->validateGeometriesCount();
4342
}
4443

45-
public function toWkt(): Expression
44+
/**
45+
* @param bool $withFunction
46+
* @return string
47+
*
48+
* @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
49+
*/
50+
public function toWkt(bool $withFunction): string
4651
{
47-
return new Expression("GEOMETRYCOLLECTION({$this->toCollectionWkt()})");
52+
$wkt = $this->toCollectionWkt(withFunction: true);
53+
54+
return "GEOMETRYCOLLECTION({$wkt})";
4855
}
4956

5057
/**
@@ -145,7 +152,7 @@ protected function validateGeometriesCount(): void
145152
*/
146153
protected function validateGeometriesType(): void
147154
{
148-
$this->geometries->each(function (mixed $geometry, $a): void {
155+
$this->geometries->each(function (mixed $geometry): void {
149156
/** @var mixed $geometry */
150157
if (! is_object($geometry) || ! ($geometry instanceof $this->collectionOf)) {
151158
throw new InvalidArgumentException(
@@ -155,14 +162,12 @@ protected function validateGeometriesType(): void
155162
});
156163
}
157164

158-
protected function toCollectionWkt(): Expression
165+
protected function toCollectionWkt(bool $withFunction): string
159166
{
160-
$wkt = $this->geometries
161-
->map(static function (Geometry $geometry): string {
162-
return (string) $geometry->toWkt();
167+
return $this->geometries
168+
->map(static function (Geometry $geometry) use ($withFunction): string {
169+
return (string) $geometry->toWkt($withFunction);
163170
})
164171
->join(',');
165-
166-
return DB::raw($wkt);
167172
}
168173
}

src/Objects/LineString.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44

55
namespace MatanYadaev\EloquentSpatial\Objects;
66

7-
use Illuminate\Database\Query\Expression;
8-
use Illuminate\Support\Facades\DB;
9-
107
class LineString extends PointCollection
118
{
129
protected int $minimumGeometries = 2;
1310

14-
public function toWkt(): Expression
11+
public function toWkt(bool $withFunction): string
1512
{
16-
return DB::raw("LINESTRING({$this->toCollectionWkt()})");
13+
$wkt = $this->toCollectionWkt(withFunction: false);
14+
15+
if ($withFunction) {
16+
return "LINESTRING(${wkt})";
17+
}
18+
19+
return "(${wkt})";
1720
}
1821
}

src/Objects/MultiLineString.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44

55
namespace MatanYadaev\EloquentSpatial\Objects;
66

7-
use Illuminate\Database\Query\Expression;
8-
use Illuminate\Support\Facades\DB;
9-
107
/**
118
* @method array<LineString> getGeometries()
129
* @method LineString offsetGet(mixed $offset)
10+
*
1311
* @extends GeometryCollection<LineString>
1412
*/
1513
class MultiLineString extends GeometryCollection
@@ -18,8 +16,16 @@ class MultiLineString extends GeometryCollection
1816

1917
protected int $minimumGeometries = 1;
2018

21-
public function toWkt(): Expression
19+
/**
20+
* @param bool $withFunction
21+
* @return string
22+
*
23+
* @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
24+
*/
25+
public function toWkt(bool $withFunction): string
2226
{
23-
return DB::raw("MULTILINESTRING({$this->toCollectionWkt()})");
27+
$wkt = $this->toCollectionWkt(withFunction: false);
28+
29+
return "MULTILINESTRING({$wkt})";
2430
}
2531
}

src/Objects/MultiPoint.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@
44

55
namespace MatanYadaev\EloquentSpatial\Objects;
66

7-
use Illuminate\Database\Query\Expression;
8-
use Illuminate\Support\Facades\DB;
9-
107
class MultiPoint extends PointCollection
118
{
129
protected int $minimumGeometries = 1;
1310

14-
public function toWkt(): Expression
11+
/**
12+
* @param bool $withFunction
13+
* @return string
14+
*
15+
* @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
16+
*/
17+
public function toWkt(bool $withFunction): string
1518
{
16-
return DB::raw("MULTIPOINT({$this->toCollectionWkt()})");
19+
$wkt = $this->toCollectionWkt(withFunction: false);
20+
21+
return "MULTIPOINT({$wkt})";
1722
}
1823
}

src/Objects/MultiPolygon.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44

55
namespace MatanYadaev\EloquentSpatial\Objects;
66

7-
use Illuminate\Database\Query\Expression;
8-
use Illuminate\Support\Facades\DB;
9-
107
/**
118
* @method array<Polygon> getGeometries()
129
* @method Polygon offsetGet(mixed $offset)
10+
*
1311
* @extends GeometryCollection<Polygon>
1412
*/
1513
class MultiPolygon extends GeometryCollection
@@ -18,8 +16,16 @@ class MultiPolygon extends GeometryCollection
1816

1917
protected int $minimumGeometries = 1;
2018

21-
public function toWkt(): Expression
19+
/**
20+
* @param bool $withFunction
21+
* @return string
22+
*
23+
* @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
24+
*/
25+
public function toWkt(bool $withFunction): string
2226
{
23-
return DB::raw("MULTIPOLYGON({$this->toCollectionWkt()})");
27+
$wkt = $this->toCollectionWkt(withFunction: false);
28+
29+
return "MULTIPOLYGON({$wkt})";
2430
}
2531
}

src/Objects/Point.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44

55
namespace MatanYadaev\EloquentSpatial\Objects;
66

7-
use Illuminate\Database\Query\Expression;
8-
use Illuminate\Support\Facades\DB;
9-
107
class Point extends Geometry
118
{
129
public float $latitude;
@@ -19,9 +16,15 @@ public function __construct(float $latitude, float $longitude)
1916
$this->longitude = $longitude;
2017
}
2118

22-
public function toWkt(): Expression
19+
public function toWkt(bool $withFunction): string
2320
{
24-
return DB::raw("POINT({$this->longitude}, {$this->latitude})");
21+
$wkt = "{$this->longitude} {$this->latitude}";
22+
23+
if ($withFunction) {
24+
return "POINT({$wkt})";
25+
}
26+
27+
return $wkt;
2528
}
2629

2730
/**

src/Objects/PointCollection.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
/**
88
* @method array<Point> getGeometries()
99
* @method Point offsetGet(mixed $offset)
10+
*
1011
* @extends GeometryCollection<Point>
1112
*/
1213
abstract class PointCollection extends GeometryCollection

0 commit comments

Comments
 (0)