Completed
Push — master ( df0c35...7f3dc3 )
by Valentyn
03:58
created

MovieRepository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
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 44
    public function __construct(RegistryInterface $registry)
24
    {
25 44
        parent::__construct($registry, Movie::class);
26 44
    }
27
28 40
    private function getBaseQuery(): QueryBuilder
29
    {
30 40
        return $this->createQueryBuilder('m')
31 40
            ->leftJoin('m.translations', 'mt', null, null, 'mt.locale')
32 40
            ->addSelect('mt')
33 40
            ->leftJoin('m.genres', 'mg')
34 40
            ->addSelect('mg')
35 40
            ->leftJoin('mg.translations', 'mgt', null, null, 'mgt.locale')
36 40
            ->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
            ->leftJoin('m.userInterestedMovie', 'uim', 'WITH', 'uim.user = :user_id AND uim.movie = :id')
65
            ->addSelect('uim')
66
            ->setParameter('user_id', $user->getId())
67
            ->setParameter('id', $id)
68
            ->getQuery()
69
            ->getSingleResult();
70
71
        return $result;
72
    }
73
74
    /**
75
     * @return QueryBuilder[]
76
     */
77 34
    public function findAllWithIsWatchedFlag(?User $user = null, ?GuestSession $guest = null): array
78
    {
79 34
        $items = $this->getBaseQuery();
80
81 34
        if ($user !== null) {
82
            $items
83
                ->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
84
                ->addSelect('uwm')
85
                ->setParameter('user_id', $user->getId());
86
        }
87
88 34
        if ($guest !== null) {
89
            $items
90
                ->leftJoin('m.guestWatchedMovie', 'gwm', 'WITH', 'gwm.guestSession = :guest_id')
91
                ->addSelect('gwm')
92
                ->setParameter('guest_id', $guest->getId());
93
        }
94
95 34
        $items->where('m.id IN (:ids)');
96
97
        /** Ids query */
98 34
        $ids = $this->createQueryBuilder('m')
99 34
            ->select('m.id')
100 34
            ->orderBy('m.id', 'DESC');
101
102 34
        return [$items, $ids];
103
    }
104
105
    /**
106
     * @param array $ids
107
     *
108
     * @return array|Movie[]
109
     */
110
    public function findAllByIds(array $ids)
111
    {
112
        $result = $this->getBaseQuery()
113
            ->where('m.id IN (:ids)')
114
            ->setParameter('ids', $ids)
115
            ->getQuery()
116
            ->getResult();
117
118
        return $result;
119
    }
120
121
    /**
122
     * @param array $ids
123
     *
124
     * @return array|Movie[]
125
     */
126
    public function findAllByIdsWithSimilarMovies(array $ids): array
127
    {
128
        $result = $this->createQueryBuilder('m')
129
            ->leftJoin('m.similarMovies', 'sm')
130
            ->addSelect('sm')
131
            ->where('m.id IN (:ids)')
132
            ->setParameter('ids', $ids)
133
            ->getQuery()
134
            ->getScalarResult();
135
136
        return $result;
137
    }
138
139
    /**
140
     * @param array $ids
141
     *
142
     * @return array|Movie[]
143
     */
144 1
    public function findAllByTmdbIds(array $ids)
145
    {
146 1
        $result = $this->getBaseQuery()
147 1
            ->where('m.tmdb.id IN (:ids)')
148 1
            ->setParameter('ids', $ids)
149 1
            ->getQuery()
150 1
            ->getResult();
151
152 1
        return $result;
153
    }
154
155
    /**
156
     * @param array $ids
157
     *
158
     * @return array of int
159
     */
160
    public function findAllIdsByTmdbIds(array $ids)
161
    {
162
        $result = $this->createQueryBuilder('m')
163
            ->select('m.id, m.tmdb.voteAverage, m.releaseDate')
164
            ->where('m.tmdb.id IN (:ids)')
165
            ->setParameter('ids', $ids)
166
            ->getQuery()
167
            ->getScalarResult();
168
169
        return $result;
170
    }
171
172 2
    public function getAllWatchedMoviesByUserId(User $owner, ?User $currentUser = null): array
173
    {
174 2
        $items = $this->getBaseQuery()
175 2
            ->leftJoin('m.ownerWatchedMovie', 'owm', 'WITH', 'owm.user = :owner_id')
176 2
            ->addSelect('owm')
177 2
            ->setParameter('owner_id', $owner->getId());
178
179 2
        if ($currentUser !== null) {
180 2
            $items->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
181 2
                ->addSelect('uwm')
182 2
                ->setParameter('user_id', $currentUser->getId());
183
        }
184
185 2
        $items->where('m.id IN (:ids)');
186
187 2
        $ids = $this->createQueryBuilder('m')
188 2
            ->select('m.id')
189 2
            ->leftJoin('m.ownerWatchedMovie', 'owm', 'WITH', 'owm.user = :owner_id')
190 2
            ->where('owm.id != 0')
191 2
            ->setParameter('owner_id', $owner->getId())
192 2
            ->orderBy('owm.id', 'DESC');
193
194 2
        $count = $this->createQueryBuilder('m')
195 2
            ->select('COUNT(m.id)')
196 2
            ->leftJoin('m.ownerWatchedMovie', 'owm', 'WITH', 'owm.user = :owner_id')
197 2
            ->setParameter('owner_id', $owner->getId())
198
199 2
            ->where('owm.id != 0');
200
201 2
        return [$items->getQuery(), $ids->getQuery(), $count->getQuery()];
202
    }
