Completed
Push — master ( ac7de6...93eb40 )
by Valentyn
07:02
created

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