Completed
Push — master ( 3d9909...7a8301 )
by Valentyn
03:23
created

MovieController::getAllRecommendations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 0
cts 9
cp 0
rs 9.7666
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
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\Pagination\MovieCollection;
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
     *
70
     * @return \Symfony\Component\HttpFoundation\JsonResponse
71
     */
72
    public function getMovies(Movie $movie)
73
    {
74
        return $this->response($movie, 200, [], [
75
            'groups' => ['view'],
76
        ]);
77
    }
78
79
    /**
80
     * Get movies by title.
81
     *
82
     * @Route("/api/movies/search", methods={"POST"})
83
     *
84
     * @param SearchRequest $request
85
     * @param SearchService $searchService
86
     * @param Request       $currentRequest
87
     *
88
     * @throws \Exception
89
     *
90
     * @return \Symfony\Component\HttpFoundation\JsonResponse
91
     */
92 2
    public function getSearch(SearchRequest $request, SearchService $searchService, Request $currentRequest)
93
    {
94 2
        $offset = (int) $request->get('offset', 0);
95 2
        $limit = $request->get('limit', null);
96
97 2
        $query = $request->get('query');
98 2
        $movies = $searchService->findByQuery($query, $currentRequest->getLocale(), $offset, $limit);
99
100 2
        return $this->response($movies, 200, [], [
101 2
            'groups' => ['list'],
102
        ]);
103
    }
104
105
    /**
106
     * Create new movie.
107
     *
108
     * @Route("/api/movies", methods={"POST"})
109
     *
110
     * @param CreateMovieRequest $request
111
     * @param MovieManageService $service
112
     * @param ValidatorInterface $validator
113
     *
114
     * @throws \Exception
115
     *
116
     * @return \Symfony\Component\HttpFoundation\JsonResponse
117
     */
118 2
    public function postMovies(CreateMovieRequest $request, MovieManageService $service, ValidatorInterface $validator)
119
    {
120 2
        $this->denyAccessUnlessGranted(UserRoles::ROLE_ADMIN);
121
122 1
        $movie = $service->createMovieByRequest($request);
123 1
        $errors = $validator->validate($movie);
124
125 1
        if (count($errors)) {
126
            return $request->getErrorResponse($errors);
127
        }
128
129 1
        $entityManager = $this->getDoctrine()->getManager();
130 1
        $entityManager->persist($movie);
131 1
        $entityManager->flush();
132
133 1
        return $this->response($movie, 200, [], [
134 1
            'groups' => ['view'],
135
        ]);
136
    }
137
138
    /**
139
     * Add new recommendation
140
     *
141
     * @Route("/api/movies/{id}/recommendations", methods={"POST"})
142
143
     * @param NewMovieRecommendationRequest $request
144
     * @param Movie $originalMovie
145
     * @param EntityManagerInterface $em
146
     * @param ProducerInterface $producer
147
     * @return JsonResponse
148
     * @throws \Doctrine\ORM\ORMException
149
     */
150 1
    public function postMoviesRecommendations(NewMovieRecommendationRequest $request, Movie $originalMovie, EntityManagerInterface $em, ProducerInterface $producer)
151
    {
152 1
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
153
154 1
        $recommendation = $request->get('recommendation');
155 1
        $user = $this->getUser();
156
157 1
        if (!empty($recommendation['movie_id'])) {
158 1
            $recommendedMovie = $em->getReference(Movie::class, $recommendation['movie_id']);
159
160 1
            if ($recommendedMovie === null) {
161
                throw new NotFoundHttpException();
162
            }
163
164 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...
165 1
            $em->persist($originalMovie);
166
            try {
167 1
                $em->flush();
168
            } catch (UniqueConstraintViolationException $exception) {
169
                // It's ok..
170
            }
171
172 1
            return new JsonResponse();
173
        }
174
175
        $producer->sendEvent(AddRecommendationProcessor::ADD_RECOMMENDATION, json_encode([
176
            'tmdb_id' => $recommendation['tmdb_id'],
177
            'movie_id' => $originalMovie->getId(),
178
            'user_id' => $user->getId(),
179
        ]));
180
181
        return new JsonResponse();
182
    }
183
184
    /**
185
     * @Route("/api/movies/{id}/recommendations", methods={"GET"})
186
     *
187
     * @param Movie $movie
188
     * @param MovieRepository $movieRepository
189
     * @param MovieRecommendationRepository $repository
190
     * @return JsonResponse
191
     * @throws \Doctrine\DBAL\DBALException
192
     */
193
    public function getMoviesRecommendations(Movie $movie, MovieRepository $movieRepository, MovieRecommendationRepository $repository)
194
    {
195
        $user = $this->getUser();
196
        $sortRecommendedMovies = function (array $movie1, array $movie2) {
197
            return $movie2['rate'] <=> $movie1['rate'];
198
        };
199
200
        if ($user instanceof User) {
201
            $recommendedMoviesIds = $repository->findAllByMovieAndUser($movie->getId(), $user->getId());
202
            usort($recommendedMoviesIds, $sortRecommendedMovies);
203
            $recommendedMovies = $movieRepository->findAllByIdsWithFlags(array_map(function (array $recommendedMovie) {
204
                return $recommendedMovie['movie_id'];
205
            }, $recommendedMoviesIds), $user->getId());
206
        } else {
207
            $recommendedMoviesIds = $repository->findAllByMovie($movie->getId());
208
            usort($recommendedMoviesIds, $sortRecommendedMovies);
209
            $recommendedMovies = $movieRepository->findAllByIdsWithoutFlags(array_map(function (array $recommendedMovie) {
210
                return $recommendedMovie['movie_id'];
211
            }, $recommendedMoviesIds));
212
        }
213
        return $this->response($recommendedMovies, 200, [], [
214
            'groups' => ['list'],
215
        ]);
216
    }
217
218
    /**
219
     * @Route("/api/recommendations", methods={"GET"})
220
     */
221
    public function getAllRecommendations(Request $request, MovieRecommendationRepository $repository)
222
    {
223
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
224
        $user = $this->getUser();
225
226
        $offset = (int) $request->get('offset', 0);
227
        $limit = $request->get('limit', null);
228
229
        $query = $repository->findAllByUser($user->getId());
230
        $movies = new PaginatedCollection($query, $offset, $limit, false);
231
232
        return $this->response($movies, 200, [], [
233
            'groups' => ['list']
234
        ]);
235
    }
236
}
237