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

MovieRepository   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 264
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 44.74%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 5
dl 0
loc 264
ccs 68
cts 152
cp 0.4474
rs 10
c 0
b 0
f 0

17 Methods

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