VSVverkeerskunde/gvq-api

View on GitHub
src/Question/Controllers/QuestionViewController.php

Summary

Maintainability
C
1 day
Test Coverage
<?php declare(strict_types=1);

namespace VSV\GVQ_API\Question\Controllers;

use Ramsey\Uuid\UuidFactoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Translation\TranslatorInterface;
use VSV\GVQ_API\Common\ValueObjects\Language;
use VSV\GVQ_API\Common\ValueObjects\Languages;
use VSV\GVQ_API\Common\ValueObjects\NotEmptyString;
use VSV\GVQ_API\Image\Controllers\ImageController;
use VSV\GVQ_API\Question\Forms\ImageFormType;
use VSV\GVQ_API\Question\Forms\QuestionFormType;
use VSV\GVQ_API\Question\Models\Question;
use VSV\GVQ_API\Question\Models\Questions;
use VSV\GVQ_API\Question\Repositories\CategoryRepository;
use VSV\GVQ_API\Question\Repositories\QuestionRepository;

class QuestionViewController extends AbstractController
{
    /**
     * @var UuidFactoryInterface
     */
    private $uuidFactory;

    /**
     * @var QuestionRepository
     */
    private $questionRepository;

    /**
     * @var CategoryRepository
     */
    private $categoryRepository;

    /**
     * @var ImageController
     */
    private $imageController;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var QuestionFormType
     */
    private $questionFormType;

    /**
     * @var ImageFormType
     */
    private $imageFormType;

    /**
     * @param UuidFactoryInterface $uuidFactory
     * @param QuestionRepository $questionRepository
     * @param CategoryRepository $categoryRepository
     * @param ImageController $imageController
     * @param TranslatorInterface $translator
     */
    public function __construct(
        UuidFactoryInterface $uuidFactory,
        QuestionRepository $questionRepository,
        CategoryRepository $categoryRepository,
        ImageController $imageController,
        TranslatorInterface $translator
    ) {
        $this->uuidFactory = $uuidFactory;
        $this->questionRepository = $questionRepository;
        $this->categoryRepository = $categoryRepository;
        $this->imageController = $imageController;
        $this->translator = $translator;

        $this->questionFormType = new QuestionFormType();
        $this->imageFormType = new ImageFormType();
    }

    /**
     * @return Response
     */
    public function index(): Response
    {
        $questions = $this->questionRepository->getAll();

        return $this->render(
            'questions/index.html.twig',
            [
                'questions' => $questions ? $questions->sortByNewest()->toArray() : [],
                'uploadPath' => getenv('UPLOAD_PATH'),
            ]
        );
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function print(Request $request): Response
    {
        $questions = $this->questionRepository->getAll();

        if ($questions) {
            $questions = $questions->sortByNewest();

            $languageFilter = $this->getLanguageFilter($request);

            if ($languageFilter) {
                $questionsArray = $this->filterQuestions($questions, $languageFilter);
            } else {
                $questionsArray = $questions->toArray();
            }

            return $this->render(
                'questions/print.html.twig',
                [
                    'questions' => $questionsArray,
                    'uploadPath' => getenv('UPLOAD_PATH'),
                ]
            );
        }

        $this->addFlash('warning', $this->translator->trans('Questions.print.none'));

        return $this->redirectToRoute('questions_view_index');
    }

    /**
     * @param Request $request
     * @return Response
     * @throws \League\Flysystem\FileExistsException
     * @throws \Exception
     */
    public function add(Request $request): Response
    {
        $form = $this->createQuestionForm(null);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();

            try {
                $fileName = $this->imageController->handleImage($data['image']);
            } catch (\InvalidArgumentException $e) {
                $form->get('image')->addError(new FormError($e->getMessage()));

                return $this->render(
                  'questions/add.html.twig',
                  [
                    'form' => $form->createView(),
                  ]
                );
            }

            $question = $this->questionFormType->newQuestionFromData(
                $this->uuidFactory,
                $fileName,
                $data
            );
            $this->questionRepository->save($question);

            $this->addFlash(
                'success',
                $this->translator->trans(
                    'Question.add.success',
                    [
                        '%id%' => $question->getId()->toString(),
                    ]
                )
            );

            return $this->redirectToRoute('questions_view_index');
        }

        return $this->render(
            'questions/add.html.twig',
            [
                'form' => $form->createView(),
            ]
        );
    }

    /**
     * @param Request $request
     * @param string $id
     * @return Response
     * @throws \Exception
     */
    public function edit(Request $request, string $id): Response
    {
        $question = $this->questionRepository->getById(
            $this->uuidFactory->fromString($id)
        );

        if (!$question) {
            $this->addFlash(
                'warning',
                $this->translator->trans(
                    'Question.edit.not.found',
                    [
                        '%id%' => $id,
                    ]
                )
            );

            return $this->redirectToRoute('questions_view_index');
        }

        $form = $this->createQuestionForm($question);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $question = $this->questionFormType->updateQuestionFromData(
                $this->uuidFactory,
                $question,
                $form->getData()
            );
            $this->questionRepository->update($question);

            $this->addFlash(
                'success',
                $this->translator->trans(
                    'Question.edit.success',
                    [
                        '%id%' => $id,
                    ]
                )
            );

            return $this->redirectToRoute('questions_view_index');
        }

