Completed
Push — master ( 71d672...bb4d5a )
by Valentyn
04:16
created

findRecommendedMovieById()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 5
cp 0
rs 9.9332
c 0
b 0
f 0
cc 4
nc 3
nop 3
crap 20
1
<?php
2
3
namespace App\Movies\Controller;
4
5
use App\Controller\BaseController;
6
use App\Movies\Entity\Movie;
7
use App\Movies\Entity\MovieRecommendation;
8
use App\Movies\EventListener\AddRecommendationProcessor;
9
use App\Movies\Repository\MovieRecommendationRepository;
10
use App\Movies\Repository\MovieRepository;
11
use App\Movies\Request\NewMovieRecommendationRequest;
12
use App\Movies\Request\RemoveMovieRecommendationRequest;
13
use App\Movies\Request\SearchRequest;
14
use App\Movies\Service\SearchService;
15
use App\Users\Entity\User;
16
use App\Users\Entity\UserRoles;
17
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Enqueue\Client\Message;
20
use Enqueue\Client\MessagePriority;
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
27
class MovieRecommendationController extends BaseController
28
{
29
    /**
30
     * Add new recommendation.
31
     *
32
     * @Route("/api/movies/{id}/recommendations", methods={"POST"})
33
     *
34
     * @param NewMovieRecommendationRequest $request
35
     * @param Movie                         $originalMovie
36
     * @param EntityManagerInterface        $em
37
     * @param ProducerInterface             $producer
38
     *
39
     * @throws \Doctrine\ORM\ORMException
40
     *
41
     * @return JsonResponse
42
     */
43 2
    public function postMoviesRecommendations(NewMovieRecommendationRequest $request, Movie $originalMovie, EntityManagerInterface $em, ProducerInterface $producer)
44
    {
45 2
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
46
47 2
        $recommendation = $request->get('recommendation');
48 2
        $user = $this->getUser();
49
50 2
        if (empty($recommendation['movie_id'])) {
51 1
            $message = new Message(json_encode([
52 1
                'tmdb_id' => $recommendation['tmdb_id'],
53 1
                'movie_id' => $originalMovie->getId(),
54 1
                'user_id' => $user->getId(),
55
            ]));
56 1
            $message->setPriority(MessagePriority::VERY_LOW);
57 1
            $producer->sendEvent(AddRecommendationProcessor::ADD_RECOMMENDATION, $message);
58
59 1
            return new JsonResponse();
60
        }
61
62 1
        $recommendedMovie = $em->getReference(Movie::class, $recommendation['movie_id']);
63
64 1
        if ($recommendedMovie === null) {
65
            throw new NotFoundHttpException();
66
        }
67
68 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...
69 1
        $em->persist($originalMovie);
70
        try {
71 1
            $em->flush();
72
        } catch (UniqueConstraintViolationException $exception) {
73
            // It's ok..
74
        }
75
76 1
        return new JsonResponse();
77
    }
78
79
    /**
80
     * Remove recommendation.
81
     *
82
     * @Route("/api/movies/{id}/recommendations", methods={"DELETE"})
83
     *
84
     * @param RemoveMovieRecommendationRequest $request
85
     * @param Movie                            $originalMovie
86
     * @param MovieRecommendationRepository    $repository
87
     * @param EntityManagerInterface           $em
88
     *
89
     * @return JsonResponse
90
     */
91
    public function deleteMoviesRecommendations(RemoveMovieRecommendationRequest $request, Movie $originalMovie, MovieRecommendationRepository $repository, EntityManagerInterface $em)
0 ignored issues
show
Unused Code introduced by
The parameter $repository is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
92
    {
93
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
94
95
        $user = $this->getUser();
96
97
        if (empty($request->get('movie_id'))) {
98
            $recommendedMovie = $this->findRecommendedMovieByTmdbId($originalMovie, $user, $request->get('tmdb_id'));
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...
99
            if ($recommendedMovie === null) {
100
                return new JsonResponse();
101
            }
102
103
            $em->remove($recommendedMovie);
104
            $em->flush();
105
106
            return new JsonResponse();
107
        }
108
109
        $recommendedMovie = $this->findRecommendedMovieById($originalMovie, $user, $request->get('movie_id'));
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...
110
        if ($recommendedMovie === null) {
111
            return new JsonResponse();
112
        }
113
114
        $em->remove($recommendedMovie);
115
        $em->flush();
116
117
        return new JsonResponse();
118
    }
119
120
    private function findRecommendedMovieById(Movie $originalMovie, User $user, int $id): ?MovieRecommendation
121
    {
122
        foreach ($originalMovie->getRecommendations() as $recommendation) {
123
            if ($recommendation->getUser()->getId() === $user->getId() && $recommendation->getRecommendedMovie()->getId() === $id) {
124
                return $recommendation;
125
            }
126
        }
127
128
        return null;
129
    }
130
131
    private function findRecommendedMovieByTmdbId(Movie $originalMovie, User $user, int $tmdbId): ?MovieRecommendation
132
    {
133
        foreach ($originalMovie->getRecommendations() as $recommendation) {
134
            if ($recommendation->getUser()->getId() === $user->getId() && $recommendation->getRecommendedMovie()->getTmdb()->getId() === $tmdbId) {
135
                return $recommendation;
136
            }
137
        }
138
139
        return null;
140
    }
141
142
    /**
143
     * @Route("/api/movies/{id}/recommendations", methods={"GET"})
144
     *
145
     * @param Movie                         $movie
146
     * @param MovieRepository               $movieRepository
147
     * @param MovieRecommendationRepository $repository
148
     *
149
     * @throws \Doctrine\DBAL\DBALException
150
     *
151
     * @return JsonResponse
152
     */
153
    public function getMoviesRecommendations(Movie $movie, MovieRepository $movieRepository, MovieRecommendationRepository $repository)
154
    {
155
        $user = $this->getUser();
156
        $sortRecommendedMovies = function (array $movie1, array $movie2) {
157
            return $movie2['rate'] <=> $movie1['rate'];
158
        };
159
160
        if ($user instanceof User) {
161
            $recommendedMoviesIds = $repository->findAllByMovieAndUser($movie->getId(), $user->getId());
162
            usort($recommendedMoviesIds, $sortRecommendedMovies);
163
            $recommendedMovies = $movieRepository->findAllByIdsWithFlags(array_map(function (array $recommendedMovie) {
164
                return $recommendedMovie['movie_id'];
165
            }, $recommendedMoviesIds), $user->getId(), $movie->getId());
166
        } else {
167
            $recommendedMoviesIds = $repository->findAllByMovie($movie->getId());
168
            usort($recommendedMoviesIds, $sortRecommendedMovies);
169
            $recommendedMovies = $movieRepository->findAllByIdsWithoutFlags(array_map(function (array $recommendedMovie) {
170
                return $recommendedMovie['movie_id'];
171
            }, $recommendedMoviesIds));
172
        }
173
174
        return $this->response($recommendedMovies, 200, [], [
175
            'groups' => ['list'],
176
        ]);
177
    }
178
179
    /**
180
     * Get movies by title.
181
     *
182
     * @Route("/api/movies/{id}/recommendations/search", methods={"POST"})
183
     *
184
     * @param int           $id
185
     * @param SearchRequest $request
186
     * @param SearchService $searchService
187
     * @param Request       $currentRequest
188
     *
189
     * @throws \App\Movies\Exception\TmdbMovieNotFoundException
190
     * @throws \App\Movies\Exception\TmdbRequestLimitException
191
     * @throws \ErrorException
192
     * @throws \Psr\SimpleCache\InvalidArgumentException
193
     *
194
     * @return \Symfony\Component\HttpFoundation\JsonResponse
195
     */
196
    public function getSearch(int $id, SearchRequest $request, SearchService $searchService, Request $currentRequest)
197
    {
198
        $offset = (int) $request->get('offset', 0);
199
        $limit = $request->get('limit', null);
200
201
        $query = $request->get('query');
202
203
        if (null === $user = $this->getUser()) {
204
            $movies = $searchService->findByQuery($query, $currentRequest->getLocale(), $offset, $limit);
205
        } else {
206
            $movies = $searchService->findByQueryWithUserRecommendedMovie($query, $id, $user->getId(), $currentRequest->getLocale(), $offset, $limit);
207
        }
208
209
        return $this->response($movies, 200, [], [
210
            'groups' => ['list'],
211
        ]);
212
    }
213
}
214