Files
tracer e0f3bbe52f
CI/CD Pipeline / deploy (push) Successful in 29s
CI/CD Pipeline / promote_stable (push) Successful in 2s
Improve asset import using ZipArchive::extractTo()
2026-05-17 18:27:48 +02:00

119 lines
3.6 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use ZipArchive;
class AssetController extends Controller
{
public function export()
{
$user = auth()->user();
if (!$user || !$user->roles()->where('name', 'ROLE_ADMIN')->exists()) {
abort(403, 'Forbidden');
}
try {
$storagePublic = storage_path('app/public');
if (!is_dir($storagePublic)) {
mkdir($storagePublic, 0775, true);
}
// Create ZIP in memory
$zip = new ZipArchive();
$tempFile = tempnam(sys_get_temp_dir(), 'speedbb_');
if ($zip->open($tempFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return response()->json(['message' => 'Failed to create ZIP'], 500);
}
// Add a manifest file to ensure ZIP is created even if empty
$zip->addFromString('MANIFEST.txt', "SpeedBB Assets Export\nExported: " . date('Y-m-d H:i:s') . "\n");
$this->addDirectoryToZip($zip, $storagePublic, '');
$zip->close();
if (!file_exists($tempFile)) {
return response()->json(['message' => 'ZIP file was not created'], 500);
}
$filename = 'assets-'.date('YmdHis').'.zip';
return response()->file($tempFile, [
'Content-Type' => 'application/zip',
'Content-Disposition' => 'attachment; filename="'.$filename.'"',
])->deleteFileAfterSend(true);
} catch (\Exception $e) {
return response()->json(['message' => 'Export error: '.$e->getMessage()], 500);
}
}
public function import(Request $request): JsonResponse
{
$user = $request->user();
if (!$user || !$user->roles()->where('name', 'ROLE_ADMIN')->exists()) {
return response()->json(['message' => 'Forbidden'], 403);
}
$data = $request->validate([
'file' => ['required', 'file', 'mimes:zip', 'max:104857600'],
]);
$file = $data['file'];
$zip = new ZipArchive();
$zipPath = $file->getPathname();
if ($zip->open($zipPath) !== true) {
return response()->json(['message' => 'Invalid zip file'], 400);
}
$storagePublic = storage_path('app/public');
if (!is_dir($storagePublic)) {
mkdir($storagePublic, 0777, true);
}
if ($zip->extractTo($storagePublic) !== true) {
$zip->close();
return response()->json(['message' => 'Failed to extract assets from ZIP'], 500);
}
$zip->close();
return response()->json([
'message' => 'Assets imported successfully',
]);
}
private function addDirectoryToZip(ZipArchive $zip, string $dir, string $zipPath): void
{
if (!is_dir($dir)) {
return;
}
$files = @scandir($dir);
if ($files === false) {
return;
}
foreach ($files as $file) {
if ($file === '.' || $file === '..') {
continue;
}
$path = $dir.DIRECTORY_SEPARATOR.$file;
$newZipPath = $zipPath === '' ? $file : $zipPath.'/'.$file;
if (is_dir($path)) {
$zip->addEmptyDir($newZipPath);
$this->addDirectoryToZip($zip, $path, $newZipPath);
} elseif (is_file($path)) {
$zip->addFile($path, $newZipPath);
}
}
}
}