feat: Fragen-Export (JSON) und -Import im Admin-Bereich

This commit is contained in:
root
2026-05-05 15:09:14 +00:00
parent bae435eb4a
commit 085ea7c3ca
3 changed files with 93 additions and 2 deletions
@@ -5,6 +5,7 @@ use App\Models\Question;
use App\Models\Subject;
use App\Models\AnswerOption;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class QuestionController extends Controller {
public function index(Request $r) {
$subjects = Subject::all();
@@ -97,4 +98,64 @@ class QuestionController extends Controller {
$question->delete();
return redirect()->route('admin.questions.index')->with('success','Frage gelöscht.');
}
public function export(Request $r) {
$query = Question::with(['subject','answerOptions'])->latest();
if ($r->filled('subject')) $query->where('subject_id', $r->subject);
$data = $query->get()->map(fn($q) => [
'subject' => $q->subject->slug,
'question_text' => $q->question_text,
'type' => $q->type,
'difficulty' => $q->difficulty,
'points_value' => $q->points_value,
'active' => (bool)$q->active,
'options' => $q->answerOptions->map(fn($o) => [
'text' => $o->text,
'is_correct' => (bool)$o->is_correct,
])->values(),
]);
$filename = 'fragen-' . now()->format('Y-m-d') . '.json';
return response()->streamDownload(
fn() => print(json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)),
$filename,
['Content-Type' => 'application/json']
);
}
public function import(Request $r) {
$r->validate(['file' => 'required|file|mimes:json|max:2048']);
$raw = json_decode(file_get_contents($r->file('file')->getRealPath()), true);
if (!is_array($raw)) {
return back()->with('error', 'Ungültiges JSON-Format.');
}
$subjects = Subject::pluck('id','slug');
$imported = 0;
$skipped = 0;
DB::transaction(function() use ($raw, $subjects, &$imported, &$skipped) {
foreach ($raw as $item) {
if (empty($item['subject']) || !isset($subjects[$item['subject']])) { $skipped++; continue; }
if (empty($item['question_text'])) { $skipped++; continue; }
$q = Question::create([
'subject_id' => $subjects[$item['subject']],
'question_text' => $item['question_text'],
'type' => $item['type'] ?? 'multiple_choice',
'difficulty' => $item['difficulty'] ?? 1,
'points_value' => $item['points_value'] ?? 5,
'active' => $item['active'] ?? true,
]);
foreach (($item['options'] ?? []) as $i => $opt) {
AnswerOption::create([
'question_id' => $q->id,
'text' => $opt['text'],
'is_correct' => $opt['is_correct'] ?? false,
'sort_order' => $i,
]);
}
$imported++;
}
});
$msg = "{$imported} Fragen importiert.";
if ($skipped) $msg .= " {$skipped} übersprungen (unbekanntes Fach oder fehlender Text).";
return back()->with('success', $msg);
}
}