Completed
Push — master ( 4851fa...058e40 )
by Valentyn
04:07
created

MovieController   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 209
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 28

Test Coverage

Coverage 75%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 28
dl 0
loc 209
ccs 54
cts 72
cp 0.75
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getAll() 0 25 1
A getMovies() 0 14 3
A getMovieReleaseDate() 0 10 2
A postMoviesUpdatePoster() 0 13 2
A getSearch() 0 12 1
A postMovies() 0 19 2
A putMovies() 0 33 1
1
<?php
2
3
namespace App\Movies\Controller;
4
5
use App\Controller\BaseController;
6
use App\Countries\Entity\Country;
7
use App\Filters\FilterBuilder;
8
use App\Filters\Movie as Filter;
9
use App\Movies\DTO\MovieTranslationDTO;
10
use App\Movies\Entity\Movie;
11
use App\Movies\Entity\MovieTranslations;
12
use App\Movies\EventListener\SimilarMoviesProcessor;
13
use App\Movies\Repository\MovieReleaseDateRepository;
14
use App\Movies\Repository\MovieRepository;
15
use App\Movies\Request\CreateMovieRequest;
16
use App\Movies\Request\SearchRequest;
17
use App\Movies\Request\UpdateMovieRequest;
18
use App\Movies\Request\UpdatePosterRequest;
19
use App\Movies\Service\MovieManageService;
20
use App\Movies\Service\SearchService;
21
use App\Movies\Transformer\MovieTransformer;
22
use App\Movies\Utils\Poster;
23
use App\Pagination\CustomPaginatedCollection;
24
use App\Users\Entity\UserRoles;
25
use Enqueue\Client\ProducerInterface;
26
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
27
use Symfony\Component\HttpFoundation\JsonResponse;
28
use Symfony\Component\HttpFoundation\Request;
29
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
30
use Symfony\Component\Routing\Annotation\Route;
31
use Symfony\Component\Validator\Validator\ValidatorInterface;
32
33
/**
34
 * Class MovieController.
35
 */
