wtf
CI - Build Tonehaus Docker image / tonehaus-ci-build (push) Successful in 2m0s

This commit is contained in:
boris committed 2025-11-28 02:00:11 +00:00
1 parent 1c98a634c3
commit dae8f3d999
35 files changed
+1510 -82

No files matched your search

+140
View File
@@ -0,0 +1,140 @@
<?php
namespace App\Entity;
use App\Repository\AlbumTrackRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* AlbumTrack persists individual tracks fetched from Spotify.
*/
#[ORM\Entity(repositoryClass: AlbumTrackRepository::class)]
#[ORM\Table(name: 'album_tracks')]
#[ORM\UniqueConstraint(name: 'uniq_album_disc_track', columns: ['album_id', 'disc_number', 'track_number'])]
class AlbumTrack
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
#[ORM\ManyToOne(targetEntity: Album::class, inversedBy: 'tracks')]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
private ?Album $album = null;
#[ORM\Column(type: 'string', length: 64, nullable: true)]
private ?string $spotifyTrackId = null;
#[ORM\Column(type: 'integer')]
private int $discNumber = 1;
#[ORM\Column(type: 'integer')]
private int $trackNumber = 1;
#[ORM\Column(type: 'string', length: 512)]
private string $name = '';
#[ORM\Column(type: 'integer')]
private int $durationMs = 0;
#[ORM\Column(type: 'string', length: 1024, nullable: true)]
private ?string $previewUrl = null;
public function getId(): ?int
{
return $this->id;
}
public function getAlbum(): ?Album
{
return $this->album;
}
public function setAlbum(?Album $album): void
{
$this->album = $album;
}
public function getSpotifyTrackId(): ?string
{
return $this->spotifyTrackId;
}
public function setSpotifyTrackId(?string $spotifyTrackId): void
{
$this->spotifyTrackId = $spotifyTrackId;
}
public function getDiscNumber(): int
{
return $this->discNumber;
}
public function setDiscNumber(int $discNumber): void
{
$this->discNumber = max(1, $discNumber);
}
public function getTrackNumber(): int
{
return $this->trackNumber;
}
public function setTrackNumber(int $trackNumber): void
{
$this->trackNumber = max(1, $trackNumber);
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getDurationMs(): int
{
return $this->durationMs;
}
public function setDurationMs(int $durationMs): void
{
$this->durationMs = max(0, $durationMs);
}
public function getPreviewUrl(): ?string
{
return $this->previewUrl;
}
public function setPreviewUrl(?string $previewUrl): void
{
$this->previewUrl = $previewUrl;
}
/**
* Normalizes the track for template rendering.
*
* @return array{disc:int,track:int,name:string,duration_label:string,duration_seconds:int,preview_url:?string}
*/
public function toTemplateArray(): array
{
$seconds = (int) floor($this->durationMs / 1000);
$minutes = intdiv($seconds, 60);
$remainingSeconds = $seconds % 60;
return [
'disc' => $this->discNumber,
'track' => $this->trackNumber,
'name' => $this->name,
'duration_label' => sprintf('%d:%02d', $minutes, $remainingSeconds),
'duration_seconds' => $seconds,
'preview_url' => $this->previewUrl,
];
}
}