Completed
Push — master ( 0b4911...4851fa )
by Valentyn
04:19 queued 11s
created

MovieController::getAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

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