36
class MovieController extends BaseController
37
{
38
    /**
39
     * Get all movies.
40
     *
41
     * @Route("/api/movies", methods={"GET"})
42
     *
43
     * @param Request         $request
44
     * @param MovieRepository $movieRepository
45
     *
46
     * @return \Symfony\Component\HttpFoundation\JsonResponse
47
     * @throws
48
     */
49 34
    public function getAll(Request $request, MovieRepository $movieRepository)
50
    {
51 34
        [$movies, $ids] = $movieRepository->findAllWithIsWatchedFlag($this->getUser(), $this->getGuest());
0 ignored issues
show
Bug introduced by
The variable $movies does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $ids does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
52
53 34
        $offset = (int) $request->get('offset', 0);
54 34
        $limit = $request->get('limit', null);
55
56
        // Its important to keep order of filters from easiest to heaviest in order to improve performance (in theory)
57 34
        $filter = new FilterBuilder(
58 34
            new Filter\YearRange(),
59 34
            new Filter\Rating(),
60 34
            new Filter\Genre(),
61 34
            new Filter\Actor()
62
        );
63
64 34
        $filter->process($request->query, $ids);
65
66
        // todo move this clone qb to CustomPaginatedCollection
67 34
        $count = clone $ids;
68 34
        $count->select('COUNT(m.id)')->resetDQLPart('orderBy');
69
70 34
        $collection = new CustomPaginatedCollection($movies->getQuery(), $ids->getQuery(), $count->getQuery(), $offset, $limit);
71
72 34
        return $this->items($collection, MovieTransformer::list());
73
    }
74
75
    /**
76
     * Get movie resource.
77
     *
78
     * @Route("/api/movies/{id}", methods={"GET"}, requirements={"id"="\d+"})
79
     *
80
     * @param int               $id
81
     * @param MovieRepository   $repository
82
     * @param ProducerInterface $producer
83
     *
84
     * @throws \Doctrine\ORM\NoResultException
85
     * @throws \Doctrine\ORM\NonUniqueResultException
86
     *
87
     * @return JsonResponse
88
     */
89 2
    public function getMovies(int $id, MovieRepository $repository, ProducerInterface $producer)
90
    {
91 2
        if (null === $movie = $repository->findOneForMoviePage($id, $this->getUser())) {
92
            throw new NotFoundHttpException();
93
        }
94
95 2
        if (\count($movie->getSimilarMovies()) === 0) {
96 2
            $producer->sendEvent(SimilarMoviesProcessor::LOAD_SIMILAR_MOVIES, json_encode($movie->getId()));
97
        }
98
99 2
        return $this->response($movie, 200, [], [
100 2
            'groups' => ['view'],
101
        ]);
102
    }
103
104
    /**
105
     * @Route("/api/movies/{movieId}/releaseDate/{countryCode}", methods={"GET"}, requirements={"movieId"="\d+"})
106
     * @ParamConverter("country", options={"mapping": {"countryCode": "code"}})
107
     */
108
    public function getMovieReleaseDate(int $movieId, Country $country, MovieReleaseDateRepository $repository)
109
    {
110
        if (null === $releaseDate = $repository->findOneByCountry($movieId, $country->getId())) {
111
            throw new NotFoundHttpException();
112
        }
113
114
        return $this->response($releaseDate, 200, [], [
115
            'groups' => ['view'],
116
        ]);
117
    }
118
119
    /**
120
     * @Route("/api/movies/{id}/updatePoster", methods={"POST"}, requirements={"id"="\d+"})
121
     *
122
     * @param Movie               $movie
123
     * @param UpdatePosterRequest $request
124
     *
125
     * @return JsonResponse
126
     */
127 1
    public function postMoviesUpdatePoster(Movie $movie, UpdatePosterRequest $request)
128
    {
129 1
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
130
131 1
        if (null === $posterPath = Poster::savePoster($movie->getId(), $request->get('url'))) {
132
            return $this->json([], 400);
133
        }
134
135 1
        $movie->setOriginalPosterUrl(Poster::getUrl($movie->getId()));
136 1
        $this->getDoctrine()->getManager()->flush();
137
138 1
        return $this->json([]);
139
    }
140
141
    /**
142
     * Get movies by title.
143
     *
144
     * @Route("/api/movies/search", methods={"POST"})
145
     *
146
     * @param SearchRequest $request
147
     * @param SearchService $searchService
148
     * @param Request       $currentRequest
149
     *
150
     * @throws \Exception
151
     *
152
     * @return \Symfony\Component\HttpFoundation\JsonResponse
153
     */
154 2
    public function getSearch(SearchRequest $request, SearchService $searchService, Request $currentRequest)
155
    {
156 2
        $offset = (int) $request->get('offset', 0);
157 2
        $limit = $request->get('limit', null);
158
159 2
        $query = $request->get('query');
160 2
        $movies = $searchService->findByQuery($query, $currentRequest->getLocale(), $offset, $limit);
161
162 2
        return $this->response($movies, 200, [], [
163 2
            'groups' => ['list'],
164
        ]);
165
    }
166
167
    /**
168
     * Create new movie.
169
     *
170
     * @Route("/api/movies", methods={"POST"})
171
     *
172
     * @param CreateMovieRequest $request
173
     * @param MovieManageService $service
174
     * @param ValidatorInterface $validator
175
     *
176
     * @throws \Exception
177
     *
178
     * @return \Symfony\Component\HttpFoundation\JsonResponse
179
     */
180
    public function postMovies(CreateMovieRequest $request, MovieManageService $service, ValidatorInterface $validator)
181
    {
182
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
183
184
        $movie = $service->createMovieByRequest($request);
185
        $errors = $validator->validate($movie);
186
187
        if (\count($errors)) {
188
            return $request->getErrorResponse($errors);
189
        }
190
191
        $entityManager = $this->getDoctrine()->getManager();
192
        $entityManager->persist($movie);
193
        $entityManager->flush();
194
195
        return $this->response($movie, 200, [], [
196
            'groups' => ['view'],
197
        ]);
198
    }
199
200
    /**
201
     * @Route("/api/movies/{id}", methods={"POST", "PUT", "PATCH"}, requirements={"id"="\d+"})
202
     *
203
     * @param Movie              $movie
204
     * @param UpdateMovieRequest $request
205
     *
206
     * @throws \ErrorException
207
     * @throws \Exception
208
     *
209
     * @return JsonResponse
210
     */
211 2
    public function putMovies(Movie $movie, UpdateMovieRequest $request)
212
    {
213 2
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
214
215 1
        $movieData = $request->get('movie');
216 1
        $movieTranslationsData = $movieData['translations'];
217
218 1
        $movie->setOriginalTitle($movieData['originalTitle']);
219 1
        $movie->setImdbId($movieData['imdbId']);
220 1
        $movie->setRuntime($movieData['runtime']);
221 1
        $movie->setBudget($movieData['budget']);
222 1
        $movie->setReleaseDate(new \DateTimeImmutable($movieData['releaseDate']));
223
224
        $addTranslation = function (array $trans) use ($movie) {
225 1
            $transDto = new MovieTranslationDTO($trans['locale'], $trans['title'], $trans['overview'], null);
226 1
            $movie->addTranslation(
227 1
                new MovieTranslations($movie, $transDto)
228
            );
229 1
        };
230
231
        $updateTranslation = function (array $trans, MovieTranslations $oldTranslation) use ($movie) {
232 1
            $oldTranslation->setTitle($trans['title']);
233 1
            $oldTranslation->setOverview($trans['overview']);
234 1
        };
235
236 1
        $movie->updateTranslations($movieTranslationsData, $addTranslation, $updateTranslation);
237
238 1
        $em = $this->getDoctrine()->getManager();
239 1
        $em->persist($movie); // if there 1+ new translations lets persist movie to be sure that they will be saved
240 1
        $em->flush();
241
242 1
        return new JsonResponse(null, 202);
243
    }
244
}
245