128 lines
3.8 KiB
PHP
128 lines
3.8 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');
|
|
|
|
for ($i = 0; $i < $zip->numFiles; $i++) {
|
|
$filename = $zip->getNameIndex($i);
|
|
$fileinfo = $zip->statIndex($i);
|
|
|
|
if ($fileinfo['crc'] == 0) {
|
|
continue;
|
|
}
|
|
|
|
$targetPath = $storagePublic.DIRECTORY_SEPARATOR.$filename;
|
|
$targetDir = dirname($targetPath);
|
|
|
|
if (!is_dir($targetDir)) {
|
|
mkdir($targetDir, 0775, true);
|
|
}
|
|
|
|
copy('zip://'.$zipPath.'#'.$filename, $targetPath);
|
|
}
|
|
|
|
$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);
|
|
}
|
|
}
|
|
}
|
|
}
|