203
204 3
    public function getAllInterestedMoviesByUserId(int $profileOwnerId, ?User $currentUser = null): Query
205
    {
206 3
        $result = $this->getBaseQuery()
207 3
            ->leftJoin('m.userInterestedMovie', 'uim', 'WITH', 'uim.user = :owner_id')
208 3
            ->addSelect('uim')
209 3
            ->setParameter('owner_id', $profileOwnerId)
210 3
            ->andWhere('uim.id != 0')
211 3
            ->orderBy('uim.id', 'DESC');
212
213 3
        if ($currentUser !== null) {
214 3
            $result->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :current_user_id')
215 3
                ->addSelect('uwm')
216 3
                ->setParameter('current_user_id', $currentUser->getId());
217
        }
218
219 3
        return $result->getQuery();
220
    }
221
222 2
    public function findAllByActor(int $actorId, ?User $currentUser = null): array
223
    {
224 2
        $items = $this->getBaseQuery()
225 2
            ->leftJoin('m.actors', 'ma', 'WITH', 'ma.actor = :actor AND ma.movie = m')
226 2
            ->setParameter('actor', $actorId)
227 2
            ->orderBy('m.releaseDate', 'DESC');
228
229 2
        if ($currentUser !== null) {
230 1
            $items->leftJoin('m.userWatchedMovie', 'uwm', 'WITH', 'uwm.user = :user_id')
231 1
                ->addSelect('uwm')
232 1
                ->setParameter('user_id', $currentUser->getId());
233
        }
234
235 2
        $items->where('m.id IN (:ids)');
236
237 2
        $ids = $this->createQueryBuilder('m')
238 2
            ->select('m.id')
239 2
            ->leftJoin('m.actors', 'ma', 'WITH', 'ma.actor = :actor AND ma.movie = m')
240 2
            ->setParameter('actor', $actorId)
241 2
            ->andWhere('ma.id != 0')
242 2
            ->orderBy('m.releaseDate', 'DESC');
243
244 2
        $count = $this->createQueryBuilder('m')
245 2
            ->select('COUNT(m.id)')
246 2
            ->leftJoin('m.actors', 'ma', 'WITH', 'ma.actor = :actor AND ma.movie = m')
247 2
            ->setParameter('actor', $actorId)
248 2
            ->andWhere('ma.id != 0');
249
250 2
        return [$items->getQuery(), $ids->getQuery(), $count->getQuery()];
251
    }
252
253
    public function findAllQuery()
254
    {
255
        $result = $this->getBaseQuery()
256
            ->orderBy('m.id', 'DESC')
257
            ->getQuery();
258
259
        return $result;
260
    }
261
262 2
    public function findByTitleQuery(string $query)
263
    {
264 2
        $query = mb_strtolower($query);
265 2
        $result = $this->getBaseQuery()
266 2
            ->andWhere('LOWER(m.originalTitle) LIKE :title OR LOWER(mt.title) LIKE :title')
267 2
            ->setParameter('title', "%{$query}%")
268 2
            ->getQuery();
269
270 2
        return $result;
271
    }
272
273
    public function findByTitleWithUserRecommendedMovieQuery(string $query, int $userId, int $originalMovieId)
274
    {
275
        $query = mb_strtolower($query);
276
        $result = $this->getBaseQuery()
277
            ->andWhere('LOWER(m.originalTitle) LIKE :title OR LOWER(mt.title) LIKE :title')
278
            ->setParameter('title', "%{$query}%")
279
            ->leftJoin('m.userRecommendedMovie', 'urm', 'WITH', 'urm.user = :user_id AND urm.originalMovie = :movie_id')
280
            ->addSelect('urm')
281
            ->setParameter('user_id', $userId)
282
            ->setParameter('movie_id', $originalMovieId)
283
            ->getQuery();
284
285
        return $result;
286
    }
287
288 9
    public function findOneByIdOrTmdbId(?int $id = null, ?int $tmdb_id = null)
289
    {
290 9
        if ($id === null && $tmdb_id === null) {
291
            throw new \InvalidArgumentException('Movie ID or TMDB ID should be provided');
292
        }
293
294 9
        return $id ? $this->find($id) : $this->findOneBy(['tmdb.id' => $tmdb_id]);
295
    }
296
297
    /**
298
     * @param string $locale
299
     * @return Query
300
     */
301
    public function findAllWithEmptyTranslation(string $locale): Query
302
    {
303
        return $this->createQueryBuilder('m')
304
            ->leftJoin('m.translations', 'mt', 'WITH', 'm = mt.movie AND mt.locale = :locale')
305
            ->addSelect('mt')
306
            ->setParameter('locale', $locale)
307
            ->where('mt IS NULL')
308
            ->getQuery();
309
    }
310
}
311