Skip to content

Commit

Permalink
feat: added meta tags support for GPX imported files
Browse files Browse the repository at this point in the history
  • Loading branch information
mwargan committed Feb 27, 2024
1 parent e84c48e commit a53ed79
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 11 deletions.
34 changes: 25 additions & 9 deletions app/Http/Controllers/MarkerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ public function storeInBulk(Request $request, Map $map)
'markers.*.description' => ['nullable', 'string', 'max:191'],
'markers.*.category_name' => ['required_without:markers.*.category', 'min:3', 'max:32', new \App\Rules\NotContainsString()],
'user_id' => 'exists:users,id',
'markers.*.created_at' => 'nullable',
'markers.*.updated_at' => 'nullable',
'markers.*.expires_at' => 'nullable',
'markers.*.created_at' => 'nullable|date',
'markers.*.updated_at' => 'nullable|date',
'markers.*.expires_at' => 'nullable|date',
'markers.*.link' => [Rule::requiredIf(optional($map->options)['links'] === "required")],
'markers.*.meta' => 'nullable|array|max:10',
'markers.*.meta.*' => ['nullable', 'max:255'],
Expand All @@ -168,8 +168,8 @@ public function storeInBulk(Request $request, Map $map)
'markers.*.locations.*.speed' => 'nullable|numeric|between:0,100000',
'markers.*.locations.*.zoom' => 'nullable|numeric|between:0,20',
'markers.*.locations.*.elevation' => 'nullable|numeric|between:-100000,100000',
'markers.*.locations.*.created_at' => 'nullable',
'markers.*.locations.*.updated_at' => 'nullable',
'markers.*.locations.*.created_at' => 'nullable|date',
'markers.*.locations.*.updated_at' => 'nullable|date',
]);

$now = Carbon::now();
Expand All @@ -179,8 +179,13 @@ public function storeInBulk(Request $request, Map $map)
foreach ($validated_data['markers'] as $index => $marker) {
$marker['bulk_insert_id'] = $bulkInsertId;

$marker['created_at'] = $marker['created_at'] ?? $now;
$marker['updated_at'] = $marker['updated_at'] ?? $now;


// The dates need to be converted to Carbon instances and then to string for insertion
$marker['created_at'] = isset($marker['created_at']) ? Carbon::parse($marker['created_at'])->toDateTimeString() : $now;
$marker['updated_at'] = isset($marker['updated_at']) ? Carbon::parse($marker['updated_at'])->toDateTimeString() : $now;
$marker['expires_at'] = isset($marker['expires_at']) ? Carbon::parse($marker['expires_at'])->toDateTimeString() : null;

$marker['token'] = Str::random(32);
$marker['user_id'] = $validated_data['user_id'];
$marker['map_id'] = $map->id;
Expand Down Expand Up @@ -216,6 +221,17 @@ public function storeInBulk(Request $request, Map $map)

$insertableMarker = $marker;

// If there is meta, we need to json_encode it
if (isset($insertableMarker['meta'])) {
$insertableMarker['meta'] = json_encode($insertableMarker['meta']);
} else {
$insertableMarker['meta'] = null;
}

if (!isset($insertableMarker['link'])) {
$insertableMarker['link'] = null;
}

unset($insertableMarker['elevation']);
unset($insertableMarker['current_location']);
unset($insertableMarker['zoom']);
Expand Down Expand Up @@ -268,8 +284,8 @@ public function storeInBulk(Request $request, Map $map)
'roll' => $location['roll'] ?? null,
'speed' => $location['speed'] ?? null,
'user_id' => $marker->user_id,
'created_at' => $location['created_at'] ?? $marker->created_at ?? $now,
'updated_at' => $location['updated_at'] ?? $marker->updated_at ?? $now,
'created_at' => isset($location['created_at']) ? Carbon::parse($location['created_at'])->toDateTimeString() : $marker->created_at ?? $now,
'updated_at' => isset($location['updated_at']) ? Carbon::parse($location['updated_at'])->toDateTimeString() : $marker->updated_at ?? $now,
];
}

Expand Down
36 changes: 34 additions & 2 deletions app/Parsers/Files/GPXParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function parseFile(string $filepath): array
!is_string($marker['name']) ||
empty($marker['name'])
) {
$marker['name'] = 'Waypoint';
$marker['name'] = $marker['sym'] ?? 'Waypoint';
}

if (
Expand All @@ -37,11 +37,27 @@ public function parseFile(string $filepath): array
$marker['desc'] = null;
}

$markerMeta = [];

// Add all direct children of the wpt element as metadata, except for the name and desc
foreach ($marker as $key => $value) {
if ($key === 'name' || $key === 'desc' || $key === 'ele' || $key === 'sym' || $key === 'link' || $key === '@attributes') {
continue;
}

$markerMeta[$key] = $value;
}

