Passed
Push — main ( 1d1c5b...83bc52 )
by Daniel
04:23
created

CatalogUpdater::update()   C

Complexity

Conditions 10
Paths 14

Size

Total Lines 107
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
eloc 65
c 0
b 0
f 0
dl 0
loc 107
ccs 0
cts 55
cp 0
rs 6.8969
cc 10
nc 14
nop 2
crap 110

How to fix   Long Method    Complexity   

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 Uxmp\Core\Component\Catalog\Manage;
6
7
use Ahc\Cli\IO\Interactor;
8
use getID3;
9
use Uxmp\Core\Component\Catalog\Manage\Update\RecursiveFileReaderInterface;
10
use Uxmp\Core\Component\Catalog\Scanner\DiscCacheInterface;
11
use Uxmp\Core\Component\Tag\Container\AudioFile;
12
use Uxmp\Core\Component\Tag\Extractor\ExtractorDeterminatorInterface;
13
use Uxmp\Core\Orm\Repository\CatalogRepositoryInterface;
14
use Uxmp\Core\Orm\Repository\SongRepositoryInterface;
15
16
final class CatalogUpdater implements CatalogUpdaterInterface
17
{
18
    private const SUPPORTED_FORMATS = [
19
        'mp3',
20
        'flac',
21
        'ogg',
22
        'wav',
23
    ];
24
25
    public function __construct(
26
        private readonly CatalogRepositoryInterface $catalogRepository,
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_STRING, expecting T_VARIABLE on line 26 at column 25
Loading history...
27
        private readonly getID3 $id3Analyzer,
28
        private readonly SongRepositoryInterface $songRepository,
29
        private readonly ExtractorDeterminatorInterface $extractorDeterminator,
30
        private readonly DiscCacheInterface $discCache,
31
        private readonly RecursiveFileReaderInterface $recursiveFileReader,
32
    ) {
33
    }
34
35
    public function update(Interactor $io, int $catalogId): void
36
    {
37
        $catalog = $this->catalogRepository->find($catalogId);
38
        if ($catalog === null) {
39
            $io->error(
40
                sprintf('Catalog `%d` not found', $catalogId),
41
                true
42
            );
43
            return;
44
        }
45
46
        $directory = $catalog->getPath();
47
48
        if (!is_dir($directory)) {
49
            $io->error(
50
                sprintf('The path `%s` is not accessible', $directory),
51
                true
52
            );
53
            return;
54
        }
55
56
        $skipped = [];
57
58
        $io->info(sprintf('Updating catalog from `%s`', $directory), true);
59
60
        foreach ($this->recursiveFileReader->read($directory) as $filename) {
61
            $audioFile = (new AudioFile())->setFilename($filename);
62
63
            $analysisResult = $this->id3Analyzer->analyze($filename);
64
65
            $fileFormat = $analysisResult['fileformat'] ?? '';
66
67
            if (!in_array($fileFormat, self::SUPPORTED_FORMATS, true)) {
68
                $skipped[] = sprintf(
69
                    'Skipped `%s`: Unknown fileformat `%s`',
70
                    $filename,
71
                    $fileFormat
72
                );
73
74
                $io->error('.');
75
                continue;
76
            }
77
78
            $extractor = $this->extractorDeterminator->determine($analysisResult['tags']);
79
            if ($extractor === null) {
80
                $skipped[] = sprintf(
81
                    'Skipped `%s`: Meta-Tag extraction failed',
82
                    $filename,
83
                );
84
85
                $io->error('.');
86
                continue;
87
            }
88
89
            $audioFile->setMimeType((string) ($analysisResult['mime_type'] ?? ''));
90
91
            $extractor->extract(
92
                $analysisResult['tags'],
93
                $audioFile
94
            );
95
96
            if ($audioFile->isValid() === false) {
97
                $skipped[] = sprintf(
98
                    'Skipped `%s`: Invalid Meta-Tags',
99
                    $filename,
100
                );
101
102
                $io->error('.');
103
                continue;
104
            }
105
106
            $io->info('.');
107
108
            $song = $this->songRepository->findByMbId($audioFile->getMbid());
109
            if ($song === null) {
110
                $song = $this->songRepository->prototype();
111
            }
112
113
            $disc = $this->discCache->retrieve($catalog, $audioFile, $analysisResult);
114
115
            $song
116
                ->setTitle($audioFile->getTitle())
117
                ->setTrackNumber($audioFile->getTrackNumber())
118
                ->setDisc($disc)
119
                ->setArtist($disc->getAlbum()->getArtist())
120
                ->setFilename($audioFile->getFilename())
121
                ->setMbid($audioFile->getMbid())
122
                ->setCatalog($catalog)
123
                ->setLength((int) round($analysisResult['playtime_seconds']))
124
                ->setYear($audioFile->getYear())
125
                ->setMimeType($audioFile->getMimeType())
126
            ;
127
128
            $this->songRepository->save($song);
129
130
            $disc->addSong($song);
131
        }
132
133
        if ($skipped !== []) {
134
            $io->error('The following errors occurred', true);
135
136
            foreach ($skipped as $error) {
137
                $io->error($error, true);
138
            }
139
        }
140
141
        $io->eol();
142
    }
143
}
144