feat: implement automatic static map image generation
- Add html-to-image for capturing map container with markers - Auto-generate map image on page/marker save via hooks - Use flag system (.regenerate-map-image) to trigger generation on Panel reload - Create file using Kirby API for proper indexing - Add mapStaticImage field in blueprint to display generated image - Wait for map to be fully loaded before capture - Capture entire container (map + custom markers) - Filter MapLibre controls from capture Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1d74105910
commit
9193ac8900
8 changed files with 474 additions and 92 deletions
|
|
@ -467,5 +467,189 @@ return [
|
|||
];
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
[
|
||||
'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
|
||||
];
|
||||
}
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue