mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-07-05 23:20:18 +02:00
Implement quizToXlsx() export and add export button
- QuizSpreadsheetService: implement quizToXlsx() as the inverse of
fillQuizFromArray() — writes quiz questions and answers to XLSX using
the same column layout as the import template
- BackofficeController: add exportQuiz() action at GET /backoffice/quiz/{quiz}/export
- tab_overview.html.twig: add Export to XLSX button in Quick actions
This commit is contained in:
@@ -11,12 +11,15 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Routing\Requirement\Requirement;
|
||||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
use Tvdt\Controller\AbstractController;
|
use Tvdt\Controller\AbstractController;
|
||||||
|
use Tvdt\Entity\Quiz;
|
||||||
use Tvdt\Entity\Season;
|
use Tvdt\Entity\Season;
|
||||||
use Tvdt\Entity\User;
|
use Tvdt\Entity\User;
|
||||||
use Tvdt\Form\CreateSeasonFormType;
|
use Tvdt\Form\CreateSeasonFormType;
|
||||||
use Tvdt\Repository\SeasonRepository;
|
use Tvdt\Repository\SeasonRepository;
|
||||||
|
use Tvdt\Security\Voter\SeasonVoter;
|
||||||
use Tvdt\Service\QuizSpreadsheetService;
|
use Tvdt\Service\QuizSpreadsheetService;
|
||||||
|
|
||||||
#[AsController]
|
#[AsController]
|
||||||
@@ -78,4 +81,20 @@ final class BackofficeController extends AbstractController
|
|||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
|
||||||
|
#[Route(
|
||||||
|
'/backoffice/quiz/{quiz}/export',
|
||||||
|
name: 'tvdt_backoffice_quiz_export',
|
||||||
|
requirements: ['quiz' => Requirement::UUID],
|
||||||
|
methods: ['GET'],
|
||||||
|
)]
|
||||||
|
public function exportQuiz(Quiz $quiz): StreamedResponse
|
||||||
|
{
|
||||||
|
$response = new StreamedResponse($this->excel->quizToXlsx($quiz));
|
||||||
|
$response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
|
$response->headers->set('Content-Disposition', 'attachment; filename="'.$quiz->name.'.xlsx"');
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,9 +120,47 @@ class QuizSpreadsheetService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function quizToXlsx(Quiz $quiz): void
|
public function quizToXlsx(Quiz $quiz): \Closure
|
||||||
{
|
{
|
||||||
throw new \Exception('Not implemented');
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
$sheet->getStyle('1:1')->getFont()->setBold(true);
|
||||||
|
|
||||||
|
$sheet->setCellValue('A1', 'Question');
|
||||||
|
$sheet->getColumnDimension('A')->setWidth(30);
|
||||||
|
$sheet->getStyle('A:A')->getAlignment()->setWrapText(true);
|
||||||
|
|
||||||
|
$counter = 1;
|
||||||
|
foreach (range('B', 'L', 2) as $column) {
|
||||||
|
$sheet->setCellValue($column.'1', 'Answer '.$counter++);
|
||||||
|
$sheet->getColumnDimension($column)->setWidth(30);
|
||||||
|
$sheet->getStyle($column.':'.$column)->getAlignment()->setWrapText(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (range('C', 'M', 2) as $column) {
|
||||||
|
$sheet->setCellValue($column.'1', 'Correct');
|
||||||
|
$sheet->getColumnDimension($column)->setAutoSize(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$answerColumns = range('B', 'L', 2);
|
||||||
|
$correctColumns = range('C', 'M', 2);
|
||||||
|
|
||||||
|
$row = 2;
|
||||||
|
foreach ($quiz->questions as $question) {
|
||||||
|
$sheet->setCellValue('A'.$row, $question->question);
|
||||||
|
|
||||||
|
$col = 0;
|
||||||
|
foreach ($question->answers as $answer) {
|
||||||
|
$sheet->setCellValue($answerColumns[$col].$row, $answer->text);
|
||||||
|
$sheet->setCellValue($correctColumns[$col].$row, $answer->isRightAnswer);
|
||||||
|
++$col;
|
||||||
|
}
|
||||||
|
|
||||||
|
++$row;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->toXlsx($spreadsheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function toXlsx(Spreadsheet $spreadsheet): \Closure
|
private function toXlsx(Spreadsheet $spreadsheet): \Closure
|
||||||
|
|||||||
@@ -49,6 +49,11 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="btn btn-outline-secondary mb-3"
|
||||||
|
href="{{ path('tvdt_backoffice_quiz_export', {quiz: quiz.id}) }}">
|
||||||
|
{{ 'Export to XLSX'|trans }}
|
||||||
|
</a>
|
||||||
|
|
||||||
<h4 class="mb-3">{{ 'Questions'|trans }}</h4>
|
<h4 class="mb-3">{{ 'Questions'|trans }}</h4>
|
||||||
<div class="accordion">
|
<div class="accordion">
|
||||||
{%~ for question in quiz.questions ~%}
|
{%~ for question in quiz.questions ~%}
|
||||||
|
|||||||
Reference in New Issue
Block a user