Completed
Push — master ( f446cd...59ed7d )
by Valentyn
13:46 queued 11:33
created

MovieController::getSearch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 9.8666
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
namespace App\Movies\Controller;
4
5
use App\Controller\BaseController;
6
use App\Movies\DTO\MovieTranslationDTO;
7
use App\Movies\Entity\Movie;
8
use App\Movies\Entity\MovieTranslations;
9
use App\Movies\EventListener\AddRecommendationProcessor;
10
use App\Movies\EventListener\SimilarMoviesProcessor;
11
use App\Movies\Repository\MovieRecommendationRepository;
12
use App\Movies\Repository\MovieRepository;
13
use App\Movies\Request\CreateMovieRequest;
14
use App\Movies\Request\NewMovieRecommendationRequest;
15
use App\Movies\Request\SearchRequest;
16
use App\Movies\Request\UpdateMovieRequest;
17
use App\Movies\Service\MovieManageService;
18
use App\Movies\Service\SearchService;
19
use App\Pagination\PaginatedCollection;
20
use App\Users\Entity\User;
21
use App\Users\Entity\UserRoles;
22
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
23
use Doctrine\ORM\EntityManagerInterface;
24
use Enqueue\Client\ProducerInterface;
25
use Symfony\Component\HttpFoundation\JsonResponse;
26
use Symfony\Component\HttpFoundation\Request;
27
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
28
use Symfony\Component\Routing\Annotation\Route;
29
use Symfony\Component\Validator\Validator\ValidatorInterface;
30
31
/**
32
 * Class MovieController.
33
 */
