*/ protected $allowedFields = [ 'id', 'podcast_id', 'episode_id', 'title', 'start_time', 'duration', 'type', 'media_id', 'metadata', 'status', 'logs', 'created_by', 'updated_by', 'job_started_at', 'job_ended_at', ]; protected $returnType = BaseClip::class; /** * @var bool */ protected $useSoftDeletes = false; /** * @var bool */ protected $useTimestamps = true; public function __construct( protected string $type = 'audio', ConnectionInterface &$db = null, ValidationInterface $validation = null ) { switch ($type) { case 'audio': $this->returnType = Soundbite::class; break; case 'video': $this->returnType = VideoClip::class; break; default: // do nothing, keep default class break; } parent::__construct($db, $validation); } public function getVideoClipById(int $videoClipId): ?VideoClip { $cacheName = "video-clip#{$videoClipId}"; if (! ($found = cache($cacheName))) { $clip = $this->find($videoClipId); if (! $clip instanceof BaseClip) { return null; } $found = new VideoClip($clip->toArray()); cache() ->save($cacheName, $found, DECADE); } return $found; } /** * Gets scheduled video clips for an episode * * @return VideoClip[] */ public function getScheduledVideoClips(): array { $found = $this->where([ 'type' => 'video', 'status' => 'queued', ]) ->orderBy('created_at') ->findAll(); foreach ($found as $key => $videoClip) { $found[$key] = new VideoClip($videoClip->toArray()); } // @phpstan-ignore-next-line return $found; } public function getRunningVideoClipsCount(): int { $result = $this->builder() ->select('COUNT(*) as `running_count`') ->where([ 'type' => 'video', 'status' => 'running', ]) ->get() ->getResultArray(); return (int) $result[0]['running_count']; } public function doesVideoClipExist(VideoClip $videoClip): int | false { $result = $this->select('id') ->builder() ->where([ 'podcast_id' => $videoClip->podcast_id, 'episode_id' => $videoClip->episode_id, 'start_time' => $videoClip->start_time, 'duration' => $videoClip->duration, ]) ->where('JSON_EXTRACT(`metadata`, "$.format")', $videoClip->format) ->where('JSON_EXTRACT(`metadata`, "$.theme.name")', $videoClip->theme['name']) ->get() ->getResultArray(); if ($result === []) { return false; } return (int) $result[0]['id']; } public function deleteVideoClip(int $podcastId, int $episodeId, int $clipId): BaseResult | bool { $this->clearVideoClipCache($clipId); return $this->delete([ 'podcast_id' => $podcastId, 'episode_id' => $episodeId, 'id' => $clipId, ]); } public function getClipCount(int $podcastId, int $episodeId): int { return $this ->where([ 'podcast_id' => $podcastId, 'episode_id' => $episodeId, ]) ->countAllResults(); } public function clearVideoClipCache(int $clipId): void { cache() ->delete("video-clip#{$clipId}"); } public function getSoundbiteById(int $soundbiteId): ?Soundbite { $cacheName = "soundbite#{$soundbiteId}"; if (! ($found = cache($cacheName))) { $clip = $this->find($soundbiteId); if (! $clip instanceof BaseClip) { return null; } $found = new Soundbite($clip->toArray()); cache() ->save($cacheName, $found, DECADE); } return $found; } /** * Gets all clips for an episode * * @return Soundbite[] */ public function getEpisodeSoundbites(int $podcastId, int $episodeId): array { $cacheName = "podcast#{$podcastId}_episode#{$episodeId}_soundbites"; if (! ($found = cache($cacheName))) { $found = $this->where([ 'episode_id' => $episodeId, 'podcast_id' => $podcastId, 'type' => 'audio', ]) ->orderBy('start_time') ->findAll(); foreach ($found as $key => $soundbite) { $found[$key] = new Soundbite($soundbite->toArray()); } cache() ->save($cacheName, $found, DECADE); } return $found; } public function deleteSoundbite(int $podcastId, int $episodeId, int $clipId): BaseResult | bool { $this->clearSoundbiteCache($podcastId, $episodeId, $clipId); return $this->delete([ 'podcast_id' => $podcastId, 'episode_id' => $episodeId, 'id' => $clipId, ]); } public function clearSoundbiteCache(int $podcastId, int $episodeId, int $clipId): void { cache() ->delete("podcast#{$podcastId}_episode#{$episodeId}_soundbites"); cache() ->delete("soundbite#{$clipId}"); } }