Passed
Push — main ( cff59a...745121 )
by Daniel
02:18
created

GetAlbumList2Method::__invoke()   B

Complexity

Conditions 8
Paths 16

Size

Total Lines 54
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 31
nc 16
nop 3
dl 0
loc 54
ccs 24
cts 24
cp 1
crap 8
rs 8.1795
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Usox\HyperSonic\FeatureSet\V1161\Method;
6
7
use DateTimeInterface;
8
use Generator;
9
use Traversable;
10
use Usox\HyperSonic\Exception\ErrorCodeEnum;
11
use Usox\HyperSonic\Exception\MethodCallFailedException;
12
use Usox\HyperSonic\FeatureSet\V1161\Contract\AlbumList2DataProviderInterface;
13
use Usox\HyperSonic\FeatureSet\V1161\Responder\ResponderFactoryInterface;
14
use Usox\HyperSonic\Response\ResponderInterface;
15
16
/**
17
 * Retrieve and transforms album data for the album list
18
 *
19
 * This class covers the `getAlbumList2.view` method
20
 *
21
 * @see http://www.subsonic.org/pages/api.jsp#getAlbumList2
22
 */
23
final class GetAlbumList2Method implements V1161MethodInterface
24
{
25
    // list of allowed types for ordering
26
    private const ORDER_TYPES = [
27
        'random',
28
        'newest',
29
        'frequent',
30
        'recent',
31
        'starred',
32
        'alphabeticalByName',
33
        'alphabeticalByArtist',
34
        'byYear',
35
        'byGenre',
36
    ];
37
38
    private const DEFAULT_LIMIT = 10;
39
    private const MAX_LIMIT = 500;
40
41 14
    public function __construct(
42
        private readonly ResponderFactoryInterface $responderFactory,
43
    ) {
44
    }
45
46
    /**
47
     * @param array<string, scalar> $queryParams
48
     * @param array<string, scalar> $args
49
     *
50
     * @throws MethodCallFailedException
51
     */
52 13
    public function __invoke(
53
        AlbumList2DataProviderInterface $albumList2DataProvider,
54
        array $queryParams,
55
        array $args,
56
    ): ResponderInterface {
57 13
        $type = $queryParams['type'] ?? '';
58 13
        $limit = min((int) ($queryParams['size'] ?? self::DEFAULT_LIMIT), self::MAX_LIMIT);
59 13
        $offset = (int) ($queryParams['offset'] ?? 0);
60 13
        $musicFolderId = $queryParams['musicFolderId'] ?? null;
61
62 13
        if ($musicFolderId !== null) {
63 7
            $musicFolderId = (string) $musicFolderId;
64
        }
65
66 13
        if (!in_array($type, self::ORDER_TYPES, true)) {
67 1
            throw new MethodCallFailedException(
68
                ErrorCodeEnum::MISSING_PARAMETER
69
            );
70
        }
71
72 12
        $orderParameter = [];
73
74 12
        if ($type === 'byYear') {
75 3
            $fromYear = $queryParams['fromYear'] ?? null;
76 3
            $toYear = $queryParams['toYear'] ?? null;
77
78 3
            if ($fromYear === null || $toYear === null) {
79 2
                throw new MethodCallFailedException(
80
                    ErrorCodeEnum::MISSING_PARAMETER
81
                );
82
            }
83 1
            $orderParameter = ['year' => ['from' => (int) $fromYear, 'to' => (int) $toYear]];
84
        }
85 10
        if ($type === 'byGenre') {
86 2
            $genre = $queryParams['genre'] ?? null;
87 2
            if ($genre === null) {
88 1
                throw new MethodCallFailedException(
89
                    ErrorCodeEnum::MISSING_PARAMETER
90
                );
91
            }
92
93 1
            $orderParameter = ['genre' => (string) $genre];
94
        }
95
96 9
        $albumList = $albumList2DataProvider->getAlbums(
97
            $type,
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type boolean; however, parameter $orderType of Usox\HyperSonic\FeatureS...rInterface::getAlbums() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

97
            /** @scrutinizer ignore-type */ $type,
Loading history...
98
            $limit,
99
            $offset,
100
            $orderParameter,
101
            $musicFolderId,
102
        );
103
104 9
        return $this->responderFactory->createAlbumList2Responder(
105 9
            $this->transformAlbums($albumList)
106
        );
107
    }
108
109
    /**
110
     * @param Traversable<array{
111
     *  id: string,
112
     *  name: string,
113
     *  coverArtId: string,
114
     *  songCount: int,
115
     *  createDate: DateTimeInterface,
116
     *  duration: int,
117
     *  artistName: string,
118
     *  artistId: string,
119
     * }> $albumList
120
     *
121
     * @return Generator<array{
122
     *  id: string,
123
     *  name: string,
124
     *  coverArt: string,
125
     *  songCount: int,
126
     *  created: string,
127
     *  duration: int,
128
     *  artist: string,
129
     *  artistId: string,
130
     * }>
131
     */
132 7
    private function transformAlbums(Traversable $albumList): Generator
133
    {
134 7
        foreach ($albumList as $album) {
135
            yield [
136 7
                'id' => $album['id'],
137 7
                'name' => $album['name'],
138 7
                'coverArt' => $album['coverArtId'],
139 7
                'songCount' => $album['songCount'],
140 7
                'created' => $album['createDate']->format(DATE_ATOM),
141 7
                'duration' => $album['duration'],
142 7
                'artist' => $album['artistName'],
143 7
                'artistId' => $album['artistId'],
144
            ];
145
        }
146
    }
147
}
148