mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-22 16:51:20 +00:00
258 lines
6.4 KiB
PHP
258 lines
6.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Class SoundbiteModel Model for podcasts_soundbites table in database
|
|
*
|
|
* @copyright 2020 Ad Aures
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
|
* @link https://castopod.org/
|
|
*/
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Entities\Clip\BaseClip;
|
|
use App\Entities\Clip\Soundbite;
|
|
use App\Entities\Clip\VideoClip;
|
|
use CodeIgniter\Database\BaseResult;
|
|
use CodeIgniter\Database\ConnectionInterface;
|
|
use CodeIgniter\Model;
|
|
use CodeIgniter\Validation\ValidationInterface;
|
|
|
|
class ClipModel extends Model
|
|
{
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $table = 'clips';
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $primaryKey = 'id';
|
|
|
|
/**
|
|
* @var string[]
|
|
*/
|
|
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}");
|
|
}
|
|
}
|