Completed
Push — master ( 914c6c...d7f41f )
by Valentyn
04:19
created

getMoviesRecommendations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2.004

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 9
cts 10
cp 0.9
rs 9.6333
c 0
b 0
f 0
cc 2
nc 2
nop 3
crap 2.004
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\Pagination\PaginatedCollection;
16
use App\Users\Entity\User;
17
use App\Users\Entity\UserRoles;
18
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
19
use Doctrine\ORM\EntityManagerInterface;
20
use Enqueue\Client\Message;
21
use Enqueue\Client\MessagePriority;
22
use Enqueue\Client\ProducerInterface;
23
use Symfony\Component\HttpFoundation\JsonResponse;
24
use Symfony\Component\HttpFoundation\Request;
25
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
26
use Symfony\Component\Routing\Annotation\Route;
27
28
class MovieRecommendationController extends BaseController
29
{
30
    /**
31
     * Add new recommendation.
32
     *
33
     * @Route("/api/movies/{id}/recommendations", methods={"POST"})
34
     *
35
     * @param NewMovieRecommendationRequest $request
36
     * @param Movie                         $originalMovie
37
     * @param EntityManagerInterface        $em
38
     * @param ProducerInterface             $producer
39
     *
40
     * @throws \Doctrine\ORM\ORMException
41
     *
42
     * @return JsonResponse
43
     */
44 5
    public function postMoviesRecommendations(NewMovieRecommendationRequest $request, Movie $originalMovie, EntityManagerInterface $em, ProducerInterface $producer)
45
    {
46 5
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
47
48 5
        $recommendation = $request->get('recommendation');
49 5
        $user = $this->getUser();
50
51 5
        if (empty($recommendation['movie_id'])) {
52 1
            $message = new Message(json_encode([
53 1
                'tmdb_id' => $recommendation['tmdb_id'],
54 1
                'movie_id' => $originalMovie->getId(),
55 1
                'user_id' => $user->getId(),
56
            ]));
57 1
            $message->setPriority(MessagePriority::VERY_LOW);
58 1
            $producer->sendEvent(AddRecommendationProcessor::ADD_RECOMMENDATION, $message);
59
60 1
            return new JsonResponse();
61
        }
62
63 4
        $recommendedMovie = $em->getReference(Movie::class, $recommendation['movie_id']);
64
65 4
        if ($recommendedMovie === null) {
66
            throw new NotFoundHttpException();
67
        }
68
69 4
        $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...
70 4
        $em->persist($originalMovie);
71
        try {
72 4
            $em->flush();
73
        } catch (UniqueConstraintViolationException $exception) {
74
            // It's ok..
75
        }
76
77 4
        return new JsonResponse();
78
    }
79
80
    /**
81
     * Remove recommendation.
82
     *
83
     * @Route("/api/movies/{id}/recommendations", methods={"DELETE"})
84
     *
85
     * @param RemoveMovieRecommendationRequest $request
86
     * @param Movie                            $originalMovie
87
     * @param MovieRecommendationRepository    $repository
88
     * @param EntityManagerInterface           $em
89
     *
90
     * @return JsonResponse
91
     */
92
    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...
93
    {
94
        $this->denyAccessUnlessGranted(UserRoles::ROLE_USER);
95
96
        $user = $this->getUser();
97
98
        if (empty($request->get('movie_id'))) {
99
            $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...
100
            if ($recommendedMovie === null) {
101
                return new JsonResponse();
102
            }
103
104
            $em->remove($recommendedMovie);
105
            $em->flush();
106
107
            return new JsonResponse();
108
        }
109
110
        $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...
111
        if ($recommendedMovie === null) {
112
            return new JsonResponse();
113
        }
114
115
        $em->remove($recommendedMovie);
116
        $em->flush();
117
118
        return new JsonResponse();
119
    }
120
121
    private function findRecommendedMovieById(Movie $originalMovie, User $user, int $id): ?MovieRecommendation
122
    {
123
        foreach ($originalMovie->getRecommendations() as $recommendation) {
124
            if ($recommendation->getUser()->getId() === $user->getId() && $recommendation->getRecommendedMovie()->getId() === $id) {
125
                return $recommendation;
126
            }
127
        }
128
129
        return null;
130
    }
131
132
    private function findRecommendedMovieByTmdbId(Movie $originalMovie, User $user, int $tmdbId): ?MovieRecommendation
133
    {
134
        foreach ($originalMovie->getRecommendations() as $recommendation) {
135
            if ($recommendation->getUser()->getId() === $user->getId() && $recommendation->getRecommendedMovie()->getTmdb()->getId() === $tmdbId) {
136
                return $recommendation;
137
            }
138
        }
139
140
        return null;
141
    }
142
143
    /**
144
     * @Route("/api/movies/{id}/recommendations", methods={"GET"})
145
     *
146
     * @param Request $request
147
     * @param Movie $movie
148
     * @param MovieRecommendationRepository $repository
149
     *
150
     * @return JsonResponse
151
     */
152 1
    public function getMoviesRecommendations(Request $request, Movie $movie, MovieRecommendationRepository $repository)
153
    {
154 1
        $user = $this->getUser();
155
156 1
        $offset = (int) $request->get('offset', 0);
157 1
        $limit = $request->get('limit', null);
158
159 1
        if ($user instanceof User) {
160 1
            $recommendedMovies = $repository->findAllByMovieAndUser($movie->getId(), $user->getId());
161
        } else {
162
            $recommendedMovies = $repository->findAllByMovie($movie->getId());
163
        }
164
165 1
        $recommendedMovies = new PaginatedCollection($recommendedMovies, $offset, $limit, false);
166
167 1
        return $this->response($recommendedMovies, 200, [], [
168 1
            'groups' => ['list'],
169
        ]);
170
    }
171
172
    /**
173
     * Get movies by title.
174
     *
175
     * @Route("/api/movies/{id}/recommendations/search", methods={"POST"})
176
     *
177
     * @param int           $id
178
     * @param SearchRequest $request
179
     * @param SearchService $searchService
180
     * @param Request       $currentRequest
181
     *
182
     * @throws \App\Movies\Exception\TmdbMovieNotFoundException
183
     * @throws \App\Movies\Exception\TmdbRequestLimitException
184
     * @throws \ErrorException
185
     * @throws \Psr\SimpleCache\InvalidArgumentException
186
     *
187
     * @return \Symfony\Component\HttpFoundation\JsonResponse
188
     */
189
    public function getSearch(int $id, SearchRequest $request, SearchService $searchService, Request $currentRequest)
190
    {
191
        $offset = (int) $request->get('offset', 0);
192
        $limit = $request->get('limit', null);
193
194
        $query = $request->get('query');
195
196
        if (null === $user = $this->getUser()) {
197
            $movies = $searchService->findByQuery($query, $currentRequest->getLocale(), $offset, $limit);
198
        } else {
199
            $movies = $searchService->findByQueryWithUserRecommendedMovie($query, $id, $user->getId(), $currentRequest->getLocale(), $offset, $limit);
200
        }
201
202
        return $this->response($movies, 200, [], [
203
            'groups' => ['list'],
204
        ]);
205
    }
206
}
207