ImageController   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 61
c 2
b 0
f 0
dl 0
loc 162
rs 10
wmc 18

8 Methods

Rating   Name   Duplication   Size   Complexity  
A cluster() 0 3 1
A index() 0 16 1
A setLocation() 0 12 3
A delete() 0 12 2
A show() 0 4 1
A setAutoTags() 0 11 3
A edit() 0 15 3
A upload() 0 44 4
1
<?php
2
3
namespace App\Controller\Admin;
4
5
use App\Entity\Image;
6
use App\Form\ImageType;
7
use App\Message\RecogniseImage;
8
use App\Message\WarmImageCache;
9
use App\Repository\ImageRepository;
10
use App\Service\DiskStatsService;
11
use App\Service\LocationService;
12
use Doctrine\ORM\EntityManagerInterface;
13
use Doctrine\Persistence\ManagerRegistry;
14
use Exception;
15
use Knp\Component\Pager\PaginatorInterface;
16
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
17
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
18
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
19
use Symfony\Component\HttpFoundation\File\UploadedFile;
20
use Symfony\Component\HttpFoundation\JsonResponse;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\Response;
23
use Symfony\Component\HttpKernel\Exception\HttpException;
24
use Symfony\Component\Messenger\MessageBusInterface;
25
use Symfony\Component\Routing\Annotation\Route;
26
use Symfony\Component\Routing\Exception\InvalidParameterException;
27
use Vich\UploaderBundle\Form\Type\VichImageType;
28
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
29
30
/**
31
 * @Route("/admin/image", name="admin_image_")
32
 */
33
class ImageController extends AbstractController
34
{
35
    /**
36
     * @Route("/", name="index", methods={"GET"})
37
     */
38
    public function index(ImageRepository $imageRepository, PaginatorInterface $paginator, Request $request): Response
39
    {
40
        $query = $imageRepository
41
            ->createQueryBuilder('i')
42
            // Nice orphan check: ->where('i.wanders is empty')
43
            ->orderBy('i.capturedAt', 'DESC')
44
            ->addOrderBy('i.id', 'DESC')
45
            ->getQuery();
46
47
        $pagination = $paginator->paginate(
48
            $query,
49
            $request->query->getInt('page', 1),
50
            10);
51
52
        return $this->render('admin/image/index.html.twig', [
53
            'pagination' => $pagination
54
        ]);
55
    }
56
57
    /**
58
     * @Route("/cluster", name="cluster", methods={"GET"})
59
     */
60
    public function cluster(): Response
61
    {
62
        return $this->render('admin/image/cluster.html.twig', [
63
        ]);
64
    }
65
66
    /**
67
     * @Route("/upload", name="upload", methods={"GET", "POST"})
68
     */
69
    public function upload(
70
            Request $request,
71
            string $imagesDirectory,
72
            DiskStatsService $diskStatsService,
73
            ManagerRegistry $managerRegistry
74
    ): Response {
75
        if ($request->isMethod('POST')) {
76
77
            $token = (string) $request->request->get('token');
78
            if (!$this->isCsrfTokenValid('image_upload', $token)) {
79
                return $this->json([ 'error' => 'Invalid CSRF token'], 401);
80
            }
81
82
            $file = $request->files->get('file');
83
            if (!$file instanceof UploadedFile) {
84
                throw new HttpException(500, "No uploaded file found.");
85
            }
86
87
            $image = new Image();
88
            $image->setImageFile($file);
89
            $entityManager = $managerRegistry->getManager();
90
            $entityManager->persist($image);
91
            $entityManager->flush();
92
93
            // It's not exactly an API response, but it'll do until we switch to handling this
94
            // a bit more properly. At least it's a JSON repsonse and *doesn't include the entire
95
            // file we just uploaded*, thanks to the wander:item grouping limiting the returned
96
            // fields. Because we set up the image URIs in a postPersist event listener, this
97
            //  also contains everything you'd need to build an image in HTML.
98
            return $this->json(
99
                $image,
100
                Response::HTTP_OK,
101
                [],
102
                [
103
                    'groups' => 'wander:item',
104
                ]
105
            );
106
        }
107
108
        // Normal GET request.
109
        $disk = $diskStatsService->getDiskStats($imagesDirectory);
110
111
        return $this->render('admin/image/upload.html.twig', [
112
                'disk' => $disk
113
        ]);
114
    }
115
116
    /**
117
     * @Route("/{id}", name="show", methods={"GET"})
118
     */
119
    public function show(Image $image): Response
120
    {
121
        return $this->render('admin/image/show.html.twig', [
122
            'image' => $image,
123
        ]);
124
    }
125
126
    /**
127
     * @Route("/{id}/edit", name="edit", methods={"GET","POST"})
128
     */
129
    public function edit(
130
        Request $request,
131
        Image $image,
132
        ManagerRegistry $managerRegistry
133
    ): Response {
134
        $form = $this->createForm(ImageType::class, $image);
135
        $form->handleRequest($request);
136
        if ($form->isSubmitted() && $form->isValid()) {
137
            $managerRegistry->getManager()->flush();
138
            return $this->redirectToRoute('admin_image_show', ['id' => $image->getId()]);
139
        }
140
141
        return $this->render('admin/image/edit.html.twig', [
142
            'image' => $image,
143
            'form' => $form->createView(),
144
        ]);
145
    }
146
147
    /**
148
     * @Route("/{id}", name="delete", methods={"DELETE"})
149
     */
150
    public function delete(
151
        Request $request,
152
        Image $image,
153
        ManagerRegistry $managerRegistry
154
    ): Response {
155
        if ($this->isCsrfTokenValid('delete'.$image->getId(), (string) $request->request->get('_token'))) {
156
            $entityManager = $managerRegistry->getManager();
157
            $entityManager->remove($image);
158
            $entityManager->flush();
159
        }
160
161
        return $this->redirectToRoute('admin_image_index');
162
    }
163
164
    /**
165
     * @Route("/{id}/set_location", name="set_location", methods={"POST"})
166
     */
167
    public function setLocation(Request $request, Image $image, LocationService $locationService, EntityManagerInterface $entityManager): Response
168
    {
169
        if ($this->isCsrfTokenValid('set_location'.$image->getId(), (string) $request->request->get('_token'))) {
170
            $neighbourhood  = $locationService->getLocationName($image->getLatitude(), $image->getLongitude());
171
            if ($neighbourhood !== null) {
172
                $image->setLocation($neighbourhood);
173
                $entityManager->persist($image);
174
                $entityManager->flush();
175
            }
176
        }
177
178
        return $this->redirectToRoute('admin_image_show', ['id' => $image->getId()]);
179
    }
180
181
    /**
182
     * @Route("/{id}/set_auto_tags", name="set_auto_tags", methods={"POST"})
183
     */
184
    public function setAutoTags(Request $request, Image $image, MessageBusInterface $messageBus): Response
185
    {
186
        if ($this->isCsrfTokenValid('set_auto_tags'.$image->getId(), (string) $request->request->get('_token'))) {
187
            $imageId = $image->getId();
188
            if ($imageId === null) {
189
                throw new InvalidParameterException('No image id in setAutoTags');
190
            }
191
            $messageBus->dispatch(new RecogniseImage($imageId, true));
192
            $this->addFlash('success', 'Image re-queued for recognition.');
193
        }
194
        return $this->redirectToRoute('admin_image_show', ['id' => $image->getId()]);
195
    }
196
}
197