Lines 100.00% 12 / 12
Functions and Methods 100.00% 2 / 2
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
DoneAt 100.00% 12 / 12 100.00% 2 / 2 8 100.00% 1 / 1
 __invoke 100.00% 8 / 8 100.00% 1 / 1 4
 day 100.00% 4 / 4 100.00% 1 / 1 4
1<?php
2
3declare(strict_types=1);
4
5namespace App\Controller\Banners;
6
7use App\Controller\BaseController;
8use App\Entity\DoneBanner;
9use App\Entity\TimelineEvent;
10use App\Security\Voter\DoneBannerVoter;
11use Doctrine\ORM\EntityManagerInterface;
12use Symfony\Component\HttpFoundation\Request;
13use Symfony\Component\HttpFoundation\Response;
14use Symfony\Component\Routing\Attribute\Route;
15use Symfony\Component\Security\Http\Attribute\IsGranted;
16
17/**
18 * Sets the day one of the user's banners was done (Y-m-d), or removes it (empty): banners with
19 * a day are on the timeline.
20 */
21#[Route('/banners/done/{id}', name: 'app_banners_done_at', requirements: ['id' => '\d+'], methods: ['POST'])]
22#[IsGranted(DoneBannerVoter::EDIT, subject: 'banner')]
23final class DoneAt extends BaseController
24{
25    public const string CSRF_TOKEN = 'done-banner';
26
27    public function __invoke(Request $request, DoneBanner $banner, EntityManagerInterface $entityManager): Response
28    {
29        $value = $request->getPayload()->getString('doneAt');
30        $doneAt = $this->day($value);
31
32        if (!$this->isCsrfTokenValid(self::CSRF_TOKEN, $request->getPayload()->getString('_token')) || false === $doneAt) {
33            $this->addFlash('danger', 'bannergress.date_invalid');
34        } else {
35            $banner->doneAt = $doneAt;
36            $entityManager->flush();
37            $this->addFlash('success', $doneAt instanceof \DateTimeImmutable ? 'bannergress.date_saved' : 'bannergress.date_removed');
38        }
39
40        return $this->redirect($this->generateUrl('app_banners').'#done-banner-'.$banner->id, Response::HTTP_SEE_OTHER);
41    }
42
43    /** The day of a Y-m-d value; null for none (empty), false for no date. */
44    private function day(string $value): \DateTimeImmutable|false|null
45    {
46        if ('' === $value) {
47            return null;
48        }
49
50        $day = \DateTimeImmutable::createFromFormat('!'.TimelineEvent::DATE_FORMAT, $value);
51
52        return $day instanceof \DateTimeImmutable && $day->format(TimelineEvent::DATE_FORMAT) === $value ? $day : false;
53    }
54}