Test Failed
Push — main ( 3531fe...1eb5c2 )
by Daniel
04:35
created

AlbumRepository::findByMbId()   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\Common\Collections\Criteria;
8
use Doctrine\ORM\EntityRepository;
9
use Doctrine\ORM\Query\Expr\Join;
10
use Generator;
11
use Uxmp\Core\Orm\Model\Album;
12
use Uxmp\Core\Orm\Model\AlbumInterface;
13
use Uxmp\Core\Orm\Model\Artist;
14
use Uxmp\Core\Orm\Model\CatalogInterface;
15
use Uxmp\Core\Orm\Model\Disc;
16
use Uxmp\Core\Orm\Model\Favorite;
17
use Uxmp\Core\Orm\Model\FavoriteItemTypeEnum;
18
use Uxmp\Core\Orm\Model\GenreInterface;
19
use Uxmp\Core\Orm\Model\GenreMap;
20
use Uxmp\Core\Orm\Model\GenreMapEnum;
21
use Uxmp\Core\Orm\Model\UserInterface;
22
23
/**
24
 * @extends EntityRepository<Album>
25
 *
26
 * @method AlbumInterface[] findBy(mixed[] $criteria, null|array $order = null, null|int $limit = null, null|int $offset = null)
27
 * @method null|AlbumInterface find(int $id)
28
 */
