Completed
Push — master ( 3d822c...064d2b )
by Valentyn
32:01
created

MovieRepository::getAllInterestedMoviesByUserId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
ccs 9
cts 9
cp 1
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Movies\Repository;
6
7
use App\Guests\Entity\GuestSession;
8
use App\Movies\Entity\Movie;
9
use App\Users\Entity\User;
10
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
11
use Doctrine\ORM\Query;
12
use Doctrine\ORM\QueryBuilder;
13
use Symfony\Bridge\Doctrine\RegistryInterface;
14
15
/**
16
 * @method Movie|null find($id, $lockMode = null, $lockVersion = null)
17
 * @method Movie|null findOneBy(array $criteria, array $orderBy = null)
18
 * @method Movie[]    findAll()
19
 * @method Movie[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
20
 */
21
class MovieRepository extends ServiceEntityRepository
22
{
23 20
    public function __construct(RegistryInterface $registry)
24
    {
25 20
        parent::__construct($registry, Movie::class);
26 20
    }
27
28 16
    private function getBaseQuery(): QueryBuilder
29
    {
30 16
        return $this->createQueryBuilder('m')
31 16
            ->leftJoin('m.translations', 'mt')
32 16
            ->addSelect('mt')
33 16
            ->leftJoin('m.genres', 'mg')
34 16
            ->addSelect('mg')
35 16
            ->leftJoin('mg.translations', 'mgt')
36 16
            ->addSelect('mgt');
37
    }
38
39
    /**
40
     * @param int       $id
41
     * @param User|null $user
42
     *
43
     * @throws \Doctrine\ORM\NoResultException
44
     * @throws \Doctrine\ORM\NonUniqueResultException
45
     *
46
     * @return Movie|null
47
     */
48 2
    public function findOneForMoviePage(int $id, ?User $user = null): ?Movie
49
    {
50 2
        if ($user === null) {
51 2
            return $this->getBaseQuery()
52 2
                ->where('m.id = :id')
53 2
                ->setParameter('id', $id)
54 2
                ->getQuery()
55 2
                ->getSingleResult();
56
        }
57
58
        $result = $this->getBaseQuery()
59
            ->where('m.id = :id')
60
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
61
            ->addSelect('uwm')
62
            ->leftJoin('m.userRecommendedMovie', 'urm', 'WITH', 'urm.user = :user_id AND urm.originalMovie = :id')
63
            ->addSelect('urm')
64
            ->setParameter('user_id', $user->getId())
65
            ->setParameter('id', $id)
66
            ->getQuery()
67
            ->getSingleResult();
68
69
        return $result;
70
    }
71
72
    public function findAllByIdsWithFlags(array $ids, int $userId, int $originalMovieId)
73
    {
74
        $result = $this->getBaseQuery()
75
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id') // if this relation exists then user has already watched this movie
76
            ->addSelect('uwm')
77
            ->leftJoin('m.userRecommendedMovie', 'urm', 'WITH', 'urm.user = :user_id AND urm.originalMovie = :original_movie_id')
78
            ->addSelect('urm')
79
            ->where('m.id IN (:ids)')
80
            ->setParameter('user_id', $userId)
81
            ->setParameter('original_movie_id', $originalMovieId)
82
            ->setParameter('ids', $ids)
83
            ->getQuery()
84
            ->getResult();
85
86
        // Sorting here because ORDER BY FIELD(m.id, ...$ids) not working in postgres, we need to use joins on sorted table and so on, but I dont want to
87
        // todo => add sorting to sql
88
        $reversedIds = array_flip($ids);
89
        usort($result, function (Movie $movie1, Movie $movie2) use ($reversedIds) {
90
            return $reversedIds[$movie1->getId()] <=> $reversedIds[$movie2->getId()];
91
        });
92
93
        return $result;
94
    }
95
96
    public function findAllByIdsWithoutFlags(array $ids)
97
    {
98
        $result = $this->findAllByIds($ids);
99
100
        // Sorting here because ORDER BY FIELD(m.id, ...$ids) not working in postgres, we need to use joins on sorted table and so on, but I dont want to
101
        // todo => add sorting to sql
102
        $reversedIds = array_flip($ids);
103
        usort($result, function (Movie $movie1, Movie $movie2) use ($reversedIds) {
104
            return $reversedIds[$movie1->getId()] <=> $reversedIds[$movie2->getId()];
105
        });
106
107
        return $result;
108
    }
109
110
    public function findAllWithIsUserWatchedFlag(User $user)
111
    {
112
        $result = $this->getBaseQuery()
113
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id') // if this relation exists then user has already watched this movie
114
            ->addSelect('uwm')
115
            ->setParameter('user_id', $user->getId())
116
            ->orderBy('m.id', 'DESC')
117
            ->getQuery();
118
119
        return $result;
120
    }
121
122 12
    public function findAllWithIsGuestWatchedFlag(?GuestSession $guestSession)
123
    {
124 12
        $guestSessionId = $guestSession ? $guestSession->getId() : 0;
125
126 12
        $result = $this->getBaseQuery()
127 12
            ->leftJoin('m.guestWatchedMovie', 'gwm', 'WITH', 'gwm.guestSession = :guest_session_id') // if this relation exists then guest has already watched this movie
128 12
            ->addSelect('gwm')
129 12
            ->setParameter('guest_session_id', $guestSessionId)
130 12
            ->orderBy('m.id', 'DESC')
131 12
            ->getQuery();
132
133 12
        return $result;
134
    }
135
136
    /**
137
     * @param array $ids
138
     *
139
     * @return array|Movie[]
140
     */
141
    public function findAllByIds(array $ids)
142
    {
143
        $result = $this->getBaseQuery()
144
            ->where('m.id IN (:ids)')
145
            ->setParameter('ids', $ids)
146
            ->getQuery()
147
            ->getResult();
148
149
        return $result;
150
    }
151
152
    /**
153
     * @param array $ids
154
     *
155
     * @return array|Movie[]
156
     */
157
    public function findAllByIdsWithSimilarMovies(array $ids): array
158
    {
159
        $result = $this->createQueryBuilder('m')
160
            ->leftJoin('m.similarMovies', 'sm')
161
            ->addSelect('sm')
162
            ->where('m.id IN (:ids)')
163
            ->setParameter('ids', $ids)
164
            ->getQuery()
165
            ->getScalarResult();
166
167
        return $result;
168
    }
169
170
    /**
171
     * @param array $ids
172
     *
173
     * @return array|Movie[]
174
     */
175 1
    public function findAllByTmdbIds(array $ids)
176
    {
177 1
        $result = $this->getBaseQuery()
178 1
            ->where('m.tmdb.id IN (:ids)')
179 1
            ->setParameter('ids', $ids)
180 1
            ->getQuery()
181 1
            ->getResult();
182
183 1
        return $result;
184
    }
185
186
    /**
187
     * @param array $ids
188
     *
189
     * @return array of int
190
     */
191
    public function findAllIdsByTmdbIds(array $ids)
192
    {
193
        $result = $this->createQueryBuilder('m')
194
            ->select('m.id, m.tmdb.voteAverage, m.releaseDate')
195
            ->where('m.tmdb.id IN (:ids)')
196
            ->setParameter('ids', $ids)
197
            ->getQuery()
198
            ->getScalarResult();
199
200
        return $result;
201
    }
202
203 2
    public function getAllWatchedMoviesByUserId(int $userId): Query
204
    {
205 2
        $result = $this->getBaseQuery()
206 2
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
207 2
            ->addSelect('uwm')
208 2
            ->setParameter('user_id', $userId)
209 2
            ->andWhere('uwm.id != 0')
210 2
            ->orderBy('uwm.id', 'DESC')
211 2
            ->getQuery();
212
213 2
        return $result;
214
    }
215
216 1
    public function getAllInterestedMoviesByUserId(int $userId): Query
217
    {
218 1
        $result = $this->getBaseQuery()
219 1
            ->leftJoin('m.userInterestedMovie', 'uim', 'WITH', 'uim.user = :user_id')
220 1
            ->addSelect('uim')
221 1
            ->setParameter('user_id', $userId)
222 1
            ->andWhere('uim.id != 0')
223 1
            ->orderBy('uim.id', 'DESC')
224 1
            ->getQuery();
225
226 1
        return $result;
227
    }
228
229
    public function findAllQuery()
230
    {
231
        $result = $this->getBaseQuery()
232
            ->orderBy('m.id', 'DESC')
233
            ->getQuery();
234
235
        return $result;
236
    }
237
238 2
    public function findByTitleQuery(string $query)
239
    {
240 2
        $query = mb_strtolower($query);
241 2
        $result = $this->getBaseQuery()
242 2
            ->andWhere('LOWER(m.originalTitle) LIKE :title OR LOWER(mt.title) LIKE :title')
243 2
            ->setParameter('title', "%{$query}%")
244 2
            ->getQuery();
245
246 2
        return $result;
247
    }
248
249
    public function findByTitleWithUserRecommendedMovieQuery(string $query, int $userId, int $originalMovieId)
250
    {
251
        $query = mb_strtolower($query);
252
        $result = $this->getBaseQuery()
253
            ->andWhere('LOWER(m.originalTitle) LIKE :title OR LOWER(mt.title) LIKE :title')
254
            ->setParameter('title', "%{$query}%")
255
            ->leftJoin('m.userRecommendedMovie', 'urm', 'WITH', 'urm.user = :user_id AND urm.originalMovie = :movie_id')
256
            ->addSelect('urm')
257
            ->setParameter('user_id', $userId)
258
            ->setParameter('movie_id', $originalMovieId)
259
            ->getQuery();
260
261
        return $result;
262
    }
263
264 7
    public function findOneByIdOrTmdbId(?int $id = null, ?int $tmdb_id = null)
265
    {
266 7
        if ($id === null && $tmdb_id === null) {
267
            throw new \InvalidArgumentException('Movie ID or TMDB ID should be provided');
268
        }
269
270 7
        return $id ? $this->find($id) : $this->findOneBy(['tmdb.id' => $tmdb_id]);
271
    }
272
}
273