Files
TijdVoorDeTest/src/Service/QuizSpreadsheetService.php
Marijn Doeve bcd6a157a8
Some checks failed
CI / Tests (push) Failing after 1m8s
CI / Build and deploy to ${{ startsWith(github.ref, 'refs/tags/') && 'production' || (github.ref == 'refs/heads/main' && 'acceptance' || '') }} (push) Has been skipped
Create Testcoverage and upgrade Symfomy and PHP
* Some tests

* More tests!

* Tests 3

* Move getScores from Candidate to Quiz

* Add some suggestions for future refactoring

* - **Add Gedmo doctrine-extensions and Stof bundle integration**
  - Added `stof/doctrine-extensions-bundle` and `gedmo/doctrine-extensions` dependencies.
  - Integrated `Timestampable` behavior for `Created` fields in entities.
  - Updated `bundles.php` to register StofDoctrineExtensionsBundle.
  - Added configuration for the Stof bundle.
  - Simplified `SeasonVoter` with `match` expression and added new tests.
  - Minor fixes and adjustments across various files.

* WIP

* All the tests

* Base64 tests

* Symfomny 7.4.0

* Update

* Update recipe

* PHP 8.5

* Rector changes

* More 8.5

* Things
2025-11-28 22:56:09 +01:00

136 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Tvdt\Service;
use PhpOffice\PhpSpreadsheet\Reader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer;
use Symfony\Component\HttpFoundation\File\File;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Exception\SpreadsheetDataException;
class QuizSpreadsheetService
{
public function generateTemplate(bool $fillExample = true): \Closure
{
$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);
}
if ($fillExample) {
$sheet->setCellValue('B2', 'Man');
$sheet->setCellValue('C2', true);
$sheet->setCellValue('D2', 'Vrouw');
$sheet->setCellValue('E2', false);
$sheet->setCellValue('A2', 'Is de mol een man of een vrouw?');
}
return $this->toXlsx($spreadsheet);
}
/** @throws SpreadsheetDataException */
public function xlsxToQuiz(Quiz $quiz, File $file): void
{
if (!$this->isSpreadsheetFile($file)) {
throw new \InvalidArgumentException('File must be a valid XLSX spreadsheet');
}
$spreadsheet = $this->readSheet($file);
$sheet = $spreadsheet->getSheet($spreadsheet->getFirstSheetIndex());
$answerLines = \array_slice($sheet->toArray(formatData: false), 1);
$this->fillQuizFromArray($quiz, $answerLines);
}
private function readSheet(File $file): Spreadsheet
{
return new Reader\Xlsx()->setReadDataOnly(true)->load($file->getRealPath());
}
/**
* @param array<int, array<int, string|bool|null>> $sheet
*
* @throws SpreadsheetDataException
*/
private function fillQuizFromArray(Quiz $quiz, array $sheet): void
{
$errors = [];
$questionCounter = 1;
foreach ($sheet as $questionArr) {
if (null === $questionArr[0]) {
break;
}
$question = new Question();
$question->question = (string) $questionArr[0];
$question->ordering = $questionCounter++;
$answerCounter = 1;
$arrCounter = 1;
while (true) {
if (null === $questionArr[$arrCounter]) {
if (1 === $answerCounter) {
$errors[] = \sprintf('Question %d has no answers', $answerCounter);
}
break;
}
$answer = new Answer((string) $questionArr[$arrCounter++], (bool) $questionArr[$arrCounter++]);
$answer->ordering = $answerCounter++;
$question->addAnswer($answer);
}
$quiz->addQuestion($question);
}
if ([] !== $errors) {
throw new SpreadsheetDataException($errors);
}
}
public function quizToXlsx(Quiz $quiz): void
{
throw new \Exception('Not implemented');
}
private function toXlsx(Spreadsheet $spreadsheet): \Closure
{
$writer = new Writer\Xlsx($spreadsheet);
return static fn () => $writer->save('php://output');
}
private function isSpreadsheetFile(File $file): bool
{
return 'xlsx' === $file->getExtension();
}
}