Passed
Push — main ( 79b143...ab85f9 )
by Daniel
03:36
created

SongRepository::delete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Uxmp\Core\Orm\Repository;
6
7
use Doctrine\ORM\EntityRepository;
8
use JetBrains\PhpStorm\Pure;
9
use Traversable;
10
use Uxmp\Core\Orm\Model\ArtistInterface;
11
use Uxmp\Core\Orm\Model\CatalogInterface;
12
use Uxmp\Core\Orm\Model\Disc;
13
use Uxmp\Core\Orm\Model\Favorite;
14
use Uxmp\Core\Orm\Model\FavoriteItemTypeEnum;
15
use Uxmp\Core\Orm\Model\GenreInterface;
16
use Uxmp\Core\Orm\Model\GenreMap;
17
use Uxmp\Core\Orm\Model\GenreMapEnum;
18
use Uxmp\Core\Orm\Model\PlaybackHistory;
19
use Uxmp\Core\Orm\Model\Song;
20
use Uxmp\Core\Orm\Model\SongInterface;
21
use Uxmp\Core\Orm\Model\UserInterface;
22
23
/**
24
 * @extends EntityRepository<Song>
25
 *
26
 * @method null|SongInterface find(mixed $id)
27
 * @method SongInterface[] findBy(mixed[] $criteria, null|array $order = null, null|int $limit = null, null|int $offset = null)
28
 */