34
class MovieController extends BaseController
35
{
36
    /**
37
     * Get all movies.
38
     *
39
     * @Route("/api/movies", methods={"GET"})
40
     *
41
     * @param Request         $request
42
     * @param MovieRepository $movieRepository
43
     *
44
     * @return \Symfony\Component\HttpFoundation\JsonResponse
45
     */
46 6
    public function getAll(Request $request, MovieRepository $movieRepository)
47
    {
48 6
        $user = $this->getUser();
49
50 6
        if ($user instanceof User) {
51
            $movies = $movieRepository->findAllWithIsUserWatchedFlag($user);
52
        } else {
53 6
            $movies = $movieRepository->findAllWithIsGuestWatchedFlag($this->getGuest());
54
        }
55
56 6
        $offset = (int) $request->get('offset', 0);
57 6
        $limit = $request->get('limit', null);
58
59 6
        $movies = new PaginatedCollection($movies, $offset, $limit);
60
61 6
        return $this->response($movies, 200, [], [
62 6
            'groups' => ['list'],
63
        ]);
64
    }
65
66
    /**
67
     * Get movie resource.
68
     *
69
     * @Route("/api/movies/{id}", methods={"GET"})
70
     *
71
     * @param Movie             $movie
72
     * @param ProducerInterface $producer
73
     *
74
     * @return \Symfony\Component\HttpFoundation\JsonResponse
75
     */
76 1
    public function getMovies(Movie $movie, ProducerInterface $producer)
77
    {
78 1
        if (count($movie->getSimilarMovies()) === 0) {
79 1
            $producer->sendEvent(SimilarMoviesProcessor::LOAD_SIMILAR_MOVIES, json_encode($movie->getId()));
80
        }
81
82 1
        return $this->response($movie, 200, [], [
83 1
            'groups' => ['view'],
84
        ]);
85
    }
86
87
    /**
88
     * Get movies by title.
89
     *
90
     * @Route("/api/movies/search", methods={"POST"})
91
     *
92
     * @param SearchRequest $request
93
     * @param SearchService $searchService
94
     * @param Request       $currentRequest
95
     *
96
     * @throws \Exception
97
     *
98
     * @return \Symfony\Component\HttpFoundation\JsonResponse
99
     */
100 2
    public function getSearch(SearchRequest $request, SearchService $searchService, Request $currentRequest)
101
    {
102 2
        $offset = (int) $request->get('offset', 0);
103 2
        $limit = $request->get('limit', null);
104
105 2
        $query = $request->get('query');
106 2
        $movies = $searchService->findByQuery($query, $currentRequest->getLocale(), $offset, $limit);
107
108 2
        return $this->response($movies, 200, [], [
109 2
            'groups' => ['list'],
110
        ]);
111
    }
112
113
    /**
114
     * Create new movie.
115
     *
116
     * @Route("/api/movies", methods={"POST"})
117
     *
118
     * @param CreateMovieRequest $request
119
     * @param MovieManageService $service
120
     * @param ValidatorInterface $validator
121
     *
122
     * @throws \Exception
123
     *
124
     * @return \Symfony\Component\HttpFoundation\JsonResponse
125
     */
126 2
    public function postMovies(CreateMovieRequest $request, MovieManageService $service, ValidatorInterface $validator)
127
    {
128 2
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
129
130 1
        $movie = $service->createMovieByRequest($request);
131 1
        $errors = $validator->validate($movie);
132
133 1
        if (count($errors)) {
134
            return $request->getErrorResponse($errors);
135
        }
136
137 1
        $entityManager = $this->getDoctrine()->getManager();
138 1
        $entityManager->persist($movie);
139 1
        $entityManager->flush();
140
141 1
        return $this->response($movie, 200, [], [
142 1
            'groups' => ['view'],
143
        ]);
144
    }
145
146
    /**
147
     * @Route("/api/movies/{id}", methods={"POST", "PUT", "PATCH"}, requirements={"id"="\d+"})
148
     *
149
     * @param Movie              $movie
150
     * @param UpdateMovieRequest $request
151
     *
152
     * @throws \ErrorException
153
     * @throws \Exception
154
     *
155
     * @return JsonResponse
156
     */
157 2
    public function putMovies(Movie $movie, UpdateMovieRequest $request)
158
    {
159 2
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
160
161 1
        $movieData = $request->get('movie');
162 1
        $movieTranslationsData = $movieData['translations'];
163
164 1
        $movie->setOriginalTitle($movieData['originalTitle']);
165 1
        $movie->setImdbId($movieData['imdbId']);
166 1
        $movie->setRuntime($movieData['runtime']);
167 1
        $movie->setBudget($movieData['budget']);
168 1
        $movie->setReleaseDate(new \DateTimeImmutable($movieData['releaseDate']));
169
170
        $addTranslation = function (array $trans) use ($movie) {
171 1
            $transDto = new MovieTranslationDTO($trans['locale'], $trans['title'], $trans['overview'], null);
172 1
            $movie->addTranslation(
173 1
                new MovieTranslations($movie, $transDto)
174
            );
175 1
        };
176
177
        $updateTranslation = function (array $trans, MovieTranslations $oldTranslation) use ($movie) {
178 1
            $oldTranslation->setTitle($trans['title']);
179 1
            $oldTranslation->setOverview($trans['overview']);
180 1
        };
181
182 1
        $movie->updateTranslations($movieTranslationsData, $addTranslation, $updateTranslation);
183
184 1
        $em = $this->getDoctrine()->getManager();
185 1
        $em->persist($movie); // if there 1+ new translations lets persist movie to be sure that they will be saved
186 1
        $em->flush();
187
188 1
        return new JsonResponse(null, 202);
189
    }
190
191
    /**
192
     * Add new recommendation.
193
     *
194
     * @Route("/api/movies/{id}/recommendations", methods={"POST"})
195
196
     *
197
     * @param NewMovieRecommendationRequest $request
198
     * @param Movie                         $originalMovie
199
     * @param EntityManagerInterface        $em
200
     * @param ProducerInterface             $producer
201
     *
202
     * @throws \Doctrine\ORM\ORMException
203
     *
204
     * @return JsonResponse
205
     */
206 1
    public function postMoviesRecommendations(NewMovieRecommendationRequest $request, Movie $originalMovie, EntityManagerInterface $em, ProducerInterface $producer)
207
    {
208 1
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
209
210 1
        $recommendation = $request->get('recommendation');
211 1
        $user = $this->getUser();
212
213 1
        if (!empty($recommendation['movie_id'])) {
214 1
            $recommendedMovie = $em->getReference(Movie::class, $recommendation['movie_id']);
215
216 1
            if ($recommendedMovie === null) {
217
                throw new NotFoundHttpException();
218
            }
219
220 1
            $originalMovie->addRecommendation($user, $recommendedMovie);
0 ignored issues
show
Documentation introduced by
$user is of type null|object, but the function expects a object<App\Users\Entity\User>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
221 1
            $em->persist($originalMovie);
222
            try {
223 1
                $em->flush();
224
            } catch (UniqueConstraintViolationException $exception) {
225
                // It's ok..
226
            }
227
228 1
            return new JsonResponse();
229
        }
230
231
        $producer->sendEvent(AddRecommendationProcessor::ADD_RECOMMENDATION, json_encode([
232
            'tmdb_id' => $recommendation['tmdb_id'],
233
            'movie_id' => $originalMovie->getId(),
234
            'user_id' => $user->getId(),
235
        ]));
236
237
        return new JsonResponse();
238
    }
239
240
    /**
241
     * @Route("/api/movies/{id}/recommendations", methods={"GET"})
242
     *
243
     * @param Movie                         $movie
244
     * @param MovieRepository               $movieRepository
245
     * @param MovieRecommendationRepository $repository
246
     *
247
     * @throws \Doctrine\DBAL\DBALException
248
     *
249
     * @return JsonResponse
250
     */
251
    public function getMoviesRecommendations(Movie $movie, MovieRepository $movieRepository, MovieRecommendationRepository $repository)
252
    {
253
        $user = $this->getUser();
254
        $sortRecommendedMovies = function (array $movie1, array $movie2) {
255
            return $movie2['rate'] <=> $movie1['rate'];
256
        };
257
258
        if ($user instanceof User) {
259
            $recommendedMoviesIds = $repository->findAllByMovieAndUser($movie->getId(), $user->getId());
260
            usort($recommendedMoviesIds, $sortRecommendedMovies);
261
            $recommendedMovies = $movieRepository->findAllByIdsWithFlags(array_map(function (array $recommendedMovie) {
262
                return $recommendedMovie['movie_id'];
263
            }, $recommendedMoviesIds), $user->getId());
264
        } else {
265
            $recommendedMoviesIds = $repository->findAllByMovie($movie->getId());
266
            usort($recommendedMoviesIds, $sortRecommendedMovies);
267
            $recommendedMovies = $movieRepository->findAllByIdsWithoutFlags(array_map(function (array $recommendedMovie) {
268
                return $recommendedMovie['movie_id'];
269
            }, $recommendedMoviesIds));
270
        }
271
272
        return $this->response($recommendedMovies, 200, [], [
273
            'groups' => ['list'],
274
        ]);
275
    }
276
277
    /**
278
     * @Route("/api/recommendations", methods={"GET"})
279
     *
280
     * @param Request                       $request
281
     * @param MovieRecommendationRepository $repository
282
     *
283
     * @return JsonResponse
284
     */
285
    public function getAllRecommendations(Request $request, MovieRecommendationRepository $repository)
286
    {
287
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
288
        $user = $this->getUser();
289
290
        $offset = (int) $request->get('offset', 0);
291
        $limit = $request->get('limit', null);
292
293
        $query = $repository->findAllByUser($user->getId());
294
        $movies = new PaginatedCollection($query, $offset, $limit, false);
295
296
        return $this->response($movies, 200, [], [
297
            'groups' => ['list'],
298
        ]);
299
    }
300
}
301