Completed
Push — master ( 685b70...d41a9c )
by Valentyn
03:12
created

MovieController::getMoviesRecommendations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 0
cts 15
cp 0
rs 9.52
c 0
b 0
f 0
cc 2
nc 2
nop 3
crap 6
1
<?php
2
3
namespace App\Movies\Controller;
4
5
use App\Controller\BaseController;
6
use App\Movies\Entity\Movie;
7
use App\Movies\EventListener\AddRecommendationProcessor;
8
use App\Movies\EventListener\SimilarMoviesProcessor;
9
use App\Movies\Repository\MovieRecommendationRepository;
10
use App\Movies\Repository\MovieRepository;
11
use App\Movies\Request\CreateMovieRequest;
12
use App\Movies\Request\NewMovieRecommendationRequest;
13
use App\Movies\Request\SearchRequest;
14
use App\Movies\Service\MovieManageService;
15
use App\Movies\Service\SearchService;
16
use App\Pagination\PaginatedCollection;
17
use App\Users\Entity\User;
18
use App\Users\Entity\UserRoles;
19
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
20
use Doctrine\ORM\EntityManagerInterface;
21
use Enqueue\Client\ProducerInterface;
22
use Symfony\Component\HttpFoundation\JsonResponse;
23
use Symfony\Component\HttpFoundation\Request;
24
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
25
use Symfony\Component\Routing\Annotation\Route;
26
use Symfony\Component\Validator\Validator\ValidatorInterface;
27
28
/**
29
 * Class MovieController.
30
 */