        return $this->render(
            'questions/add.html.twig',
            [
                'form' => $form->createView(),
            ]
        );
    }

    /**
     * @param Request $request
     * @param string $id
     * @return Response
     * @throws \League\Flysystem\FileExistsException
     * @throws \League\Flysystem\FileNotFoundException
     */
    public function editImage(Request $request, string $id): Response
    {
        $question = $this->questionRepository->getById(
            $this->uuidFactory->fromString($id)
        );

        if (!$question) {
            $this->addFlash(
                'warning',
                $this->translator->trans(
                    'Question.edit.not.found',
                    [
                        '%id%' => $id,
                    ]
                )
            );

            return $this->redirectToRoute('questions_view_index');
        }

        $form = $this->createEditImageForm();
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();

            try {
                $fileName = $this->imageController->handleImage($data['image']);
            } catch (\InvalidArgumentException $e) {
                $form->get('image')->addError(new FormError($e->getMessage()));

                return $this->render(
                  'questions/edit_image.html.twig',
                  [
                    'form' => $form->createView(),
                  ]
                );
            }

            $this->imageController->delete($question->getImageFileName());

            $question = $this->updateQuestionImage(
                $question,
                $fileName
            );
            $this->questionRepository->update($question);

            $this->addFlash(
                'success',
                $this->translator->trans(
                    'Question.edit.image.success',
                    [
                        '%id%' => $id,
                    ]
                )
            );

            return $this->redirectToRoute('questions_view_index');
        }

        return $this->render(
            'questions/edit_image.html.twig',
            [
                'form' => $form->createView(),
            ]
        );
    }

    /**
     * @param Request $request
     * @param string $id
     * @return Response
     * @throws \League\Flysystem\FileNotFoundException
     */
    public function delete(Request $request, string $id): Response
    {
        if ($request->getMethod() === 'POST') {
            $question = $this->questionRepository->getById($this->uuidFactory->fromString($id));

            if ($question) {
                $this->questionRepository->delete(
                    $this->uuidFactory->fromString($id)
                );

                $this->imageController->delete($question->getImageFileName());

                $this->addFlash(
                    'success',
                    $this->translator->trans(
                        'Question.delete.success',
                        [
                            '%id%' => $id,
                        ]
                    )
                );
            }

            return $this->redirectToRoute('questions_view_index');
        }

        return $this->render(
            'questions/delete.html.twig',
            [
                'id' => $id,
            ]
        );
    }

    /**
     * @param Request $request
     * @param string $id
     * @return Response
     * @throws \Exception
     */
    public function archive(Request $request, string $id): Response
    {
        if ($request->getMethod() === 'POST') {
            $question = $this->questionRepository->getById(
                $this->uuidFactory->fromString($id)
            );

            if ($question) {
                $question->archiveOn(new \DateTimeImmutable('now'));
                $this->questionRepository->update($question);

                $this->addFlash(
                    'success',
                    $this->translator->trans(
                        'Question.archive.success',
                        [
                            '%id%' => $id,
                        ]
                    )
                );
            }

            return $this->redirectToRoute('questions_view_index');
        }

        return $this->render(
            'questions/archive.html.twig',
            [
                'id' => $id,
            ]
        );
    }

    /**
     * @param null|Question $question
     * @return FormInterface
     */
    private function createQuestionForm(?Question $question): FormInterface
    {
        $formBuilder = $this->createFormBuilder();

        $this->questionFormType->buildForm(
            $formBuilder,
            [
                'languages' => new Languages(),
                'categories' => $this->categoryRepository->getAll(),
                'question' => $question,
                'translator' => $this->translator,
            ]
        );

        return $formBuilder->getForm();
    }

    /**
     * @return FormInterface
     */
    private function createEditImageForm(): FormInterface
    {
        $formBuilder = $this->createFormBuilder();

        $this->imageFormType->buildForm(
            $formBuilder,
            [
                'translator' => $this->translator,
            ]
        );

        return $formBuilder->getForm();
    }

    /**
     * @param Request $request
     * @return null|Language
     */
    private function getLanguageFilter(Request $request): ?Language
    {
        $printNL = $request->query->get('print_nl') === 'on';
        $printFR = $request->query->get('print_fr') === 'on';

        if ($printNL && !$printFR) {
            return new Language(Language::NL);
        }

        if (!$printNL && $printFR) {
            return new Language(Language::FR);
        }

        return null;
    }

    /**
     * @param Questions $questions
     * @param Language $language
     * @return Question[]
     */
    private function filterQuestions(
        Questions $questions,
        Language $language
    ): array {
        $filteredQuestions = [];

        foreach ($questions as $question) {
            if ($question->getLanguage()->equals($language)) {
                $filteredQuestions[] = $question;
            }
        }

        return $filteredQuestions;
    }

    /**
     * @param Question $question
     * @param NotEmptyString $imageFileName
     * @return Question
     */
    public function updateQuestionImage(
        Question $question,
        NotEmptyString $imageFileName
    ): Question {
        return new Question(
            $question->getId(),
            $question->getLanguage(),
            $question->getYear(),
            $question->getCategory(),
            $question->getText(),
            $imageFileName,
            $question->getAnswers(),
            $question->getFeedback(),
            $question->getCreatedOn()
        );
    }
}