| Total Complexity | 44 |
| Total Lines | 309 |
| Duplicated Lines | 0 % |
| Changes | 6 | ||
| Bugs | 0 | Features | 0 |
Complex classes like Track often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Track, and based on these observations, apply Extract Interface, too.
| 1 | <?php declare(strict_types=1); |
||
| 66 | class Track extends Entity { |
||
| 67 | public string $title = ''; |
||
| 68 | public ?int $number = null; |
||
| 69 | public ?int $disk = null; |
||
| 70 | public ?int $year = null; |
||
| 71 | public ?int $artistId = null; |
||
| 72 | public ?int $albumId = null; |
||
| 73 | public ?int $length = null; |
||
| 74 | public int $fileId = 0; |
||
| 75 | public ?int $bitrate = null; |
||
| 76 | public string $mimetype = ''; |
||
| 77 | public ?string $mbid = null; |
||
| 78 | public ?string $starred = null; |
||
| 79 | public int $rating = 0; |
||
| 80 | public ?int $genreId = null; |
||
| 81 | public int $playCount = 0; |
||
| 82 | public ?string $lastPlayed = null; |
||
| 83 | public int $dirty = 0; |
||
| 84 | |||
| 85 | // not from the music_tracks table but still part of the standard content of this entity: |
||
| 86 | public string $filename = ''; |
||
| 87 | public int $size = 0; |
||
| 88 | public int $fileModTime = 0; |
||
| 89 | public ?string $albumName = null; |
||
| 90 | public ?string $artistName = null; |
||
| 91 | public ?string $genreName = null; |
||
| 92 | public int $folderId = 0; |
||
| 93 | |||
| 94 | // the rest of the variables are injected separately when needed |
||
| 95 | private ?Album $album = null; |
||
| 96 | private ?int $numberOnPlaylist = null; |
||
| 97 | private ?string $folderPath = null; |
||
| 98 | private ?string $lyrics = null; |
||
| 99 | |||
| 100 | public function __construct() { |
||
| 101 | $this->addType('number', 'int'); |
||
| 102 | $this->addType('disk', 'int'); |
||
| 103 | $this->addType('year', 'int'); |
||
| 104 | $this->addType('artistId', 'int'); |
||
| 105 | $this->addType('albumId', 'int'); |
||
| 106 | $this->addType('length', 'int'); |
||
| 107 | $this->addType('bitrate', 'int'); |
||
| 108 | $this->addType('fileId', 'int'); |
||
| 109 | $this->addType('genreId', 'int'); |
||
| 110 | $this->addType('playCount', 'int'); |
||
| 111 | $this->addType('rating', 'int'); |
||
| 112 | $this->addType('dirty', 'int'); |
||
| 113 | $this->addType('size', 'int'); |
||
| 114 | $this->addType('fileModTime', 'int'); |
||
| 115 | $this->addType('folderId', 'int'); |
||
| 116 | } |
||
| 117 | |||
| 118 | public function getAlbum() : ?Album { |
||
| 119 | return $this->album; |
||
| 120 | } |
||
| 121 | |||
| 122 | public function setAlbum(?Album $album) : void { |
||
| 123 | $this->album = $album; |
||
| 124 | } |
||
| 125 | |||
| 126 | public function getNumberOnPlaylist() : ?int { |
||
| 127 | return $this->numberOnPlaylist; |
||
| 128 | } |
||
| 129 | |||
| 130 | public function setNumberOnPlaylist(int $number) : void { |
||
| 131 | $this->numberOnPlaylist = $number; |
||
| 132 | } |
||
| 133 | |||
| 134 | public function setFolderPath(string $path) : void { |
||
| 135 | $this->folderPath = $path; |
||
| 136 | } |
||
| 137 | |||
| 138 | public function setLyrics(?string $lyrics) : void { |
||
| 139 | $this->lyrics = $lyrics; |
||
| 140 | } |
||
| 141 | |||
| 142 | public function getPath() : ?string { |
||
| 143 | return ($this->folderPath ?? '') . '/' . $this->filename; |
||
| 144 | } |
||
| 145 | |||
| 146 | public function getUri(IURLGenerator $urlGenerator) : string { |
||
| 147 | return $urlGenerator->linkToRoute( |
||
| 148 | 'music.shivaApi.track', |
||
| 149 | ['id' => $this->id] |
||
| 150 | ); |
||
| 151 | } |
||
| 152 | |||
| 153 | public function getArtistWithUri(IURLGenerator $urlGenerator) : array { |
||
| 154 | return [ |
||
| 155 | 'id' => $this->artistId, |
||
| 156 | 'uri' => $urlGenerator->linkToRoute( |
||
| 157 | 'music.shivaApi.artist', |
||
| 158 | ['id' => $this->artistId] |
||
| 159 | ) |
||
| 160 | ]; |
||
| 161 | } |
||
| 162 | |||
| 163 | public function getAlbumWithUri(IURLGenerator $urlGenerator) : array { |
||
| 169 | ) |
||
| 170 | ]; |
||
| 171 | } |
||
| 172 | |||
| 173 | public function getArtistNameString(IL10N $l10n) : string { |
||
| 174 | return $this->getArtistName() ?: Artist::unknownNameString($l10n); |
||
| 175 | } |
||
| 176 | |||
| 177 | public function getAlbumNameString(IL10N $l10n) : string { |
||
| 178 | return $this->getAlbumName() ?: Album::unknownNameString($l10n); |
||
| 179 | } |
||
| 180 | |||
| 181 | public function getGenreNameString(IL10N $l10n) : string { |
||
| 182 | return $this->getGenreName() ?: Genre::unknownNameString($l10n); |
||
| 183 | } |
||
| 184 | |||
| 185 | public function toCollection() : array { |
||
| 186 | return [ |
||
| 187 | 'title' => $this->getTitle(), |
||
| 188 | 'number' => $this->getNumber(), |
||
| 189 | 'disk' => $this->getDisk(), |
||
| 190 | 'artistId' => $this->getArtistId(), |
||
| 191 | 'length' => $this->getLength(), |
||
| 192 | 'files' => [$this->getMimetype() => $this->getFileId()], |
||
| 193 | 'id' => $this->getId(), |
||
| 194 | ]; |
||
| 195 | } |
||
| 196 | |||
| 197 | public function toShivaApi(IURLGenerator $urlGenerator) : array { |
||
| 198 | return [ |
||
| 199 | 'title' => $this->getTitle(), |
||
| 200 | 'ordinal' => $this->getAdjustedTrackNumber(), |
||
| 201 | 'artist' => $this->getArtistWithUri($urlGenerator), |
||
| 202 | 'album' => $this->getAlbumWithUri($urlGenerator), |
||
| 203 | 'length' => $this->getLength(), |
||
| 204 | 'files' => [$this->getMimetype() => $urlGenerator->linkToRoute( |
||
| 205 | 'music.musicApi.download', |
||
| 206 | ['fileId' => $this->getFileId()] |
||
| 207 | )], |
||
| 208 | 'bitrate' => $this->getBitrate(), |
||
| 209 | 'id' => $this->getId(), |
||
| 210 | 'slug' => $this->slugify('title'), |
||
|
|
|||
| 211 | 'uri' => $this->getUri($urlGenerator) |
||
| 212 | ]; |
||
| 213 | } |
||
| 214 | |||
| 215 | public function toAmpacheApi( |
||
| 216 | IL10N $l10n, |
||
| 217 | callable $createPlayUrl, |
||
| 218 | callable $createImageUrl, |
||
| 219 | callable $renderAlbumOrArtistRef, |
||
| 220 | string $genreKey, |
||
| 221 | bool $includeArtists) : array { |
||
| 222 | $album = $this->getAlbum(); |
||
| 223 | |||
| 224 | $result = [ |
||
| 225 | 'id' => (string)$this->getId(), |
||
| 226 | 'title' => $this->getTitle() ?: '', |
||
| 227 | 'name' => $this->getTitle() ?: '', |
||
| 228 | 'artist' => $renderAlbumOrArtistRef($this->getArtistId() ?: 0, $this->getArtistNameString($l10n)), |
||
| 229 | 'albumartist' => $renderAlbumOrArtistRef($album->getAlbumArtistId() ?: 0, $album->getAlbumArtistNameString($l10n)), |
||
| 230 | 'album' => $renderAlbumOrArtistRef($album->getId() ?: 0, $album->getNameString($l10n)), |
||
| 231 | 'url' => $createPlayUrl($this), |
||
| 232 | 'time' => $this->getLength(), |
||
| 233 | 'year' => $this->getYear(), |
||
| 234 | 'track' => $this->getAdjustedTrackNumber(), // TODO: maybe there should be a user setting to select plain or adjusted number |
||
| 235 | 'playlisttrack' => $this->getAdjustedTrackNumber(), |
||
| 236 | 'disk' => $this->getDisk(), |
||
| 237 | 'filename' => $this->getFilename(), |
||
| 238 | 'format' => $this->getFileExtension(), |
||
| 239 | 'stream_format' => $this->getFileExtension(), |
||
| 240 | 'bitrate' => $this->getBitrate(), |
||
| 241 | 'stream_bitrate' => $this->getBitrate(), |
||
| 242 | 'mime' => $this->getMimetype(), |
||
| 243 | 'stream_mime' => $this->getMimetype(), |
||
| 244 | 'size' => $this->getSize(), |
||
| 245 | 'art' => $createImageUrl($this), |
||
| 246 | 'rating' => $this->getRating(), |
||
| 247 | 'preciserating' => $this->getRating(), |
||
| 248 | 'playcount' => $this->getPlayCount(), |
||
| 249 | 'flag' => !empty($this->getStarred()), |
||
| 250 | 'language' => null, |
||
| 251 | 'lyrics' => $this->lyrics, |
||
| 252 | 'mode' => null, // cbr/vbr |
||
| 253 | 'rate' => null, // sample rate [Hz] |
||
| 254 | 'replaygain_album_gain' => null, |
||
| 255 | 'replaygain_album_peak' => null, |
||
| 256 | 'replaygain_track_gain' => null, |
||
| 257 | 'replaygain_track_peak' => null, |
||
| 258 | 'r128_album_gain' => null, |
||
| 259 | 'r128_track_gain' => null, |
||
| 260 | ]; |
||
| 261 | |||
| 262 | $result['has_art'] = !empty($result['art']); |
||
| 263 | |||
| 264 | $genreId = $this->getGenreId(); |
||
| 265 | if ($genreId !== null) { |
||
| 266 | $result[$genreKey] = [[ |
||
| 267 | 'id' => (string)$genreId, |
||
| 268 | 'text' => $this->getGenreNameString($l10n), |
||
| 269 | 'count' => 1 |
||
| 270 | ]]; |
||
| 271 | } |
||
| 272 | |||
| 273 | if ($includeArtists) { |
||
| 274 | // Add another property `artists`. Apparently, it exists to support multiple artists per song |
||
| 275 | // but we don't have such possibility and this is always just a 1-item array. |
||
| 276 | $result['artists'] = [$result['artist']]; |
||
| 277 | } |
||
| 278 | |||
| 279 | return $result; |
||
| 280 | } |
||
| 281 | |||
| 282 | /** |
||
| 283 | * The same API format is used both on "old" and "new" API methods. The "new" API adds some |
||
| 284 | * new fields for the songs, but providing some extra fields shouldn't be a problem for the |
||
| 285 | * older clients. The $track entity must have the Album reference injected prior to calling this. |
||
| 286 | * |
||
| 287 | * @param string[] $ignoredArticles |
||
| 288 | */ |
||
| 289 | public function toSubsonicApi(IL10N $l10n, array $ignoredArticles) : array { |
||
| 290 | $albumId = $this->getAlbumId(); |
||
| 291 | $album = $this->getAlbum(); |
||
| 292 | $hasCoverArt = ($album !== null && !empty($album->getCoverFileId())); |
||
| 293 | |||
| 294 | return [ |
||
| 295 | 'id' => 'track-' . $this->getId(), |
||
| 296 | 'parent' => 'album-' . $albumId, |
||
| 297 | 'discNumber' => $this->getDisk(), |
||
| 298 | 'title' => $this->getTitle(), |
||
| 299 | 'artist' => $this->getArtistNameString($l10n), |
||
| 300 | 'isDir' => false, |
||
| 301 | 'album' => $this->getAlbumNameString($l10n), |
||
| 302 | 'year' => $this->getYear(), |
||
| 303 | 'size' => $this->getSize(), |
||
| 304 | 'contentType' => $this->getMimetype(), |
||
| 305 | 'suffix' => $this->getFileExtension(), |
||
| 306 | 'duration' => $this->getLength() ?? 0, |
||
| 307 | 'bitRate' => empty($this->getBitrate()) ? null : (int)\round($this->getBitrate()/1000), // convert bps to kbps |
||
| 308 | 'path' => $this->getPath(), |
||
| 309 | 'isVideo' => false, |
||
| 310 | 'albumId' => 'album-' . $albumId, |
||
| 311 | 'artistId' => 'artist-' . $this->getArtistId(), |
||
| 312 | 'type' => 'music', |
||
| 313 | 'mediaType' => 'song', // OpenSubsonic |
||
| 314 | 'created' => Util::formatZuluDateTime($this->getCreated()), |
||
| 315 | 'track' => $this->getAdjustedTrackNumber(false), // DSub would get confused of playlist numbering, https://github.com/owncloud/music/issues/994 |
||
| 316 | 'starred' => Util::formatZuluDateTime($this->getStarred()), |
||
| 317 | 'userRating' => $this->getRating() ?: null, |
||
| 318 | 'averageRating' => $this->getRating() ?: null, |
||
| 319 | 'genre' => empty($this->getGenreId()) ? null : $this->getGenreNameString($l10n), |
||
| 320 | 'coverArt' => !$hasCoverArt ? null : 'album-' . $albumId, |
||
| 321 | 'playCount' => $this->getPlayCount(), |
||
| 322 | 'played' => Util::formatZuluDateTime($this->getLastPlayed()) ?? '', // OpenSubsonic |
||
| 323 | 'sortName' => StringUtil::splitPrefixAndBasename($this->getTitle(), $ignoredArticles)['basename'], // OpenSubsonic |
||
| 324 | ]; |
||
| 325 | } |
||
| 326 | |||
| 327 | public function getAdjustedTrackNumber(bool $enablePlaylistNumbering=true) : ?int { |
||
| 347 | } |
||
| 348 | |||
| 349 | public function getFileExtension() : string { |
||
| 352 | } |
||
| 353 | |||
| 354 | /** |
||
| 355 | * Get an instance which has all the mandatory fields set to valid but empty values |
||
| 356 | */ |
||
| 357 | public static function emptyInstance() : Track { |
||
| 358 | $track = new self(); |
||
| 359 | |||
| 360 | $track->id = -1; |
||
| 361 | $track->title = ''; |
||
| 362 | $track->artistId = -1; |
||
| 363 | $track->albumId = -1; |
||
| 364 | $track->fileId = -1; |
||
| 365 | $track->mimetype = ''; |
||
| 366 | $track->playCount = 0; |
||
| 367 | $track->dirty = 0; |
||
| 377 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.