Skip to content

Commit

Permalink
prevent json_encode error 5
Browse files Browse the repository at this point in the history
immediately apply casting to geometry objects to prevent errors while trying to json_encode binary data
  • Loading branch information
d0m4te committed Dec 28, 2023
1 parent 17f3c35 commit 8283e7d
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
25 changes: 25 additions & 0 deletions src/Traits/HasSpatial.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MatanYadaev\EloquentSpatial\Traits;

use MatanYadaev\EloquentSpatial\Objects\Geometry;
use MatanYadaev\EloquentSpatial\SpatialBuilder;

trait HasSpatial
Expand All @@ -10,4 +11,28 @@ public function newEloquentBuilder($query): SpatialBuilder
{
return new SpatialBuilder($query);
}

/**
* @param array<string, mixed> $attributes
*/
public function setRawAttributes(array $attributes, $sync = false)
{
$result = parent::setRawAttributes($attributes, $sync);

foreach ($attributes as $attribute => $value) {
if ($value && is_string($value) && ! preg_match('//u', $value)) { // the string is binary
// access the attribute to force conversion via attribute cast
$spatialAttribute = $this->$attribute;

// override attribute and original attribute to get rid of binary strings
// (Those would lead to errors while JSON encoding a serialized version of the model.)
if ($spatialAttribute instanceof Geometry) {
$this->attributes[$attribute] = $spatialAttribute;
$this->original[$attribute] = $spatialAttribute;
}
}
}

return $result;
}
}
46 changes: 42 additions & 4 deletions tests/GeometryCastTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@
TestPlace::insert(array_merge(TestPlace::factory()->definition(), [
'point_with_line_string_cast' => DB::raw('POINT(0, 180)'),
]));
/** @var TestPlace $testPlace */
$testPlace = TestPlace::firstOrFail();

expect(function () use ($testPlace): void {
$testPlace->getAttribute('point_with_line_string_cast');
expect(function (): void {
// cast deserialization happens in setRawAttributes
// called immediately after retrieving db record
TestPlace::firstOrFail();
})->toThrow(InvalidArgumentException::class);
});

Expand All @@ -126,3 +126,41 @@

expect($testPlace->point)->toEqual($point);
});

it('is serializeable and JSON encodeable by standard serialize / JSON encode functions', function (): void {
$point = new Point(0, 180);

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

$serialized = serialize($testPlace);
$json = json_encode($serialized);

expect($json)->toBeTruthy('JSON encoding failed.');

// @phpstan-ignore-next-line
$recoveredTestPlace = unserialize(json_decode($json));

expect($recoveredTestPlace)->toEqual($testPlace);
});

it('is serializeable and JSON encodeable by standard serialize / JSON encode functions when retrieved from db', function (): void {
$point = new Point(0, 180);

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

$testPlace->save();

$testPlaceFromDb = TestPlace::find($testPlace->id);

$serialized = serialize($testPlaceFromDb);
$json = json_encode($serialized);

expect($json)->toBeTruthy('JSON encoding failed.');

// @phpstan-ignore-next-line
$recoveredTestPlace = unserialize(json_decode($json));

expect($recoveredTestPlace)->toEqual($testPlaceFromDb);
});

0 comments on commit 8283e7d

Please sign in to comment.