29
final class SongRepository extends EntityRepository implements SongRepositoryInterface
30
{
31 1
    #[Pure]
32
    public function prototype(): SongInterface
33
    {
34 1
        return new Song();
35
    }
36
37 1
    public function save(SongInterface $song): void
38
    {
39 1
        $this->getEntityManager()->persist($song);
40 1
        $this->getEntityManager()->flush();
41
    }
42
43 1
    public function delete(SongInterface $song): void
44
    {
45 1
        $this->getEntityManager()->remove($song);
46 1
        $this->getEntityManager()->flush();
47
    }
48
49 1
    public function findByMbId(string $mbid): ?SongInterface
50
    {
51 1
        return $this->findOneBy([
52 1
            'mbid' => $mbid,
53 1
        ]);
54
    }
55
56
    /**
57
     * Retrieve a complete list of favorite songs for a user
58
     *
59
     * @return iterable<SongInterface>
60
     */
61 1
    public function findFavorites(
62
        UserInterface $user,
63
        ?CatalogInterface $catalog = null
64
    ): iterable {
65 1
        $parameter = [
66 1
            'user' => $user,
67 1
            'type' => FavoriteItemTypeEnum::SONG,
68 1
        ];
69
70 1
        $qb = $this->createQueryBuilder('a');
71 1
        $qbSub = $this
72 1
            ->getEntityManager()
73 1
            ->createQueryBuilder();
74 1
        $expressionBuilder = $this->getEntityManager()->getExpressionBuilder();
75
76 1
        $andExpression = $expressionBuilder->andX();
77 1
        $andExpression->add($expressionBuilder->eq('fav.user', ':user'));
78 1
        $andExpression->add($expressionBuilder->eq('fav.type', ':type'));
79 1
        if ($catalog !== null) {
80 1
            $andExpression->add($expressionBuilder->eq('a.catalog', ':catalog'));
81
82 1
            $parameter['catalog'] = $catalog;
83
        }
84
85 1
        $qb
86 1
            ->where(
87 1
                $expressionBuilder->in(
88 1
                    'a.id',
89 1
                    $qbSub
90 1
                        ->select('fav.item_id')
91 1
                        ->from(Favorite::class, 'fav')
92 1
                        ->where($andExpression)
93 1
                        ->getDQL()
94 1
                )
95 1
            )
96 1
            ->setParameters($parameter)
97 1
        ;
98
99 1
        return $qb->getQuery()->getResult();
100
    }
101
102
    /**
103
     * Returns most played songs of a certain artis
104
     *
105
     * @return iterable<SongInterface>
106
     */
107 1
    public function getTopSongsByArtist(
108
        ArtistInterface $artist
109
    ): iterable {
110 1
        $query = <<<SQL
111
            SELECT song
112
            FROM %s song
113
            LEFT JOIN %s pbh
114
            WITH pbh.song_id = song.id
115
            WHERE song.artist = :artist
116
            GROUP BY song HAVING(COUNT(pbh.id)) > 0
117
            ORDER BY COUNT(pbh.id) DESC
118 1
            SQL;
119
120 1
        return $this->getEntityManager()
121 1
            ->createQuery(
122 1
                sprintf(
123 1
                    $query,
124 1
                    Song::class,
125 1
                    PlaybackHistory::class,
126 1
                )
127 1
            )
128 1
            ->setParameters(['artist' => $artist])
129 1
            ->setMaxResults(10)
130 1
            ->toIterable();
131
    }
132
133 1
    public function search(string $searchTerm): array
134
    {
135 1
        $qb = $this->getEntityManager()->createQueryBuilder();
136
137 1
        $qb
138 1
            ->select('a')
139 1
            ->from(Song::class, 'a')
140 1
            ->where(
141 1
                $qb->expr()->like('lower(a.title)', ':searchTerm')
142 1
            )
143 1
            ->setParameter('searchTerm', sprintf('%%%s%%', mb_strtolower($searchTerm)))
144 1
        ;
145
146 1
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
147
    }
148
149 1
    public function getRandomBy(
150
        ?CatalogInterface $catalog = null,
151
        ?GenreInterface $genre = null,
152
        ?int $fromYear = null,
153
        ?int $toYear = null,
154
    ): Traversable {
155 1
        $qb = $this->getEntityManager()->createQueryBuilder();
156
157 1
        $qb
158 1
            ->select('a')
159 1
            ->from(Song::class, 'a')
160 1
        ;
161
162 1
        if ($fromYear !== null) {
163 1
            $qb->andWhere(
164 1
                $qb->expr()->gte('a.year', ':fromYear')
165 1
            );
166 1
            $qb->setParameter('fromYear', $fromYear);
167
        }
168
169 1
        if ($toYear !== null) {
170 1
            $qb->andWhere(
171 1
                $qb->expr()->lte('a.year', ':toYear')
172 1
            );
173 1
            $qb->setParameter('toYear', $fromYear);
174
        }
175
176 1
        if ($catalog !== null) {
177 1
            $qb->andWhere(
178 1
                $qb->expr()->eq('a.catalog', ':catalog')
179 1
            );
180 1
            $qb->setParameter('catalog', $catalog);
181
        }
182
183 1
        if ($genre !== null) {
184 1
            $discQueryBuilder = $this
185 1
                ->getEntityManager()
186 1
                ->createQueryBuilder();
187 1
            $genreQueryBuilder = $this
188 1
                ->getEntityManager()
189 1
                ->createQueryBuilder();
190
191 1
            $qb->andWhere(
192 1
                $qb->expr()->in(
193 1
                    'a.disc',
194 1
                    $discQueryBuilder
195 1
                        ->select('disc')
196 1
                        ->from(Disc::class, 'disc')
197 1
                        ->where(
198 1
                            $discQueryBuilder->expr()->in(
199 1
                                'disc.album',
200 1
                                $genreQueryBuilder
201 1
                                    ->select('genre_map.mapped_item_id')
202 1
                                    ->from(GenreMap::class, 'genre_map')
203 1
                                    ->where(
204 1
                                        $genreQueryBuilder->expr()->eq('genre_map.genre', ':genre')
205 1
                                    )
206 1
                                    ->andWhere(
207 1
                                        $genreQueryBuilder->expr()->eq('genre_map.mapped_item_type', ':genreType')
208 1
                                    )
209 1
                                    ->getDQL()
210 1
                            )
211 1
                        )
212 1
                        ->getDQL()
213 1
                )
214 1
            );
215
216 1
            $qb->setParameter('genre', $genre);
217 1
            $qb->setParameter('genreType', GenreMapEnum::ALBUM);
218
        }
219
220 1
        foreach ($qb->getQuery()->toIterable() as $song) {
221 1
            yield $song;
222
        }
223
    }
224
}
225