$markers[] = [
'lat' => $marker['@attributes']['lat'],
'lng' => $marker['@attributes']['lon'],
'category_name' => $marker['name'] ?? 'Waypoint',
'category_name' => $marker['name'],
'description' => $marker['desc'] ?? null,
'link' => $marker['link'] ?? null,
'elevation' => $marker['ele'] ?? null,
'created_at' => $marker['time'] ?? null,
'updated_at' => $marker['time'] ?? null,
'meta' => $markerMeta,
];
}
}
Expand All @@ -60,6 +76,9 @@ public function parseFile(string $filepath): array
$markerlocations[] = [
'lat' => $trkpt['@attributes']['lat'],
'lng' => $trkpt['@attributes']['lon'],
'elevation' => $trkpt['ele'] ?? null,
'created_at' => $trkpt['time'] ?? null,
'updated_at' => $trkpt['time'] ?? null,
];
}
}
Expand All @@ -83,11 +102,24 @@ public function parseFile(string $filepath): array
$track['desc'] = null;
}

$markerMeta = [];

// Add all direct children of the trk element as metadata, except for the name and desc
foreach ($track as $key => $value) {
if ($key === 'name' || $key === 'desc' || $key === 'ele' || $key === 'trkseg' || $key === 'trkpt' || $key === '@attributes') {
continue;
}

$markerMeta[$key] = $value;
}

$markers[] = [
'description' => $track['desc'],
'locations' => $markerlocations,
// The category_name is the name of the track - parsed CDATA
'category_name' => $track['name'],
// Meta needs to be encoded as JSON
'meta' => $markerMeta,
];
}
}
Expand Down
40 changes: 40 additions & 0 deletions tests/Unit/MarkerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Tests\Unit;

use App\Jobs\FillMissingLocationGeocodes;
use App\Jobs\FillMissingMarkerElevation;
use App\Models\Category;
use App\Models\Marker;
use App\Models\User;
Expand Down Expand Up @@ -214,6 +216,12 @@ public function testFailCreateMarkerInBulkUnauthorised()
*/
public function testCreateMarkerInBulk()
{
// Skip any dispatched jobs
$this->expectsJobs([
FillMissingMarkerElevation::class,
FillMissingLocationGeocodes::class,
]);

// Get raw factory data
$marker = Marker::factory()->make();

Expand Down Expand Up @@ -258,6 +266,12 @@ public function testCreateMarkerInBulk()
*/
public function testCreateMarkerInBulkWithAllMapOptions()
{
// Skip any dispatched jobs
$this->expectsJobs([
FillMissingMarkerElevation::class,
FillMissingLocationGeocodes::class,
]);

$map = new \App\Models\Map();
$map->users_can_create_markers = 'yes';
$map->options = ['links' => 'optional'];
Expand Down Expand Up @@ -306,6 +320,12 @@ public function testCreateMarkerInBulkWithAllMapOptions()
*/
public function testCreateMarkerInBulkWithMultipleLocations()
{
// Skip any dispatched jobs
$this->expectsJobs([
FillMissingMarkerElevation::class,
FillMissingLocationGeocodes::class,
]);

$map = new \App\Models\Map();
$map->users_can_create_markers = 'yes';
$map->options = ['links' => 'optional'];
Expand Down Expand Up @@ -382,6 +402,14 @@ public function testCreateMarkerInBulkWithMultipleLocations()
*/
public function testCreateMarkerInBulkWithGpxFile()
{
$this->withoutExceptionHandling();

// Skip any dispatched jobs
$this->expectsJobs([
FillMissingMarkerElevation::class,
FillMissingLocationGeocodes::class,
]);

// We need to clean up the database before we start
DB::table('markers')->delete();
DB::table('marker_locations')->delete();
Expand Down Expand Up @@ -412,6 +440,18 @@ public function testCreateMarkerInBulkWithGpxFile()

// The DB file adds 348 trkpt, so we should have 348 locations + 25 wpt
$this->assertEquals(373, $map->markerLocations()->count());

// 271 of the locations should have an elevation
$this->assertEquals(271, $map->markerLocations()->whereNotNull('elevation')->count());

// 267 should have created_at and updated_at on 2002-04-21 (any time)
$this->assertEquals(267, $map->markerLocations()->whereDate('marker_locations.created_at', '2002-04-21')->whereDate('marker_locations.updated_at', '2002-04-21')->count());

// The others should have todays date
$this->assertEquals(106, $map->markerLocations()->whereDate('marker_locations.created_at', now()->toDateString())->whereDate('marker_locations.updated_at', now()->toDateString())->count());

// There should be 11 markers with the field "number". It doesn't matter what the value is, just that it exists. This field will be a key in the JSON column called "meta"
$this->assertEquals(11, $map->markers()->whereNotNull('meta->number')->count());
}

/**
Expand Down

0 comments on commit a53ed79

Please sign in to comment.