koel/app/Values/Podcast/EpisodePlayable.php

66 lines
1.7 KiB
PHP

<?php
namespace App\Values\Podcast;
use App\Models\Song as Episode;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
final class EpisodePlayable implements Arrayable, Jsonable
{
private function __construct(public readonly string $path, public readonly string $checksum)
{
}
public static function make(string $path, string $sum): self
{
return new self($path, $sum);
}
public function valid(): bool
{
return File::isReadable($this->path) && $this->checksum === md5_file($this->path);
}
public static function getForEpisode(Episode $episode): ?self
{
/** @var self|null $cached */
$cached = Cache::get("episode-playable.$episode->id");
return $cached?->valid() ? $cached : self::createForEpisode($episode);
}
private static function createForEpisode(Episode $episode): self
{
$dir = sys_get_temp_dir() . '/koel-episodes';
$file = sprintf('%s/%s.mp3', $dir, $episode->id);
if (!File::exists($file)) {
File::ensureDirectoryExists($dir);
Http::sink($file)->get($episode->path)->throw();
}
$playable = new self($file, md5_file($file));
Cache::forever("episode-playable.$episode->id", $playable);
return $playable;
}
/** @inheritDoc */
public function toArray(): array
{
return [
'path' => $this->path,
'checksum' => $this->checksum,
];
}
/** @inheritDoc */
public function toJson($options = 0): string
{
return json_encode($this->toArray(), $options);
}
}