31
class MovieController extends BaseController
32
{
33
    /**
34
     * Get all movies.
35
     *
36
     * @Route("/api/movies", methods={"GET"})
37
     *
38
     * @param Request         $request
39
     * @param MovieRepository $movieRepository
40
     *
41
     * @return \Symfony\Component\HttpFoundation\JsonResponse
42
     */
43 4
    public function getAll(Request $request, MovieRepository $movieRepository)
44
    {
45 4
        $user = $this->getUser();
46
47 4
        if ($user instanceof User) {
48
            $movies = $movieRepository->findAllWithIsUserWatchedFlag($user);
49
        } else {
50 4
            $movies = $movieRepository->findAllWithIsGuestWatchedFlag($this->getGuest());
51
        }
52
53 4
        $offset = (int) $request->get('offset', 0);
54 4
        $limit = $request->get('limit', null);
55
56 4
        $movies = new PaginatedCollection($movies, $offset, $limit);
57
58 4
        return $this->response($movies, 200, [], [
59 4
            'groups' => ['list'],
60
        ]);
61
    }
62
63
    /**
64
     * Get movie resource.
65
     *
66
     * @Route("/api/movies/{id}", methods={"GET"})
67
     *
68
     * @param Movie             $movie
69
     * @param ProducerInterface $producer
70
     *
71
     * @return \Symfony\Component\HttpFoundation\JsonResponse
72
     */
73
    public function getMovies(Movie $movie, ProducerInterface $producer)
74
    {
75
        if (count($movie->getSimilarMovies()) === 0) {
76
            $producer->sendEvent(SimilarMoviesProcessor::LOAD_SIMILAR_MOVIES, json_encode($movie->getId()));
77
        }
78
79
        return $this->response($movie, 200, [], [
80
            'groups' => ['view'],
81
        ]);
82
    }
83
84
    /**
85
     * Get movies by title.
86
     *
87
     * @Route("/api/movies/search", methods={"POST"})
88
     *
89
     * @param SearchRequest $request
90
     * @param SearchService $searchService
91
     * @param Request       $currentRequest
92
     *
93
     * @throws \Exception
94
     *
95
     * @return \Symfony\Component\HttpFoundation\JsonResponse
96
     */
97 2
    public function getSearch(SearchRequest $request, SearchService $searchService, Request $currentRequest)
98
    {
99 2
        $offset = (int) $request->get('offset', 0);
100 2
        $limit = $request->get('limit', null);
101
102 2
        $query = $request->get('query');
103 2
        $movies = $searchService->findByQuery($query, $currentRequest->getLocale(), $offset, $limit);
104
105 2
        return $this->response($movies, 200, [], [
106 2
            'groups' => ['list'],
107
        ]);
108
    }
109
110
    /**
111
     * Create new movie.
112
     *
113
     * @Route("/api/movies", methods={"POST"})
114
     *
115
     * @param CreateMovieRequest $request
116
     * @param MovieManageService $service
117
     * @param ValidatorInterface $validator
118
     *
119
     * @throws \Exception
120
     *
121
     * @return \Symfony\Component\HttpFoundation\JsonResponse
122
     */
123 2
    public function postMovies(CreateMovieRequest $request, MovieManageService $service, ValidatorInterface $validator)
124
    {
125 2
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
126
127 1
        $movie = $service->createMovieByRequest($request);
128 1
        $errors = $validator->validate($movie);
129
130 1
        if (count($errors)) {
131
            return $request->getErrorResponse($errors);
132
        }
133
134 1
        $entityManager = $this->getDoctrine()->getManager();
135 1
        $entityManager->persist($movie);
136 1
        $entityManager->flush();
137
138 1
        return $this->response($movie, 200, [], [
139 1
            'groups' => ['view'],
140
        ]);
141
    }
142
143
    /**
144
     * Add new recommendation.
145
     *
146
     * @Route("/api/movies/{id}/recommendations", methods={"POST"})
147
148
     *
149
     * @param NewMovieRecommendationRequest $request
150
     * @param Movie                         $originalMovie
151
     * @param EntityManagerInterface        $em
152
     * @param ProducerInterface             $producer
153
     *
154
     * @throws \Doctrine\ORM\ORMException
155
     *
156
     * @return JsonResponse
157
     */
158 1
    public function postMoviesRecommendations(NewMovieRecommendationRequest $request, Movie $originalMovie, EntityManagerInterface $em, ProducerInterface $producer)
159
    {
160 1
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
161
162 1
        $recommendation = $request->get('recommendation');
163 1
        $user = $this->getUser();
164
165 1
        if (!empty($recommendation['movie_id'])) {
166 1
            $recommendedMovie = $em->getReference(Movie::class, $recommendation['movie_id']);
167
168 1
            if ($recommendedMovie === null) {
169
                throw new NotFoundHttpException();
170
            }
171
172 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...
173 1
            $em->persist($originalMovie);
174
            try {
175 1
                $em->flush();
176
            } catch (UniqueConstraintViolationException $exception) {
177
                // It's ok..
178
            }
179
180 1
            return new JsonResponse();
181
        }
182
183
        $producer->sendEvent(AddRecommendationProcessor::ADD_RECOMMENDATION, json_encode([
184
            'tmdb_id' => $recommendation['tmdb_id'],
185
            'movie_id' => $originalMovie->getId(),
186
            'user_id' => $user->getId(),
187
        ]));
188
189
        return new JsonResponse();
190
    }
191
192
    /**
193
     * @Route("/api/movies/{id}/recommendations", methods={"GET"})
194
     *
195
     * @param Movie                         $movie
196
     * @param MovieRepository               $movieRepository
197
     * @param MovieRecommendationRepository $repository
198
     *
199
     * @throws \Doctrine\DBAL\DBALException
200
     *
201
     * @return JsonResponse
202
     */
203
    public function getMoviesRecommendations(Movie $movie, MovieRepository $movieRepository, MovieRecommendationRepository $repository)
204
    {
205
        $user = $this->getUser();
206
        $sortRecommendedMovies = function (array $movie1, array $movie2) {
207
            return $movie2['rate'] <=> $movie1['rate'];
208
        };
209
210
        if ($user instanceof User) {
211
            $recommendedMoviesIds = $repository->findAllByMovieAndUser($movie->getId(), $user->getId());
212
            usort($recommendedMoviesIds, $sortRecommendedMovies);
213
            $recommendedMovies = $movieRepository->findAllByIdsWithFlags(array_map(function (array $recommendedMovie) {
214
                return $recommendedMovie['movie_id'];
215
            }, $recommendedMoviesIds), $user->getId());
216
        } else {
217
            $recommendedMoviesIds = $repository->findAllByMovie($movie->getId());
218
            usort($recommendedMoviesIds, $sortRecommendedMovies);
219
            $recommendedMovies = $movieRepository->findAllByIdsWithoutFlags(array_map(function (array $recommendedMovie) {
220
                return $recommendedMovie['movie_id'];
221
            }, $recommendedMoviesIds));
222
        }
223
224
        return $this->response($recommendedMovies, 200, [], [
225
            'groups' => ['list'],
226
        ]);
227
    }
228
229
    /**
230
     * @Route("/api/recommendations", methods={"GET"})
231
     *
232
     * @param Request                       $request
233
     * @param MovieRecommendationRepository $repository
234
     *
235
     * @return JsonResponse
236
     */
237
    public function getAllRecommendations(Request $request, MovieRecommendationRepository $repository)
238
    {
239
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
240
        $user = $this->getUser();
241
242
        $offset = (int) $request->get('offset', 0);
243
        $limit = $request->get('limit', null);
244
245
        $query = $repository->findAllByUser($user->getId());
246
        $movies = new PaginatedCollection($query, $offset, $limit, false);
247
248
        return $this->response($movies, 200, [], [
249
            'groups' => ['list'],
250
        ]);
251
    }
252
}
253