'map-editor/pages/(:all)/markers', 'method' => 'GET', 'auth' => false, 'action' => function (string $pageId) { try { $user = kirby()->user(); if (!$user && !kirby()->option('debug', false)) { return [ 'status' => 'error', 'message' => 'Unauthorized', 'code' => 401 ]; } $mapPage = kirby()->page($pageId); if (!$mapPage) { return [ 'status' => 'error', 'message' => 'Map page not found', 'code' => 404 ]; } if (!$mapPage->isReadable()) { return [ 'status' => 'error', 'message' => 'Forbidden', 'code' => 403 ]; } $markerPages = $mapPage ->children() ->listed() ->filterBy('intendedTemplate', 'marker') ->sortBy('num', 'asc'); $markers = []; foreach ($markerPages as $marker) { $iconFile = $marker->markerIcon()->toFile(); $iconUrl = $iconFile ? $iconFile->url() : null; $iconSize = $marker->markerIconSize()->isNotEmpty() ? (int) $marker->markerIconSize()->value() : 40; $markers[] = [ 'id' => $marker->id(), 'slug' => $marker->slug(), 'title' => $marker->title()->value(), 'position' => [ 'lat' => (float) $marker->latitude()->value(), 'lon' => (float) $marker->longitude()->value() ], 'num' => $marker->num(), 'panelUrl' => (string) $marker->panel()->url(), 'iconUrl' => $iconUrl, 'iconSize' => $iconSize ]; } return [ 'status' => 'success', 'data' => [ 'markers' => $markers ] ]; } catch (Exception $e) { return [ 'status' => 'error', 'message' => $e->getMessage(), 'code' => 500 ]; } } ], // POST create new marker [ 'pattern' => 'map-editor/pages/(:all)/markers', 'method' => 'POST', 'auth' => false, 'action' => function (string $pageId) { try { $user = kirby()->user(); if (!$user && !kirby()->option('debug', false)) { return [ 'status' => 'error', 'message' => 'Unauthorized', 'code' => 401 ]; } $mapPage = kirby()->page($pageId); if (!$mapPage) { return [ 'status' => 'error', 'message' => 'Map page not found', 'code' => 404 ]; } if (!$mapPage->permissions()->can('create')) { return [ 'status' => 'error', 'message' => 'Forbidden', 'code' => 403 ]; } $data = kirby()->request()->data(); if (!isset($data['position']['lat']) || !isset($data['position']['lon'])) { return [ 'status' => 'error', 'message' => 'Position (lat, lon) is required', 'code' => 400 ]; } $lat = (float) $data['position']['lat']; $lon = (float) $data['position']['lon']; if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { return [ 'status' => 'error', 'message' => 'Invalid coordinates', 'code' => 400 ]; } $existingMarkers = $mapPage ->children() ->filterBy('intendedTemplate', 'marker'); $nextNum = $existingMarkers->count() + 1; $title = 'Marqueur ' . $nextNum; $slug = Str::slug($title); $newMarker = $mapPage->createChild([ 'slug' => $slug, 'template' => 'marker', 'content' => [ 'title' => $title, 'latitude' => $lat, 'longitude' => $lon ] ]); $newMarker->changeStatus('listed', $nextNum); $iconFile = $newMarker->markerIcon()->toFile(); $iconUrl = $iconFile ? $iconFile->url() : null; $iconSize = $newMarker->markerIconSize()->isNotEmpty() ? (int) $newMarker->markerIconSize()->value() : 40; return [ 'status' => 'success', 'data' => [ 'marker' => [ 'id' => $newMarker->id(), 'slug' => $newMarker->slug(), 'title' => $title, 'position' => [ 'lat' => $lat, 'lon' => $lon ], 'num' => $nextNum, 'panelUrl' => (string) $newMarker->panel()->url(), 'iconUrl' => $iconUrl, 'iconSize' => $iconSize ] ] ]; } catch (Exception $e) { return [ 'status' => 'error', 'message' => $e->getMessage(), 'code' => 500 ]; } } ], // PATCH update marker position [ 'pattern' => 'map-editor/pages/(:all)/markers/(:all)', 'method' => 'PATCH', 'auth' => false, 'action' => function (string $pageId, string $markerId) { try { $user = kirby()->user(); if (!$user && !kirby()->option('debug', false)) { return [ 'status' => 'error', 'message' => 'Unauthorized', 'code' => 401 ]; } $marker = kirby()->page($markerId); if (!$marker) { return [ 'status' => 'error', 'message' => 'Marker not found', 'code' => 404 ]; } if (!$marker->permissions()->can('update')) { return [ 'status' => 'error', 'message' => 'Forbidden', 'code' => 403 ]; } $data = kirby()->request()->data(); if (!isset($data['position']['lat']) || !isset($data['position']['lon'])) { return [ 'status' => 'error', 'message' => 'Position (lat, lon) is required', 'code' => 400 ]; } $lat = (float) $data['position']['lat']; $lon = (float) $data['position']['lon']; if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { return [ 'status' => 'error', 'message' => 'Invalid coordinates', 'code' => 400 ]; } $marker->update([ 'latitude' => $lat, 'longitude' => $lon ]); $iconFile = $marker->markerIcon()->toFile(); $iconUrl = $iconFile ? $iconFile->url() : null; $iconSize = $marker->markerIconSize()->isNotEmpty() ? (int) $marker->markerIconSize()->value() : 40; return [ 'status' => 'success', 'data' => [ 'marker' => [ 'id' => $marker->id(), 'slug' => $marker->slug(), 'title' => $marker->title()->value(), 'position' => [ 'lat' => $lat, 'lon' => $lon ], 'num' => $marker->num(), 'panelUrl' => (string) $marker->panel()->url(), 'iconUrl' => $iconUrl, 'iconSize' => $iconSize ] ] ]; } catch (Exception $e) { return [ 'status' => 'error', 'message' => $e->getMessage(), 'code' => 500 ]; } } ], // DELETE marker [ 'pattern' => 'map-editor/pages/(:all)/markers/(:all)', 'method' => 'DELETE', 'auth' => false, 'action' => function (string $pageId, string $markerId) { try { $user = kirby()->user(); if (!$user && !kirby()->option('debug', false)) { return [ 'status' => 'error', 'message' => 'Unauthorized', 'code' => 401 ]; } $marker = kirby()->page($markerId); if (!$marker) { return [ 'status' => 'error', 'message' => 'Marker not found', 'code' => 404 ]; } if (!$marker->permissions()->can('delete')) { return [ 'status' => 'error', 'message' => 'Forbidden', 'code' => 403 ]; } $marker->delete(true); return [ 'status' => 'success', 'data' => [ 'message' => 'Marker deleted successfully' ] ]; } catch (Exception $e) { return [ 'status' => 'error', 'message' => $e->getMessage(), 'code' => 500 ]; } } ] ];