Add source to podcast, add related DB records and API responses.
This commit is contained in:
parent
ca425d3e9c
commit
d08235a8da
|
@ -21,6 +21,15 @@ final class Podcast
|
|||
#[OA\Property]
|
||||
public int $storage_location_id;
|
||||
|
||||
#[OA\Property]
|
||||
public string $source;
|
||||
|
||||
#[OA\Property]
|
||||
public ?int $playlist_id = null;
|
||||
|
||||
#[OA\Property]
|
||||
public bool $playlist_auto_publish = false;
|
||||
|
||||
#[OA\Property]
|
||||
public string $title;
|
||||
|
||||
|
|
|
@ -43,7 +43,10 @@ final class PodcastEpisode
|
|||
public bool $has_media = false;
|
||||
|
||||
#[OA\Property]
|
||||
public PodcastMedia $media;
|
||||
public ?string $playlist_media_id = null;
|
||||
|
||||
#[OA\Property]
|
||||
public ?PodcastMedia $media = null;
|
||||
|
||||
#[OA\Property]
|
||||
public bool $has_custom_art = false;
|
||||
|
|
|
@ -38,6 +38,10 @@ final class PodcastApiGenerator
|
|||
$return->id = $record->getIdRequired();
|
||||
$return->storage_location_id = $record->getStorageLocation()->getIdRequired();
|
||||
|
||||
$return->source = $record->getSource()->value;
|
||||
$return->playlist_id = $record->getPlaylist()?->getIdRequired();
|
||||
$return->playlist_auto_publish = $record->playlistAutoPublish();
|
||||
|
||||
$return->title = $record->getTitle();
|
||||
$return->link = $record->getLink();
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ namespace App\Entity\ApiGenerator;
|
|||
|
||||
use App\Entity\Api\PodcastEpisode as ApiPodcastEpisode;
|
||||
use App\Entity\Api\PodcastMedia as ApiPodcastMedia;
|
||||
use App\Entity\Enums\PodcastSources;
|
||||
use App\Entity\PodcastEpisode;
|
||||
use App\Entity\PodcastMedia;
|
||||
use App\Entity\StationMedia;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Utilities\Strings;
|
||||
|
||||
|
@ -34,21 +36,40 @@ final class PodcastEpisodeApiGenerator
|
|||
$return->created_at = $record->getCreatedAt();
|
||||
$return->publish_at = $record->getPublishAt();
|
||||
|
||||
$mediaRow = $record->getMedia();
|
||||
$return->has_media = ($mediaRow instanceof PodcastMedia);
|
||||
if ($mediaRow instanceof PodcastMedia) {
|
||||
$media = new ApiPodcastMedia();
|
||||
$media->id = $mediaRow->getId();
|
||||
$media->original_name = $mediaRow->getOriginalName();
|
||||
$media->length = $mediaRow->getLength();
|
||||
$media->length_text = $mediaRow->getLengthText();
|
||||
$media->path = $mediaRow->getPath();
|
||||
switch ($podcast->getSource()) {
|
||||
case PodcastSources::Playlist:
|
||||
$return->media = null;
|
||||
|
||||
$return->has_media = true;
|
||||
$return->media = $media;
|
||||
} else {
|
||||
$return->has_media = false;
|
||||
$return->media = new ApiPodcastMedia();
|
||||
$playlistMediaRow = $record->getPlaylistMedia();
|
||||
if ($playlistMediaRow instanceof StationMedia) {
|
||||
$return->has_media = true;
|
||||
$return->playlist_media_id = $playlistMediaRow->getUniqueId();
|
||||
} else {
|
||||
$return->has_media = false;
|
||||
$return->playlist_media_id = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case PodcastSources::Manual:
|
||||
$return->playlist_media_id = null;
|
||||
|
||||
$mediaRow = $record->getMedia();
|
||||
$return->has_media = ($mediaRow instanceof PodcastMedia);
|
||||
if ($mediaRow instanceof PodcastMedia) {
|
||||
$media = new ApiPodcastMedia();
|
||||
$media->id = $mediaRow->getId();
|
||||
$media->original_name = $mediaRow->getOriginalName();
|
||||
$media->length = $mediaRow->getLength();
|
||||
$media->length_text = $mediaRow->getLengthText();
|
||||
$media->path = $mediaRow->getPath();
|
||||
|
||||
$return->has_media = true;
|
||||
$return->media = $media;
|
||||
} else {
|
||||
$return->has_media = false;
|
||||
$return->media = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$return->is_published = $record->isPublished();
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity\Enums;
|
||||
|
||||
enum PodcastSources: string
|
||||
{
|
||||
case Manual = 'manual';
|
||||
case Playlist = 'playlist';
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity\Migration;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20240221151753 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add ability for podcasts to sync from playlists.';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE podcast ADD playlist_id INT DEFAULT NULL, ADD source VARCHAR(50) NOT NULL, ADD playlist_auto_publish TINYINT(1) NOT NULL');
|
||||
$this->addSql('ALTER TABLE podcast ADD CONSTRAINT FK_D7E805BD6BBD148 FOREIGN KEY (playlist_id) REFERENCES station_playlists (id) ON DELETE CASCADE');
|
||||
$this->addSql('CREATE INDEX IDX_D7E805BD6BBD148 ON podcast (playlist_id)');
|
||||
$this->addSql('ALTER TABLE podcast_episode ADD playlist_media_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE podcast_episode ADD CONSTRAINT FK_77EB2BD017421B18 FOREIGN KEY (playlist_media_id) REFERENCES station_media (id) ON DELETE CASCADE');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_77EB2BD017421B18 ON podcast_episode (playlist_media_id)');
|
||||
|
||||
$this->addSql(
|
||||
<<<'SQL'
|
||||
UPDATE podcast SET source='manual'
|
||||
SQL
|
||||
);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE podcast DROP FOREIGN KEY FK_D7E805BD6BBD148');
|
||||
$this->addSql('DROP INDEX IDX_D7E805BD6BBD148 ON podcast');
|
||||
$this->addSql('ALTER TABLE podcast DROP playlist_id, DROP source, DROP playlist_auto_publish');
|
||||
$this->addSql('ALTER TABLE podcast_episode DROP FOREIGN KEY FK_77EB2BD017421B18');
|
||||
$this->addSql('DROP INDEX UNIQ_77EB2BD017421B18 ON podcast_episode');
|
||||
$this->addSql('ALTER TABLE podcast_episode DROP playlist_media_id');
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Entity\Enums\PodcastSources;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
@ -25,6 +26,19 @@ class Podcast implements Interfaces\IdentifiableEntityInterface
|
|||
#[ORM\JoinColumn(name: 'storage_location_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
protected StorageLocation $storage_location;
|
||||
|
||||
#[ORM\Column(nullable: false, insertable: false, updatable: false)]
|
||||
protected int $storage_location_id;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'podcasts')]
|
||||
#[ORM\JoinColumn(name: 'playlist_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
protected ?StationPlaylist $playlist = null;
|
||||
|
||||
#[ORM\Column(nullable: true, insertable: false, updatable: false)]
|
||||
protected ?int $playlist_id = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, enumType: PodcastSources::class)]
|
||||
protected PodcastSources $source = PodcastSources::Manual;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Assert\NotBlank]
|
||||
protected string $title;
|
||||
|
@ -51,6 +65,9 @@ class Podcast implements Interfaces\IdentifiableEntityInterface
|
|||
#[Attributes\AuditIgnore]
|
||||
protected int $art_updated_at = 0;
|
||||
|
||||
#[ORM\Column]
|
||||
protected bool $playlist_auto_publish = true;
|
||||
|
||||
/** @var Collection<int, PodcastCategory> */
|
||||
#[ORM\OneToMany(mappedBy: 'podcast', targetEntity: PodcastCategory::class)]
|
||||
protected Collection $categories;
|
||||
|
@ -72,6 +89,26 @@ class Podcast implements Interfaces\IdentifiableEntityInterface
|
|||
return $this->storage_location;
|
||||
}
|
||||
|
||||
public function getPlaylist(): ?StationPlaylist
|
||||
{
|
||||
return $this->playlist;
|
||||
}
|
||||
|
||||
public function setPlaylist(?StationPlaylist $playlist): void
|
||||
{
|
||||
$this->playlist = $playlist;
|
||||
}
|
||||
|
||||
public function getSource(): PodcastSources
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
public function setSource(PodcastSources $source): void
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->title;
|
||||
|
@ -156,6 +193,16 @@ class Podcast implements Interfaces\IdentifiableEntityInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function playlistAutoPublish(): bool
|
||||
{
|
||||
return $this->playlist_auto_publish;
|
||||
}
|
||||
|
||||
public function setPlaylistAutoPublish(bool $playlist_auto_publish): void
|
||||
{
|
||||
$this->playlist_auto_publish = $playlist_auto_publish;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, PodcastCategory>
|
||||
*/
|
||||
|
|
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Entity\Enums\PodcastSources;
|
||||
use App\Entity\Interfaces\IdentifiableEntityInterface;
|
||||
use App\Entity\Traits;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
|
@ -25,6 +25,10 @@ class PodcastEpisode implements IdentifiableEntityInterface
|
|||
#[ORM\JoinColumn(name: 'podcast_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
protected Podcast $podcast;
|
||||
|
||||
#[ORM\OneToOne(inversedBy: 'podcast_episode')]
|
||||
#[ORM\JoinColumn(name: 'playlist_media_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
protected ?StationMedia $playlist_media = null;
|
||||
|
||||
#[ORM\OneToOne(mappedBy: 'episode')]
|
||||
protected ?PodcastMedia $media = null;
|
||||
|
||||
|
@ -73,6 +77,16 @@ class PodcastEpisode implements IdentifiableEntityInterface
|
|||
return $this->media;
|
||||
}
|
||||
|
||||
public function getPlaylistMedia(): ?StationMedia
|
||||
{
|
||||
return $this->playlist_media;
|
||||
}
|
||||
|
||||
public function setPlaylistMedia(?StationMedia $playlist_media): void
|
||||
{
|
||||
$this->playlist_media = $playlist_media;
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->title;
|
||||
|
@ -168,10 +182,9 @@ class PodcastEpisode implements IdentifiableEntityInterface
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($this->getMedia() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return match ($this->getPodcast()->getSource()) {
|
||||
PodcastSources::Manual => ($this->getMedia() !== null),
|
||||
PodcastSources::Playlist => ($this->getPlaylistMedia() !== null)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue