diff --git a/public/site/plugins/map-editor/api/routes.php b/public/site/plugins/map-editor/api/routes.php deleted file mode 100644 index e534822..0000000 --- a/public/site/plugins/map-editor/api/routes.php +++ /dev/null @@ -1,655 +0,0 @@ - 'map-editor/pages/(:all)/markers', - 'method' => 'GET', - 'auth' => false, // Allow Panel session auth - 'action' => function (string $pageId) { - try { - // Get user from session (Panel context) - $user = kirby()->user(); - - // For Panel requests, we trust the session is valid - // The Panel itself already requires authentication - if (!$user && !kirby()->option('debug', false)) { - return [ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 401 - ]; - } - - // Get the map page - $mapPage = kirby()->page($pageId); - if (!$mapPage) { - return [ - 'status' => 'error', - 'message' => 'Map page not found', - 'code' => 404 - ]; - } - - // Check if user can read the page - if (!$mapPage->isReadable()) { - return [ - 'status' => 'error', - 'message' => 'Forbidden', - 'code' => 403 - ]; - } - - // Get all marker subpages, listed only, sorted by num - $markerPages = $mapPage - ->children() - ->listed() - ->filterBy('intendedTemplate', 'marker') - ->sortBy('num', 'asc'); - - // Format markers for response - $markers = []; - foreach ($markerPages as $marker) { - // Get custom icon if available - $iconFile = $marker->markerIcon()->toFile(); - $iconUrl = $iconFile ? $iconFile->url() : null; - - // Get icon size if set - $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 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/markers', - 'method' => 'POST', - 'auth' => false, // Allow Panel session auth - 'action' => function (string $pageId) { - try { - // Get user from session (Panel context) - $user = kirby()->user(); - - // For Panel requests, we trust the session is valid - if (!$user && !kirby()->option('debug', false)) { - return [ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 401 - ]; - } - - // Note: CSRF verification skipped for Panel session requests - // The Panel session itself is already authenticated and secure - - // Get the map page - $mapPage = kirby()->page($pageId); - if (!$mapPage) { - return [ - 'status' => 'error', - 'message' => 'Map page not found', - 'code' => 404 - ]; - } - - // Check if user can create children - if (!$mapPage->permissions()->can('create')) { - return [ - 'status' => 'error', - 'message' => 'Forbidden', - 'code' => 403 - ]; - } - - // Get position from request body - // Use data() instead of body() - Kirby automatically parses JSON - $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']; - - // Validate coordinates - if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { - return [ - 'status' => 'error', - 'message' => 'Invalid coordinates', - 'code' => 400 - ]; - } - - // Get existing markers to determine next num - $existingMarkers = $mapPage - ->children() - ->filterBy('intendedTemplate', 'marker'); - $nextNum = $existingMarkers->count() + 1; - - // Generate title and slug based on title - $title = 'Marqueur ' . $nextNum; - $slug = Str::slug($title); - - // Create the new marker page - $newMarker = $mapPage->createChild([ - 'slug' => $slug, - 'template' => 'marker', - 'content' => [ - 'title' => $title, - 'latitude' => $lat, - 'longitude' => $lon - ] - ]); - - // Publish the page as listed with the correct num - $newMarker->changeStatus('listed', $nextNum); - - // Get custom icon if available (new markers won't have one initially) - $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 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/markers/(:all)', - 'method' => 'PATCH', - 'auth' => false, // Allow Panel session auth - 'action' => function (string $pageId, string $markerId) { - try { - // Get user from session (Panel context) - $user = kirby()->user(); - - if (!$user && !kirby()->option('debug', false)) { - return [ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 401 - ]; - } - - // Note: CSRF verification skipped for Panel session requests - // The Panel session itself is already authenticated and secure - - // Get the marker page - $marker = kirby()->page($markerId); - if (!$marker) { - return [ - 'status' => 'error', - 'message' => 'Marker not found', - 'code' => 404 - ]; - } - - // Check if user can update the page - if (!$marker->permissions()->can('update')) { - return [ - 'status' => 'error', - 'message' => 'Forbidden', - 'code' => 403 - ]; - } - - // Get position from request body - $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']; - - // Validate coordinates - if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { - return [ - 'status' => 'error', - 'message' => 'Invalid coordinates', - 'code' => 400 - ]; - } - - // Update the marker position - $marker->update([ - 'latitude' => $lat, - 'longitude' => $lon - ]); - - // Get custom icon if available - $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 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/markers/(:all)', - 'method' => 'DELETE', - 'auth' => false, // Allow Panel session auth - 'action' => function (string $pageId, string $markerId) { - try { - // Get user from session (Panel context) - $user = kirby()->user(); - - if (!$user && !kirby()->option('debug', false)) { - return [ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 401 - ]; - } - - // Note: CSRF verification skipped for Panel session requests - // The Panel session itself is already authenticated and secure - - // Get the marker page - $marker = kirby()->page($markerId); - if (!$marker) { - return [ - 'status' => 'error', - 'message' => 'Marker not found', - 'code' => 404 - ]; - } - - // Check if user can delete the page - if (!$marker->permissions()->can('delete')) { - return [ - 'status' => 'error', - 'message' => 'Forbidden', - 'code' => 403 - ]; - } - - // Delete the marker page - $marker->delete(true); // true = force delete - - return [ - 'status' => 'success', - 'data' => [ - 'message' => 'Marker deleted successfully' - ] - ]; - - } catch (Exception $e) { - return [ - 'status' => 'error', - 'message' => $e->getMessage(), - 'code' => 500 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/position', - 'method' => 'PATCH', - 'auth' => false, // Allow Panel session auth - 'action' => function (string $pageId) { - try { - // Get user from session (Panel context) - $user = kirby()->user(); - - if (!$user && !kirby()->option('debug', false)) { - return [ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 401 - ]; - } - - // Note: CSRF verification skipped for Panel session requests - // The Panel session itself is already authenticated and secure - - // Get the page (marker page in single mode) - $page = kirby()->page($pageId); - if (!$page) { - return [ - 'status' => 'error', - 'message' => 'Page not found', - 'code' => 404 - ]; - } - - // Check if user can update the page - if (!$page->permissions()->can('update')) { - return [ - 'status' => 'error', - 'message' => 'Forbidden', - 'code' => 403 - ]; - } - - // Get coordinates from request body - $data = kirby()->request()->data(); - - if (!isset($data['latitude']) || !isset($data['longitude'])) { - return [ - 'status' => 'error', - 'message' => 'Latitude and longitude are required', - 'code' => 400 - ]; - } - - $lat = (float) $data['latitude']; - $lon = (float) $data['longitude']; - - // Validate coordinates - if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { - return [ - 'status' => 'error', - 'message' => 'Invalid coordinates', - 'code' => 400 - ]; - } - - // Update the page position - $page->update([ - 'latitude' => $lat, - 'longitude' => $lon - ]); - - return [ - 'status' => 'success', - 'data' => [ - 'latitude' => $lat, - 'longitude' => $lon - ] - ]; - - } catch (Exception $e) { - return [ - 'status' => 'error', - 'message' => $e->getMessage(), - 'code' => 500 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/capture-image', - 'method' => 'POST', - 'auth' => false, // Allow Panel session auth - 'action' => function (string $pageId) { - try { - // Get user from session (Panel context) - $user = kirby()->user(); - - if (!$user && !kirby()->option('debug', false)) { - return [ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 401 - ]; - } - - // Get the map page - $mapPage = kirby()->page($pageId); - if (!$mapPage) { - return [ - 'status' => 'error', - 'message' => 'Map page not found', - 'code' => 404 - ]; - } - - // Check if user can update the page - if (!$mapPage->permissions()->can('update')) { - return [ - 'status' => 'error', - 'message' => 'Forbidden', - 'code' => 403 - ]; - } - - // Get image data from request - $data = kirby()->request()->data(); - - if (!isset($data['image'])) { - return [ - 'status' => 'error', - 'message' => 'Image data is required', - 'code' => 400 - ]; - } - - // Extract base64 data (remove data:image/png;base64, prefix) - $imageData = $data['image']; - if (preg_match('/^data:image\/(png|jpeg|jpg);base64,(.+)$/', $imageData, $matches)) { - $imageData = $matches[2]; - $extension = $matches[1] === 'jpeg' ? 'jpg' : $matches[1]; - } else { - return [ - 'status' => 'error', - 'message' => 'Invalid image format', - 'code' => 400 - ]; - } - - // Decode base64 - $decodedImage = base64_decode($imageData); - if ($decodedImage === false) { - return [ - 'status' => 'error', - 'message' => 'Failed to decode image', - 'code' => 400 - ]; - } - - // Create temporary file - $filename = 'map-static.' . $extension; - $tempPath = sys_get_temp_dir() . '/' . uniqid() . '.' . $extension; - file_put_contents($tempPath, $decodedImage); - - // Delete existing map-static file if it exists - $existingFile = $mapPage->files()->filterBy('name', 'map-static')->first(); - if ($existingFile) { - $existingFile->delete(); - } - - // Create file using Kirby API (so it's properly indexed) - try { - $file = $mapPage->createFile([ - 'source' => $tempPath, - 'filename' => $filename - ]); - - // Clean up temp file - @unlink($tempPath); - } catch (Exception $e) { - @unlink($tempPath); - throw $e; - } - - return [ - 'status' => 'success', - 'data' => [ - 'message' => 'Image saved successfully', - 'filename' => $filename, - 'path' => $filepath - ] - ]; - - } catch (Exception $e) { - return [ - 'status' => 'error', - 'message' => $e->getMessage(), - 'code' => 500 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/check-regenerate-flag', - 'method' => 'GET', - 'auth' => false, - 'action' => function (string $pageId) { - try { - $page = kirby()->page($pageId); - if (!$page) { - return [ - 'status' => 'error', - 'message' => 'Page not found', - 'code' => 404 - ]; - } - - $markerFile = $page->root() . '/.regenerate-map-image'; - $needsRegeneration = file_exists($markerFile); - - return [ - 'status' => 'success', - 'data' => [ - 'needsRegeneration' => $needsRegeneration - ] - ]; - } catch (Exception $e) { - return [ - 'status' => 'error', - 'message' => $e->getMessage(), - 'code' => 500 - ]; - } - } - ], - - [ - 'pattern' => 'map-editor/pages/(:all)/clear-regenerate-flag', - 'method' => 'DELETE', - 'auth' => false, - 'action' => function (string $pageId) { - try { - $page = kirby()->page($pageId); - if (!$page) { - return [ - 'status' => 'error', - 'message' => 'Page not found', - 'code' => 404 - ]; - } - - $markerFile = $page->root() . '/.regenerate-map-image'; - if (file_exists($markerFile)) { - unlink($markerFile); - } - - return [ - 'status' => 'success', - 'data' => [ - 'message' => 'Flag cleared' - ] - ]; - } catch (Exception $e) { - return [ - 'status' => 'error', - 'message' => $e->getMessage(), - 'code' => 500 - ]; - } - } - ] -]; diff --git a/public/site/plugins/map-editor/index.php b/public/site/plugins/map-editor/index.php index 9bfc81b..e9c4643 100644 --- a/public/site/plugins/map-editor/index.php +++ b/public/site/plugins/map-editor/index.php @@ -50,7 +50,11 @@ Kirby::plugin('geoproject/map-editor', [ ] ], 'api' => [ - 'routes' => require __DIR__ . '/api/routes.php' + 'routes' => [ + require __DIR__ . '/routes/markers.php', + require __DIR__ . '/routes/position.php', + require __DIR__ . '/routes/image.php', + ] ], 'hooks' => [ 'page.update:after' => function ($newPage, $oldPage) { diff --git a/public/site/plugins/map-editor/routes/image.php b/public/site/plugins/map-editor/routes/image.php new file mode 100644 index 0000000..73aa889 --- /dev/null +++ b/public/site/plugins/map-editor/routes/image.php @@ -0,0 +1,185 @@ + 'map-editor/pages/(:all)/capture-image', + '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('update')) { + return [ + 'status' => 'error', + 'message' => 'Forbidden', + 'code' => 403 + ]; + } + + $data = kirby()->request()->data(); + + if (!isset($data['image'])) { + return [ + 'status' => 'error', + 'message' => 'Image data is required', + 'code' => 400 + ]; + } + + $imageData = $data['image']; + if (preg_match('/^data:image\/(png|jpeg|jpg);base64,(.+)$/', $imageData, $matches)) { + $imageData = $matches[2]; + $extension = $matches[1] === 'jpeg' ? 'jpg' : $matches[1]; + } else { + return [ + 'status' => 'error', + 'message' => 'Invalid image format', + 'code' => 400 + ]; + } + + $decodedImage = base64_decode($imageData); + if ($decodedImage === false) { + return [ + 'status' => 'error', + 'message' => 'Failed to decode image', + 'code' => 400 + ]; + } + + $filename = 'map-static.' . $extension; + $tempPath = sys_get_temp_dir() . '/' . uniqid() . '.' . $extension; + file_put_contents($tempPath, $decodedImage); + + $existingFile = $mapPage->files()->filterBy('name', 'map-static')->first(); + if ($existingFile) { + $existingFile->delete(); + } + + try { + $file = $mapPage->createFile([ + 'source' => $tempPath, + 'filename' => $filename + ]); + + @unlink($tempPath); + } catch (Exception $e) { + @unlink($tempPath); + throw $e; + } + + return [ + 'status' => 'success', + 'data' => [ + 'message' => 'Image saved successfully', + 'filename' => $filename, + 'path' => $file->root() + ] + ]; + + } catch (Exception $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => 500 + ]; + } + } + ], + + // GET check if regeneration flag exists + [ + 'pattern' => 'map-editor/pages/(:all)/check-regenerate-flag', + 'method' => 'GET', + 'auth' => false, + 'action' => function (string $pageId) { + try { + $page = kirby()->page($pageId); + if (!$page) { + return [ + 'status' => 'error', + 'message' => 'Page not found', + 'code' => 404 + ]; + } + + $markerFile = $page->root() . '/.regenerate-map-image'; + $needsRegeneration = file_exists($markerFile); + + return [ + 'status' => 'success', + 'data' => [ + 'needsRegeneration' => $needsRegeneration + ] + ]; + } catch (Exception $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => 500 + ]; + } + } + ], + + // DELETE clear regeneration flag + [ + 'pattern' => 'map-editor/pages/(:all)/clear-regenerate-flag', + 'method' => 'DELETE', + 'auth' => false, + 'action' => function (string $pageId) { + try { + $page = kirby()->page($pageId); + if (!$page) { + return [ + 'status' => 'error', + 'message' => 'Page not found', + 'code' => 404 + ]; + } + + $markerFile = $page->root() . '/.regenerate-map-image'; + if (file_exists($markerFile)) { + unlink($markerFile); + } + + return [ + 'status' => 'success', + 'data' => [ + 'message' => 'Flag cleared' + ] + ]; + } catch (Exception $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => 500 + ]; + } + } + ] +]; diff --git a/public/site/plugins/map-editor/routes/markers.php b/public/site/plugins/map-editor/routes/markers.php new file mode 100644 index 0000000..c6c94d6 --- /dev/null +++ b/public/site/plugins/map-editor/routes/markers.php @@ -0,0 +1,346 @@ + '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 + ]; + } + } + ] +]; diff --git a/public/site/plugins/map-editor/routes/position.php b/public/site/plugins/map-editor/routes/position.php new file mode 100644 index 0000000..6ab5e36 --- /dev/null +++ b/public/site/plugins/map-editor/routes/position.php @@ -0,0 +1,83 @@ + 'map-editor/pages/(:all)/position', + 'method' => 'PATCH', + 'auth' => false, + 'action' => function (string $pageId) { + try { + $user = kirby()->user(); + + if (!$user && !kirby()->option('debug', false)) { + return [ + 'status' => 'error', + 'message' => 'Unauthorized', + 'code' => 401 + ]; + } + + $page = kirby()->page($pageId); + if (!$page) { + return [ + 'status' => 'error', + 'message' => 'Page not found', + 'code' => 404 + ]; + } + + if (!$page->permissions()->can('update')) { + return [ + 'status' => 'error', + 'message' => 'Forbidden', + 'code' => 403 + ]; + } + + $data = kirby()->request()->data(); + + if (!isset($data['latitude']) || !isset($data['longitude'])) { + return [ + 'status' => 'error', + 'message' => 'Latitude and longitude are required', + 'code' => 400 + ]; + } + + $lat = (float) $data['latitude']; + $lon = (float) $data['longitude']; + + if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { + return [ + 'status' => 'error', + 'message' => 'Invalid coordinates', + 'code' => 400 + ]; + } + + $page->update([ + 'latitude' => $lat, + 'longitude' => $lon + ]); + + return [ + 'status' => 'success', + 'data' => [ + 'latitude' => $lat, + 'longitude' => $lon + ] + ]; + + } catch (Exception $e) { + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => 500 + ]; + } + } +];