29
final class AlbumRepository extends EntityRepository implements AlbumRepositoryInterface
30
{
31 1
    public function prototype(): AlbumInterface
32
    {
33 1
        return new Album();
34
    }
35
36 1
    public function save(AlbumInterface $album): void
37
    {
38 1
        $em = $this->getEntityManager();
39
40 1
        $em->persist($album);
41 1
        $em->flush();
42
    }
43
44 1
    public function findByMbId(string $mbid): ?AlbumInterface
45
    {
46 1
        return $this->findOneBy([
47 1
            'mbid' => $mbid,
48 1
        ]);
49
    }
50
51
    /**
52
     * Returns albums having a certain genre
53
     *
54
     * @return Generator<AlbumInterface>
55
     */
56 1
    public function findByGenre(
57
        GenreInterface $genre,
58
        ?int $limit = null,
59
        ?int $offset = null,
60
        ?int $catalogId = null,
61
    ): Generator {
62 1
        $queryBuilder = $this->createQueryBuilder('a');
63 1
        $subQueryBuilder = $this
64 1
            ->getEntityManager()
65 1
            ->createQueryBuilder();
66 1
        $expressionBuilder = $this
67 1
            ->getEntityManager()
68 1
            ->getExpressionBuilder();
69
70 1
        $andExpression = $expressionBuilder->andX();
71 1
        $andExpression->add($expressionBuilder->eq('genre_map.genre', ':genre'));
72 1
        $andExpression->add($expressionBuilder->eq('genre_map.mapped_item_type', ':genreType'));
73
74 1
        $queryBuilder
75 1
            ->where(
76 1
                $expressionBuilder->in(
77 1
                    'a.id',
78 1
                    $subQueryBuilder
79 1
                        ->select('genre_map.mapped_item_id')
80 1
                        ->from(GenreMap::class, 'genre_map')
81 1
                        ->where($andExpression)
82 1
                        ->getDQL()
83 1
                )
84 1
            )
85 1
            ->setFirstResult($offset)
86 1
            ->setMaxResults($limit)
87 1
            ->orderBy('a.title', 'ASC')
88 1
            ->setParameter('genre', $genre)
89 1
            ->setParameter('genreType', GenreMapEnum::ALBUM)
90 1
        ;
91
92 1
        if ($catalogId !== null) {
93 1
            $queryBuilder->andWhere('catalog_id = :catalogId');
94 1
            $queryBuilder->setParameter('catalogId', $catalogId);
95
        }
96
97 1
        foreach ($queryBuilder->getQuery()->toIterable() as $item) {
98 1
            yield $item;
99
        }
100
    }
101
102 1
    public function delete(AlbumInterface $album): void
103
    {
104 1
        $em = $this->getEntityManager();
105
106 1
        $em->remove($album);
107 1
        $em->flush();
108
    }
109
110
    /**
111
     * @return iterable<AlbumInterface>
112
     */
113 1
    public function getFavorites(
114
        UserInterface $user,
115
        ?CatalogInterface $catalog = null,
116
        ?int $limit = null,
117
        ?int $offset = null
118
    ): iterable {
119 1
        $parameter = [
120 1
            'user' => $user,
121 1
            'type' => FavoriteItemTypeEnum::ALBUM,
122 1
        ];
123
124 1
        $qb = $this
125 1
            ->getEntityManager()
126 1
            ->createQueryBuilder();
127 1
        $qbSub = $this
128 1
            ->getEntityManager()
129 1
            ->createQueryBuilder();
130 1
        $expressionBuilder = $this
131 1
            ->getEntityManager()
132 1
            ->getExpressionBuilder();
133
134 1
        $andExpression = $expressionBuilder->andX();
135 1
        $andExpression->add($expressionBuilder->eq('fav.user', ':user'));
136 1
        $andExpression->add($expressionBuilder->eq('fav.type', ':type'));
137 1
        if ($catalog !== null) {
138 1
            $andExpression->add($expressionBuilder->eq('a.catalog', ':catalog'));
139
140 1
            $parameter['catalog'] = $catalog;
141
        }
142
143 1
        $qb
144 1
            ->select('a')
145 1
            ->from(Album::class, 'a')
146 1
            ->where(
147 1
                $expressionBuilder->in(
148 1
                    'a.id',
149 1
                    $qbSub
150 1
                        ->select('fav.item_id')
151 1
                        ->from(Favorite::class, 'fav')
152 1
                        ->where($andExpression)
153 1
                        ->getDQL()
154 1
                )
155 1
            )
156 1
            ->setParameters($parameter)
157 1
            ->orderBy('a.title', 'ASC')
158 1
            ->setMaxResults($limit)
159 1
            ->setFirstResult($offset);
160
161 1
        return $qb->getQuery()->getResult();
162
    }
163
164 1
    public function findEmptyAlbums(CatalogInterface $catalog): iterable
165
    {
166 1
        $query = <<<SQL
167
            SELECT album
168
            FROM %s album
169
            LEFT JOIN %s disc 
170
            WITH disc.album_id = album.id
171
            WHERE album.catalog_id = %d
172
            GROUP BY album HAVING COUNT(disc.id) = 0
173 1
            SQL;
174
175 1
        return $this->getEntityManager()
176 1
            ->createQuery(sprintf(
177 1
                $query,
178 1
                Album::class,
179 1
                Disc::class,
180 1
                $catalog->getId(),
181 1
            ))
182 1
            ->getResult();
183
    }
184
185
    /**
186
     * Returns an ordered list by the albums artist
187
     *
188
     * @return Generator<AlbumInterface>
189
     */
190 1
    public function getListOrderedByArtist(
191
        null|int $limit = null,
192
        null|int $offset = null,
193
        ?int $catalogId = null,
194
    ): Generator {
195 1
        $query_builder = $this
196 1
            ->createQueryBuilder('ab')
197 1
            ->leftJoin(
198 1
                Artist::class,
199 1
                'ac',
200 1
                Join::WITH,
201 1
                'ac.id = ab.artist_id'
202 1
            )
203 1
            ->setFirstResult($offset)
204 1
            ->setMaxResults($limit)
205 1
            ->addOrderBy('ac.title', Criteria::ASC)
206 1
            ->addOrderBy('ab.title', Criteria::ASC)
207 1
        ;
208
209 1
        if ($catalogId !== null) {
210 1
            $query_builder->where('ab.catalog_id = :catalogId');
211 1
            $query_builder->setParameter('catalogId', $catalogId);
212
        }
213
214 1
        foreach ($query_builder->getQuery()->toIterable() as $album) {
215 1
            yield $album;
216
        }
217
    }
218
219
    public function search(string $searchTerm): array
220
    {
221
        $qb = $this->getEntityManager()->createQueryBuilder();
222
223
        $qb
224
            ->select('a')
225
            ->from(Album::class, 'a')
226
            ->where(
227
                $qb->expr()->like('a.title', ':searchTerm')
228
            )
229
            ->setParameter('searchTerm', sprintf('%%%s%%', $searchTerm))
230
        ;
231
232
        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...
233
    }
234
}
235