Passed
Push — master ( 028b7a...8da5b1 )
by Matt
05:44 queued 55s
created

ImageController::filterQueryByYearAndMonth()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 14
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 25
rs 9.4888
1
<?php
2
3
namespace App\Controller\Image;
4
5
use App\Entity\Image;
6
use App\Form\ImageFilterData;
7
use App\Form\ImageFilterType;
8
use App\Repository\ImageRepository;
9
use Carbon\Carbon;
10
use Carbon\CarbonImmutable;
11
use DateTime;
12
use Doctrine\ORM\QueryBuilder;
13
use Knp\Component\Pager\PaginatorInterface;
14
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
15
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
16
use Symfony\Component\HttpFoundation\InputBag;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\Routing\Annotation\Route;
20
21
/**
22
 * @Route("/image", name="image_")
23
 */
24
class ImageController extends AbstractController
25
{
26
    /**
27
     * @Route("/{id}", name="show", methods={"GET"})
28
     */
29
    public function show(Image $image, ImageRepository $imageRepository): Response
30
    {
31
        $prev = $imageRepository->findPrev($image);
32
        $next = $imageRepository->findNext($image);
33
        return $this->render('image/show.html.twig', [
34
            'image' => $image,
35
            'prev' => $prev,
36
            'next' => $next
37
        ]);
38
    }
39
40
    /**
41
     * @Route(
42
     *  "",
43
     *  name="index",
44
     *  methods={"GET"},
45
     * )
46
     */
47
    public function index(
48
        Request $request,
49
        ImageRepository $imageRepository,
50
        PaginatorInterface $paginator
51
    ): Response {
52
        /** @var ImageFilterData $filterData */
53
54
        // Sensible defaults
55
        $filterData = new ImageFilterData();
56
        $filterData->setStartDate($imageRepository->getEarliestImageCaptureDate());
57
        $filterData->setEndDate($imageRepository->getLatestImageCaptureDate());
58
        $filterData->setRatingComparison('eq');
59
        $locationChoices = $this->getLocationChoices($imageRepository);
60
61
        // These are overrides that can be sent by links set up on our
62
        // charts on the Statistics page. If we get a location, star
63
        // rating or start & end dates via those, we override our defaults.
64
        $filterData->setLocation((string) $request->query->get('location'));
65
        if ($request->query->has('rating')) {
66
            $filterData->setRating($request->query->getInt('rating'));
67
        }
68
        if ($request->query->has('periodStartDate')) {
69
            $filterData->setStartDateFromUrlParam((string) $request->query->get('periodStartDate'));
70
        }
71
        if ($request->query->has('periodEndDate')) {
72
            $filterData->setEndDateFromUrlParam((string) $request->query->get('periodEndDate'));
73
        }
74
75
        // Filtering form for the top of the page
76
        $filterForm = $this->createForm(
77
            ImageFilterType::class,
78
            $filterData,
79
            [
80
                'locations' => array_combine($locationChoices, array_values($locationChoices)),
81
                'csrf_protection' => false // We're just a GET request, and nothing bad happens no matter what you do.
82
            ]
83
        );
84
85
        $filterForm->handleRequest($request);
86
        if ($filterForm->isSubmitted() && $filterForm->isValid()) {
87
            $filterData = $filterForm->getData();
88
        };
89
90
        $qb = $imageRepository->getReversePaginatorQueryBuilder();
91
92
        if ($filterData->hasRating() && $filterData->hasRatingComparison()) {
93
            $this->filterQueryByRating(
94
                $filterData->getRating(),
95
                $filterData->getRatingComparison(),
96
                $qb
97
            );
98
        }
99
100
        if ($filterData->hasStartDate()) {
101
            $qb
102
                ->andWhere('i.capturedAt >= :startDate')
103
                ->setParameter('startDate', $filterData->getStartDate());
104
        }
105
106
        if ($filterData->hasEndDate()) {
107
            $endDate = (new CarbonImmutable($filterData->getEndDate()))->addDays(1);
108
            $qb
109
                ->andWhere('i.capturedAt < :endDate')
110
                ->setParameter('endDate', $endDate);
111
        }
112
113
        if ($filterData->hasLocation()) {
114
            $qb
115
                ->andWhere('i.location = :location')
116
                ->setParameter('location', $filterData->getLocation());
117
        }
118
119
        $query = $qb->getQuery();
120
121
        $page = $request->query->getInt('page', 1);
122
        $pagination = $paginator->paginate(
123
            $query,
124
            $page,
125
            20
126
        );
127
128
        return $this->render('image/index.html.twig', [
129
            'image_pagination' => $pagination,
130
            'filter_form' => $filterForm->createView()
131
        ]);
132
    }
133
134
    /**
135
     * @return array<string>
136
     */
137
    private function getLocationChoices(ImageRepository $imageRepository)
138
    {
139
        return $imageRepository->getAllLocations();
140
    }
141
142
    private function filterQueryByRating(?int $rating, string $ratingComparison, QueryBuilder &$qb): QueryBuilder
143
    {
144
        if ($rating !== null) {
145
            switch ($ratingComparison) {
146
                case 'lte':
147
                    $qb->andWhere($qb->expr()->lte('i.rating', ':rating'));
148
                    break;
149
                case 'gte':
150
                    $qb->andWhere($qb->expr()->gte('i.rating', ':rating'));
151
                    break;
152
                default:
153
                    // 'eq'
154
                    $qb->andWhere($qb->expr()->eq('i.rating', ':rating'));
155
                    break;
156
            }
157
            $qb->setParameter('rating', $rating);
158
        }
159
        return $qb;
160
    }
161
}
162