Completed
Push — master ( bb4d5a...e8c3b1 )
by Valentyn
04:47
created

findByTitleWithUserRecommendedMovieQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 0
cts 11
cp 0
rs 9.7998
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 2
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 16
    public function __construct(RegistryInterface $registry)
24
    {
25 16
        parent::__construct($registry, Movie::class);
26 16
    }
27
28 12
    private function getBaseQuery(): QueryBuilder
29
    {
30 12
        return $this->createQueryBuilder('m')
31 12
            ->leftJoin('m.translations', 'mt')
32 12
            ->addSelect('mt')
33 12
            ->leftJoin('m.genres', 'mg')
34 12
            ->addSelect('mg')
35 12
            ->leftJoin('mg.translations', 'mgt')
36 12
            ->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 1
    public function findOneForMoviePage(int $id, ?User $user = null): ?Movie
49
    {
50 1
        if ($user === null) {
51 1
            return $this->getBaseQuery()
52 1
                ->where('m.id = :id')
53 1
                ->setParameter('id', $id)
54 1
                ->getQuery()
55 1
                ->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 findAllByIdsWithIsWatchedFlag(array $ids, int $userId)
97
    {
98
        $result = $this->getBaseQuery()
99
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
100
            ->addSelect('uwm')
101
            ->where('m.id IN (:ids)')
102
            ->setParameter('user_id', $userId)
103
            ->setParameter('ids', $ids)
104
            ->getQuery();
105
106
        return $result;
107
    }
108
109
    public function findAllByIdsWithoutFlags(array $ids)
110
    {
111
        $result = $this->findAllByIds($ids);
112
113
        // 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
114
        // todo => add sorting to sql
115
        $reversedIds = array_flip($ids);
116
        usort($result, function (Movie $movie1, Movie $movie2) use ($reversedIds) {
117
            return $reversedIds[$movie1->getId()] <=> $reversedIds[$movie2->getId()];
118
        });
119
120
        return $result;
121
    }
122
123
    public function findAllWithIsUserWatchedFlag(User $user)
124
    {
125
        $result = $this->getBaseQuery()
126
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id') // if this relation exists then user has already watched this movie
127
            ->addSelect('uwm')
128
            ->setParameter('user_id', $user->getId())
129
            ->orderBy('m.id', 'DESC')
130
            ->getQuery();
131
132
        return $result;
133
    }
134
135 8
    public function findAllWithIsGuestWatchedFlag(?GuestSession $guestSession)
136
    {
137 8
        $guestSessionId = $guestSession ? $guestSession->getId() : 0;
138
139 8
        $result = $this->getBaseQuery()
140 8
            ->leftJoin('m.guestWatchedMovie', 'gwm', 'WITH', 'gwm.guestSession = :guest_session_id') // if this relation exists then guest has already watched this movie
141 8
            ->addSelect('gwm')
142 8
            ->setParameter('guest_session_id', $guestSessionId)
143 8
            ->orderBy('m.id', 'DESC')
144 8
            ->getQuery();
145
146 8
        return $result;
147
    }
148
149
    /**
150
     * @param array $ids
151
     *
152
     * @return array|Movie[]
153
     */
154
    public function findAllByIds(array $ids)
155
    {
156
        $result = $this->getBaseQuery()
157
            ->where('m.id IN (:ids)')
158
            ->setParameter('ids', $ids)
159
            ->getQuery()
160
            ->getResult();
161
162
        return $result;
163
    }
164
165
    public function findAllByIdsQuery(array $ids): Query
166
    {
167
        $result = $this->getBaseQuery()
168
            ->where('m.id IN (:ids)')
169
            ->setParameter('ids', $ids)
170
            ->getQuery();
171
172
        return $result;
173
    }
174
175
    /**
176
     * @param array $ids
177
     *
178
     * @return array|Movie[]
179
     */
180
    public function findAllByIdsWithSimilarMovies(array $ids): array
181
    {
182
        $result = $this->createQueryBuilder('m')
183
            ->leftJoin('m.similarMovies', 'sm')
184
            ->addSelect('sm')
185
            ->where('m.id IN (:ids)')
186
            ->setParameter('ids', $ids)
187
            ->getQuery()
188
            ->getScalarResult();
189
190
        return $result;
191
    }
192
193
    /**
194
     * @param array $ids
195
     *
196
     * @return array|Movie[]
197
     */
198 1
    public function findAllByTmdbIds(array $ids)
199
    {
200 1
        $result = $this->getBaseQuery()
201 1
            ->where('m.tmdb.id IN (:ids)')
202 1
            ->setParameter('ids', $ids)
203 1
            ->getQuery()
204 1
            ->getResult();
205
206 1
        return $result;
207
    }
208
209
    /**
210
     * @param array $ids
211
     *
212
     * @return array of int
213
     */
214
    public function findAllIdsByTmdbIds(array $ids)
215
    {
216
        $result = $this->createQueryBuilder('m')
217
            ->select('m.id, m.tmdb.voteAverage')
218
            ->where('m.tmdb.id IN (:ids)')
219
            ->setParameter('ids', $ids)
220
            ->getQuery()
221
            ->getScalarResult();
222
223
        return $result;
224
    }
225
226 2
    public function getAllWatchedMoviesByUserId(int $userId): Query
227
    {
228 2
        $result = $this->getBaseQuery()
229 2
            ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
230 2
            ->addSelect('uwm')
231 2
            ->setParameter('user_id', $userId)
232 2
            ->andWhere('uwm.id != 0')
233 2
            ->orderBy('uwm.id', 'DESC')
234 2
            ->getQuery();
235
236 2
        return $result;
237
    }
238
239
    public function findAllQuery()
240
    {
241
        $result = $this->getBaseQuery()
242
            ->orderBy('m.id', 'DESC')
243
            ->getQuery();
244
245
        return $result;
246
    }
247
248 2
    public function findByTitleQuery(string $query)
249
    {
250 2
        $query = mb_strtolower($query);
251 2
        $result = $this->getBaseQuery()
252 2
            ->andWhere('LOWER(m.originalTitle) LIKE :title OR LOWER(mt.title) LIKE :title')
253 2
            ->setParameter('title', "%{$query}%")
254 2
            ->getQuery();
255
256 2
        return $result;
257
    }
258
259
    public function findByTitleWithUserRecommendedMovieQuery(string $query, int $userId, int $originalMovieId)
260
    {
261
        $query = mb_strtolower($query);
262
        $result = $this->getBaseQuery()
263
            ->andWhere('LOWER(m.originalTitle) LIKE :title OR LOWER(mt.title) LIKE :title')
264
            ->setParameter('title', "%{$query}%")
265
            ->leftJoin('m.userRecommendedMovie', 'urm', 'WITH', 'urm.user = :user_id AND urm.originalMovie = :movie_id')
266
            ->addSelect('urm')
267
            ->setParameter('user_id', $userId)
268
            ->setParameter('movie_id', $originalMovieId)
269
            ->getQuery();
270
271
        return $result;
272
    }
273
274 7
    public function findOneByIdOrTmdbId(?int $id = null, ?int $tmdb_id = null)
275
    {
276 7
        if ($id === null && $tmdb_id === null) {
277
            throw new \InvalidArgumentException('Movie ID or TMDB ID should be provided');
278
        }
279
280 7
        return $id ? $this->find($id) : $this->findOneBy(['tmdb.id' => $tmdb_id]);
281
    }
282
}
283