mirror of
https://code.castopod.org/adaures/castopod
synced 2025-06-05 08:52:00 +00:00
feat: add remote_url alternative for transcript and chapters files
This commit is contained in:
parent
1296187613
commit
3143c9ad36
@ -1,4 +1,4 @@
|
|||||||
image: php:7.2-fpm
|
image: php:7.3-fpm
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- bundle
|
- bundle
|
||||||
|
@ -26,10 +26,10 @@ class Analytics extends AnalyticsBase
|
|||||||
$this->gateway = config('App')->adminGateway . '/analytics';
|
$this->gateway = config('App')->adminGateway . '/analytics';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEnclosureUrl($enclosureUri)
|
public function getAudioFileUrl($audioFilePath)
|
||||||
{
|
{
|
||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
return media_base_url($enclosureUri);
|
return media_base_url($audioFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,11 +108,12 @@ class Episode extends BaseController
|
|||||||
public function attemptCreate()
|
public function attemptCreate()
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'enclosure' => 'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]',
|
'audio_file' => 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]',
|
||||||
'image' =>
|
'image' =>
|
||||||
'is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]',
|
'is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]',
|
||||||
'transcript' => 'ext_in[transcript,txt,html,srt,json]|permit_empty',
|
'transcript_file' =>
|
||||||
'chapters' => 'ext_in[chapters,json]|permit_empty',
|
'ext_in[transcript,txt,html,srt,json]|permit_empty',
|
||||||
|
'chapters_file' => 'ext_in[chapters,json]|permit_empty',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$this->validate($rules)) {
|
if (!$this->validate($rules)) {
|
||||||
@ -127,7 +128,7 @@ class Episode extends BaseController
|
|||||||
'title' => $this->request->getPost('title'),
|
'title' => $this->request->getPost('title'),
|
||||||
'slug' => $this->request->getPost('slug'),
|
'slug' => $this->request->getPost('slug'),
|
||||||
'guid' => '',
|
'guid' => '',
|
||||||
'enclosure' => $this->request->getFile('enclosure'),
|
'audio_file' => $this->request->getFile('audio_file'),
|
||||||
'description_markdown' => $this->request->getPost('description'),
|
'description_markdown' => $this->request->getPost('description'),
|
||||||
'image' => $this->request->getFile('image'),
|
'image' => $this->request->getFile('image'),
|
||||||
'location' => $this->request->getPost('location_name'),
|
'location' => $this->request->getPost('location_name'),
|
||||||
@ -151,6 +152,30 @@ class Episode extends BaseController
|
|||||||
'published_at' => null,
|
'published_at' => null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$transcriptChoice = $this->request->getPost('transcript-choice');
|
||||||
|
if (
|
||||||
|
$transcriptChoice === 'upload-file' &&
|
||||||
|
($transcriptFile = $this->request->getFile('transcript_file'))
|
||||||
|
) {
|
||||||
|
$newEpisode->transcript_file = $transcriptFile;
|
||||||
|
} elseif ($transcriptChoice === 'remote-url') {
|
||||||
|
$newEpisode->transcript_file_remote_url = $this->request->getPost(
|
||||||
|
'transcript_file_remote_url',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$chaptersChoice = $this->request->getPost('chapters-choice');
|
||||||
|
if (
|
||||||
|
$chaptersChoice === 'upload-file' &&
|
||||||
|
($chaptersFile = $this->request->getFile('chapters_file'))
|
||||||
|
) {
|
||||||
|
$newEpisode->chapters_file = $chaptersFile;
|
||||||
|
} elseif ($chaptersChoice === 'remote-url') {
|
||||||
|
$newEpisode->chapters_file_remote_url = $this->request->getPost(
|
||||||
|
'chapters_file_remote_url',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$episodeModel = new EpisodeModel();
|
$episodeModel = new EpisodeModel();
|
||||||
|
|
||||||
if (!($newEpisodeId = $episodeModel->insert($newEpisode, true))) {
|
if (!($newEpisodeId = $episodeModel->insert($newEpisode, true))) {
|
||||||
@ -201,12 +226,13 @@ class Episode extends BaseController
|
|||||||
public function attemptEdit()
|
public function attemptEdit()
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'enclosure' =>
|
'audio_file' =>
|
||||||
'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]|permit_empty',
|
'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]|permit_empty',
|
||||||
'image' =>
|
'image' =>
|
||||||
'is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]',
|
'is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]',
|
||||||
'transcript' => 'ext_in[transcript,txt,html,srt,json]|permit_empty',
|
'transcript_file' =>
|
||||||
'chapters' => 'ext_in[chapters,json]|permit_empty',
|
'ext_in[transcript_file,txt,html,srt,json]|permit_empty',
|
||||||
|
'chapters_file' => 'ext_in[chapters_file,json]|permit_empty',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$this->validate($rules)) {
|
if (!$this->validate($rules)) {
|
||||||
@ -240,21 +266,61 @@ class Episode extends BaseController
|
|||||||
|
|
||||||
$this->episode->updated_by = user()->id;
|
$this->episode->updated_by = user()->id;
|
||||||
|
|
||||||
$enclosure = $this->request->getFile('enclosure');
|
$audioFile = $this->request->getFile('audio_file');
|
||||||
if ($enclosure->isValid()) {
|
if ($audioFile) {
|
||||||
$this->episode->enclosure = $enclosure;
|
$this->episode->audio_file = $audioFile;
|
||||||
}
|
}
|
||||||
$image = $this->request->getFile('image');
|
$image = $this->request->getFile('image');
|
||||||
if ($image) {
|
if ($image) {
|
||||||
$this->episode->image = $image;
|
$this->episode->image = $image;
|
||||||
}
|
}
|
||||||
$transcript = $this->request->getFile('transcript');
|
|
||||||
if ($transcript->isValid()) {
|
$transcriptChoice = $this->request->getPost('transcript-choice');
|
||||||
$this->episode->transcript = $transcript;
|
if ($transcriptChoice === 'upload-file') {
|
||||||
|
$transcriptFile = $this->request->getFile('transcript_file');
|
||||||
|
if ($transcriptFile->isValid()) {
|
||||||
|
$this->episode->transcript_file = $transcriptFile;
|
||||||
|
$this->episode->transcript_file_remote_url = null;
|
||||||
|
}
|
||||||
|
} elseif ($transcriptChoice === 'remote-url') {
|
||||||
|
if (
|
||||||
|
$transcriptFileRemoteUrl = $this->request->getPost(
|
||||||
|
'transcript_file_remote_url',
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
($transcriptFile = $this->episode->transcript_file) &&
|
||||||
|
!empty($transcriptFile)
|
||||||
|
) {
|
||||||
|
unlink($transcriptFile);
|
||||||
|
$this->episode->transcript_file_path = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->episode->transcript_file_remote_url = $transcriptFileRemoteUrl;
|
||||||
}
|
}
|
||||||
$chapters = $this->request->getFile('chapters');
|
|
||||||
if ($chapters->isValid()) {
|
$chaptersChoice = $this->request->getPost('chapters-choice');
|
||||||
$this->episode->chapters = $chapters;
|
if ($chaptersChoice === 'upload-file') {
|
||||||
|
$chaptersFile = $this->request->getFile('chapters_file');
|
||||||
|
if ($chaptersFile->isValid()) {
|
||||||
|
$this->episode->chapters_file = $chaptersFile;
|
||||||
|
$this->episode->chapters_file_remote_url = null;
|
||||||
|
}
|
||||||
|
} elseif ($chaptersChoice === 'remote-url') {
|
||||||
|
if (
|
||||||
|
$chaptersFileRemoteUrl = $this->request->getPost(
|
||||||
|
'chapters_file_remote_url',
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
($chaptersFile = $this->episode->chapters_file) &&
|
||||||
|
!empty($chaptersFile)
|
||||||
|
) {
|
||||||
|
unlink($chaptersFile);
|
||||||
|
$this->episode->chapters_file_path = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->episode->chapters_file_remote_url = $chaptersFileRemoteUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
$episodeModel = new EpisodeModel();
|
$episodeModel = new EpisodeModel();
|
||||||
@ -289,8 +355,8 @@ class Episode extends BaseController
|
|||||||
|
|
||||||
public function transcriptDelete()
|
public function transcriptDelete()
|
||||||
{
|
{
|
||||||
unlink($this->episode->transcript);
|
unlink($this->episode->transcript_file);
|
||||||
$this->episode->transcript_uri = null;
|
$this->episode->transcript_file_path = null;
|
||||||
|
|
||||||
$episodeModel = new EpisodeModel();
|
$episodeModel = new EpisodeModel();
|
||||||
|
|
||||||
@ -306,8 +372,8 @@ class Episode extends BaseController
|
|||||||
|
|
||||||
public function chaptersDelete()
|
public function chaptersDelete()
|
||||||
{
|
{
|
||||||
unlink($this->episode->chapters);
|
unlink($this->episode->chapters_file);
|
||||||
$this->episode->chapters_uri = null;
|
$this->episode->chapters_file_path = null;
|
||||||
|
|
||||||
$episodeModel = new EpisodeModel();
|
$episodeModel = new EpisodeModel();
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ class PodcastImport extends BaseController
|
|||||||
'guid' => empty($item->guid) ? null : $item->guid,
|
'guid' => empty($item->guid) ? null : $item->guid,
|
||||||
'title' => $item->title,
|
'title' => $item->title,
|
||||||
'slug' => $slug,
|
'slug' => $slug,
|
||||||
'enclosure' => download_file($item->enclosure->attributes()),
|
'audio_file' => download_file($item->enclosure->attributes()),
|
||||||
'description_markdown' => $converter->convert(
|
'description_markdown' => $converter->convert(
|
||||||
$itemDescriptionHtml,
|
$itemDescriptionHtml,
|
||||||
),
|
),
|
||||||
|
@ -41,7 +41,7 @@ class AddPodcasts extends Migration
|
|||||||
'description_html' => [
|
'description_html' => [
|
||||||
'type' => 'TEXT',
|
'type' => 'TEXT',
|
||||||
],
|
],
|
||||||
'image_uri' => [
|
'image_path' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
],
|
],
|
||||||
|
@ -39,25 +39,25 @@ class AddEpisodes extends Migration
|
|||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 191,
|
'constraint' => 191,
|
||||||
],
|
],
|
||||||
'enclosure_uri' => [
|
'audio_file_path' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
],
|
],
|
||||||
'enclosure_duration' => [
|
'audio_file_duration' => [
|
||||||
'type' => 'INT',
|
'type' => 'INT',
|
||||||
'unsigned' => true,
|
'unsigned' => true,
|
||||||
'comment' => 'Playtime in seconds',
|
'comment' => 'Playtime in seconds',
|
||||||
],
|
],
|
||||||
'enclosure_mimetype' => [
|
'audio_file_mimetype' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
],
|
],
|
||||||
'enclosure_filesize' => [
|
'audio_file_size' => [
|
||||||
'type' => 'INT',
|
'type' => 'INT',
|
||||||
'unsigned' => true,
|
'unsigned' => true,
|
||||||
'comment' => 'File size in bytes',
|
'comment' => 'File size in bytes',
|
||||||
],
|
],
|
||||||
'enclosure_headersize' => [
|
'audio_file_header_size' => [
|
||||||
'type' => 'INT',
|
'type' => 'INT',
|
||||||
'unsigned' => true,
|
'unsigned' => true,
|
||||||
'comment' => 'Header size in bytes',
|
'comment' => 'Header size in bytes',
|
||||||
@ -68,7 +68,7 @@ class AddEpisodes extends Migration
|
|||||||
'description_html' => [
|
'description_html' => [
|
||||||
'type' => 'TEXT',
|
'type' => 'TEXT',
|
||||||
],
|
],
|
||||||
'image_uri' => [
|
'image_path' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
@ -80,16 +80,26 @@ class AddEpisodes extends Migration
|
|||||||
'constraint' => 13,
|
'constraint' => 13,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'transcript_uri' => [
|
'transcript_file_path' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'chapters_uri' => [
|
'transcript_file_remote_url' => [
|
||||||
|
'type' => 'VARCHAR',
|
||||||
|
'constraint' => 512,
|
||||||
|
'null' => true,
|
||||||
|
],
|
||||||
|
'chapters_file_path' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
|
'chapters_file_remote_url' => [
|
||||||
|
'type' => 'VARCHAR',
|
||||||
|
'constraint' => 512,
|
||||||
|
'null' => true,
|
||||||
|
],
|
||||||
'parental_advisory' => [
|
'parental_advisory' => [
|
||||||
'type' => 'ENUM',
|
'type' => 'ENUM',
|
||||||
'constraint' => ['clean', 'explicit'],
|
'constraint' => ['clean', 'explicit'],
|
||||||
|
@ -41,7 +41,7 @@ class AddPersons extends Migration
|
|||||||
'The url to a relevant resource of information about the person, such as a homepage or third-party profile platform.',
|
'The url to a relevant resource of information about the person, such as a homepage or third-party profile platform.',
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'image_uri' => [
|
'image_path' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 255,
|
'constraint' => 255,
|
||||||
],
|
],
|
||||||
|
@ -13,6 +13,8 @@ use App\Models\SoundbiteModel;
|
|||||||
use App\Models\EpisodePersonModel;
|
use App\Models\EpisodePersonModel;
|
||||||
use App\Models\NoteModel;
|
use App\Models\NoteModel;
|
||||||
use CodeIgniter\Entity;
|
use CodeIgniter\Entity;
|
||||||
|
use CodeIgniter\Files\Exceptions\FileNotFoundException;
|
||||||
|
use CodeIgniter\HTTP\Exceptions\HTTPException;
|
||||||
use CodeIgniter\I18n\Time;
|
use CodeIgniter\I18n\Time;
|
||||||
use League\CommonMark\CommonMarkConverter;
|
use League\CommonMark\CommonMarkConverter;
|
||||||
|
|
||||||
@ -36,47 +38,37 @@ class Episode extends Entity
|
|||||||
/**
|
/**
|
||||||
* @var \CodeIgniter\Files\File
|
* @var \CodeIgniter\Files\File
|
||||||
*/
|
*/
|
||||||
protected $enclosure;
|
protected $audioFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \CodeIgniter\Files\File
|
* @var \CodeIgniter\Files\File
|
||||||
*/
|
*/
|
||||||
protected $transcript;
|
protected $transcript_file;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \CodeIgniter\Files\File
|
* @var \CodeIgniter\Files\File
|
||||||
*/
|
*/
|
||||||
protected $chapters;
|
protected $chapters_file;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $enclosure_media_path;
|
protected $audio_file_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $enclosure_url;
|
protected $audio_file_analytics_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $enclosure_web_url;
|
protected $audio_file_web_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $enclosure_opengraph_url;
|
protected $audio_file_opengraph_url;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $transcript_url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $chapters_url;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \App\Entities\EpisodePerson[]
|
* @var \App\Entities\EpisodePerson[]
|
||||||
@ -132,17 +124,19 @@ class Episode extends Entity
|
|||||||
'guid' => 'string',
|
'guid' => 'string',
|
||||||
'slug' => 'string',
|
'slug' => 'string',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
'enclosure_uri' => 'string',
|
'audio_file_path' => 'string',
|
||||||
'enclosure_duration' => 'integer',
|
'audio_file_duration' => 'integer',
|
||||||
'enclosure_mimetype' => 'string',
|
'audio_file_mimetype' => 'string',
|
||||||
'enclosure_filesize' => 'integer',
|
'audio_file_size' => 'integer',
|
||||||
'enclosure_headersize' => 'integer',
|
'audio_file_header_size' => 'integer',
|
||||||
'description_markdown' => 'string',
|
'description_markdown' => 'string',
|
||||||
'description_html' => 'string',
|
'description_html' => 'string',
|
||||||
'image_uri' => '?string',
|
'image_path' => '?string',
|
||||||
'image_mimetype' => '?string',
|
'image_mimetype' => '?string',
|
||||||
'transcript_uri' => '?string',
|
'transcript_file_path' => '?string',
|
||||||
'chapters_uri' => '?string',
|
'transcript_file_remote_url' => '?string',
|
||||||
|
'chapters_file_path' => '?string',
|
||||||
|
'chapters_file_remote_url' => '?string',
|
||||||
'parental_advisory' => '?string',
|
'parental_advisory' => '?string',
|
||||||
'number' => '?integer',
|
'number' => '?integer',
|
||||||
'season_number' => '?integer',
|
'season_number' => '?integer',
|
||||||
@ -176,13 +170,13 @@ class Episode extends Entity
|
|||||||
|
|
||||||
// check whether the user has inputted an image and store
|
// check whether the user has inputted an image and store
|
||||||
$this->attributes['image_mimetype'] = $image->getMimeType();
|
$this->attributes['image_mimetype'] = $image->getMimeType();
|
||||||
$this->attributes['image_uri'] = save_media(
|
$this->attributes['image_path'] = save_media(
|
||||||
$image,
|
$image,
|
||||||
'podcasts/' . $this->getPodcast()->name,
|
'podcasts/' . $this->getPodcast()->name,
|
||||||
$this->attributes['slug'],
|
$this->attributes['slug'],
|
||||||
);
|
);
|
||||||
$this->image = new \App\Libraries\Image(
|
$this->image = new \App\Libraries\Image(
|
||||||
$this->attributes['image_uri'],
|
$this->attributes['image_path'],
|
||||||
$this->attributes['image_mimetype'],
|
$this->attributes['image_mimetype'],
|
||||||
);
|
);
|
||||||
$this->image->saveSizes();
|
$this->image->saveSizes();
|
||||||
@ -193,9 +187,9 @@ class Episode extends Entity
|
|||||||
|
|
||||||
public function getImage(): \App\Libraries\Image
|
public function getImage(): \App\Libraries\Image
|
||||||
{
|
{
|
||||||
if ($image_uri = $this->attributes['image_uri']) {
|
if ($imagePath = $this->attributes['image_path']) {
|
||||||
return new \App\Libraries\Image(
|
return new \App\Libraries\Image(
|
||||||
$image_uri,
|
$imagePath,
|
||||||
$this->attributes['image_mimetype'],
|
$this->attributes['image_mimetype'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -203,58 +197,59 @@ class Episode extends Entity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves an enclosure
|
* Saves an audio file
|
||||||
*
|
*
|
||||||
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $enclosure
|
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $audioFile
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setEnclosure($enclosure = null)
|
public function setAudioFile($audioFile = null)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!empty($enclosure) &&
|
!empty($audioFile) &&
|
||||||
(!($enclosure instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
|
(!($audioFile instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
|
||||||
$enclosure->isValid())
|
$audioFile->isValid())
|
||||||
) {
|
) {
|
||||||
helper(['media', 'id3']);
|
helper(['media', 'id3']);
|
||||||
|
|
||||||
$enclosure_metadata = get_file_tags($enclosure);
|
$audio_metadata = get_file_tags($audioFile);
|
||||||
|
|
||||||
$this->attributes['enclosure_uri'] = save_media(
|
$this->attributes['audio_file_path'] = save_media(
|
||||||
$enclosure,
|
$audioFile,
|
||||||
'podcasts/' . $this->getPodcast()->name,
|
'podcasts/' . $this->getPodcast()->name,
|
||||||
$this->attributes['slug'],
|
$this->attributes['slug'],
|
||||||
);
|
);
|
||||||
$this->attributes['enclosure_duration'] = round(
|
$this->attributes['audio_file_duration'] = round(
|
||||||
$enclosure_metadata['playtime_seconds'],
|
$audio_metadata['playtime_seconds'],
|
||||||
);
|
);
|
||||||
$this->attributes['enclosure_mimetype'] =
|
$this->attributes['audio_file_mimetype'] =
|
||||||
$enclosure_metadata['mime_type'];
|
$audio_metadata['mime_type'];
|
||||||
$this->attributes['enclosure_filesize'] =
|
$this->attributes['audio_file_size'] = $audio_metadata['filesize'];
|
||||||
$enclosure_metadata['filesize'];
|
$this->attributes['audio_file_header_size'] =
|
||||||
$this->attributes['enclosure_headersize'] =
|
$audio_metadata['avdataoffset'];
|
||||||
$enclosure_metadata['avdataoffset'];
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves an episode transcript
|
* Saves an episode transcript file
|
||||||
*
|
*
|
||||||
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $transcript
|
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $transcriptFile
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setTranscript($transcript)
|
public function setTranscriptFile($transcriptFile)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!empty($transcript) &&
|
!empty($transcriptFile) &&
|
||||||
(!($transcript instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
|
(!(
|
||||||
$transcript->isValid())
|
$transcriptFile instanceof \CodeIgniter\HTTP\Files\UploadedFile
|
||||||
|
) ||
|
||||||
|
$transcriptFile->isValid())
|
||||||
) {
|
) {
|
||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
$this->attributes['transcript_uri'] = save_media(
|
$this->attributes['transcript_file_path'] = save_media(
|
||||||
$transcript,
|
$transcriptFile,
|
||||||
$this->getPodcast()->name,
|
$this->getPodcast()->name,
|
||||||
$this->attributes['slug'] . '-transcript',
|
$this->attributes['slug'] . '-transcript',
|
||||||
);
|
);
|
||||||
@ -264,22 +259,22 @@ class Episode extends Entity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves an episode chapters
|
* Saves an episode chapters file
|
||||||
*
|
*
|
||||||
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $chapters
|
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $chaptersFile
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setChapters($chapters)
|
public function setChaptersFile($chaptersFile)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!empty($chapters) &&
|
!empty($chaptersFile) &&
|
||||||
(!($chapters instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
|
(!($chaptersFile instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
|
||||||
$chapters->isValid())
|
$chaptersFile->isValid())
|
||||||
) {
|
) {
|
||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
$this->attributes['chapters_uri'] = save_media(
|
$this->attributes['chapters_file_path'] = save_media(
|
||||||
$chapters,
|
$chaptersFile,
|
||||||
$this->getPodcast()->name,
|
$this->getPodcast()->name,
|
||||||
$this->attributes['slug'] . '-chapters',
|
$this->attributes['slug'] . '-chapters',
|
||||||
);
|
);
|
||||||
@ -288,87 +283,102 @@ class Episode extends Entity
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEnclosure()
|
public function getAudioFile()
|
||||||
{
|
|
||||||
return new \CodeIgniter\Files\File($this->getEnclosureMediaPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTranscript()
|
|
||||||
{
|
|
||||||
return $this->attributes['transcript_uri']
|
|
||||||
? new \CodeIgniter\Files\File($this->getTranscriptMediaPath())
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getChapters()
|
|
||||||
{
|
|
||||||
return $this->attributes['chapters_uri']
|
|
||||||
? new \CodeIgniter\Files\File($this->getChaptersMediaPath())
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEnclosureMediaPath()
|
|
||||||
{
|
{
|
||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
return media_path($this->attributes['enclosure_uri']);
|
return new \CodeIgniter\Files\File(media_path($this->audio_file_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTranscriptMediaPath()
|
public function getTranscriptFile()
|
||||||
|
{
|
||||||
|
if ($this->attributes['transcript_file_path']) {
|
||||||
|
helper('media');
|
||||||
|
|
||||||
|
return new \CodeIgniter\Files\File(
|
||||||
|
media_path($this->attributes['transcript_file_path']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChaptersFile()
|
||||||
|
{
|
||||||
|
if ($this->attributes['chapters_file_path']) {
|
||||||
|
helper('media');
|
||||||
|
|
||||||
|
return new \CodeIgniter\Files\File(
|
||||||
|
media_path($this->attributes['chapters_file_path']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAudioFileUrl()
|
||||||
{
|
{
|
||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
return $this->attributes['transcript_uri']
|
return media_url($this->audio_file_path);
|
||||||
? media_path($this->attributes['transcript_uri'])
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getChaptersMediaPath()
|
public function getAudioFileAnalyticsUrl()
|
||||||
{
|
|
||||||
helper('media');
|
|
||||||
|
|
||||||
return $this->attributes['chapters_uri']
|
|
||||||
? media_path($this->attributes['chapters_uri'])
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEnclosureUrl()
|
|
||||||
{
|
{
|
||||||
helper('analytics');
|
helper('analytics');
|
||||||
|
|
||||||
return generate_episode_analytics_url(
|
return generate_episode_analytics_url(
|
||||||
$this->podcast_id,
|
$this->podcast_id,
|
||||||
$this->id,
|
$this->id,
|
||||||
$this->enclosure_uri,
|
$this->audio_file_path,
|
||||||
$this->enclosure_duration,
|
$this->audio_file_duration,
|
||||||
$this->enclosure_filesize,
|
$this->audio_file_size,
|
||||||
$this->enclosure_headersize,
|
$this->audio_file_header_size,
|
||||||
$this->published_at,
|
$this->published_at,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEnclosureWebUrl()
|
public function getAudioFileWebUrl()
|
||||||
{
|
{
|
||||||
return $this->getEnclosureUrl() . '?_from=-+Website+-';
|
return $this->getAudioFileAnalyticsUrl() . '?_from=-+Website+-';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEnclosureOpengraphUrl()
|
public function getAudioFileOpengraphUrl()
|
||||||
{
|
{
|
||||||
return $this->getEnclosureUrl() . '?_from=-+Open+Graph+-';
|
return $this->getAudioFileAnalyticsUrl() . '?_from=-+Open+Graph+-';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTranscriptUrl()
|
/**
|
||||||
|
* Gets transcript url from transcript file uri if it exists
|
||||||
|
* or returns the transcript_file_remote_url which can be null.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
* @throws HTTPException
|
||||||
|
*/
|
||||||
|
public function getTranscriptFileUrl()
|
||||||
{
|
{
|
||||||
return $this->attributes['transcript_uri']
|
if ($this->attributes['transcript_file_path']) {
|
||||||
? base_url($this->getTranscriptMediaPath())
|
return media_url($this->attributes['transcript_file_path']);
|
||||||
: null;
|
} else {
|
||||||
|
return $this->attributes['transcript_file_remote_url'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getChaptersUrl()
|
/**
|
||||||
|
* Gets chapters file url from chapters file uri if it exists
|
||||||
|
* or returns the chapters_file_remote_url which can be null.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws HTTPException
|
||||||
|
*/
|
||||||
|
public function getChaptersFileUrl()
|
||||||
{
|
{
|
||||||
return $this->attributes['chapters_uri']
|
if ($this->attributes['chapters_file_path']) {
|
||||||
? base_url($this->getChaptersMediaPath())
|
return media_url($this->attributes['chapters_file_path']);
|
||||||
: null;
|
} else {
|
||||||
|
return $this->attributes['chapters_file_remote_url'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ class Person extends Entity
|
|||||||
'full_name' => 'string',
|
'full_name' => 'string',
|
||||||
'unique_name' => 'string',
|
'unique_name' => 'string',
|
||||||
'information_url' => '?string',
|
'information_url' => '?string',
|
||||||
'image_uri' => 'string',
|
'image_path' => 'string',
|
||||||
'image_mimetype' => 'string',
|
'image_mimetype' => 'string',
|
||||||
'created_by' => 'integer',
|
'created_by' => 'integer',
|
||||||
'updated_by' => 'integer',
|
'updated_by' => 'integer',
|
||||||
@ -40,13 +40,13 @@ class Person extends Entity
|
|||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
$this->attributes['image_mimetype'] = $image->getMimeType();
|
$this->attributes['image_mimetype'] = $image->getMimeType();
|
||||||
$this->attributes['image_uri'] = save_media(
|
$this->attributes['image_path'] = save_media(
|
||||||
$image,
|
$image,
|
||||||
'persons',
|
'persons',
|
||||||
$this->attributes['unique_name'],
|
$this->attributes['unique_name'],
|
||||||
);
|
);
|
||||||
$this->image = new \App\Libraries\Image(
|
$this->image = new \App\Libraries\Image(
|
||||||
$this->attributes['image_uri'],
|
$this->attributes['image_path'],
|
||||||
$this->attributes['image_mimetype'],
|
$this->attributes['image_mimetype'],
|
||||||
);
|
);
|
||||||
$this->image->saveSizes();
|
$this->image->saveSizes();
|
||||||
@ -58,7 +58,7 @@ class Person extends Entity
|
|||||||
public function getImage()
|
public function getImage()
|
||||||
{
|
{
|
||||||
return new \App\Libraries\Image(
|
return new \App\Libraries\Image(
|
||||||
$this->attributes['image_uri'],
|
$this->attributes['image_path'],
|
||||||
$this->attributes['image_mimetype'],
|
$this->attributes['image_mimetype'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ class Podcast extends Entity
|
|||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
'description_markdown' => 'string',
|
'description_markdown' => 'string',
|
||||||
'description_html' => 'string',
|
'description_html' => 'string',
|
||||||
'image_uri' => 'string',
|
'image_path' => 'string',
|
||||||
'image_mimetype' => 'string',
|
'image_mimetype' => 'string',
|
||||||
'language_code' => 'string',
|
'language_code' => 'string',
|
||||||
'category_id' => 'integer',
|
'category_id' => 'integer',
|
||||||
@ -161,14 +161,14 @@ class Podcast extends Entity
|
|||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
$this->attributes['image_mimetype'] = $image->getMimeType();
|
$this->attributes['image_mimetype'] = $image->getMimeType();
|
||||||
$this->attributes['image_uri'] = save_media(
|
$this->attributes['image_path'] = save_media(
|
||||||
$image,
|
$image,
|
||||||
'podcasts/' . $this->attributes['name'],
|
'podcasts/' . $this->attributes['name'],
|
||||||
'cover',
|
'cover',
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->image = new \App\Libraries\Image(
|
$this->image = new \App\Libraries\Image(
|
||||||
$this->attributes['image_uri'],
|
$this->attributes['image_path'],
|
||||||
$this->attributes['image_mimetype'],
|
$this->attributes['image_mimetype'],
|
||||||
);
|
);
|
||||||
$this->image->saveSizes();
|
$this->image->saveSizes();
|
||||||
@ -180,7 +180,7 @@ class Podcast extends Entity
|
|||||||
public function getImage()
|
public function getImage()
|
||||||
{
|
{
|
||||||
return new \App\Libraries\Image(
|
return new \App\Libraries\Image(
|
||||||
$this->attributes['image_uri'],
|
$this->attributes['image_path'],
|
||||||
$this->attributes['image_mimetype'],
|
$this->attributes['image_mimetype'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,15 @@ function get_file_tags($file)
|
|||||||
*
|
*
|
||||||
* @return UploadedFile
|
* @return UploadedFile
|
||||||
*/
|
*/
|
||||||
function write_enclosure_tags($episode)
|
function write_audio_file_tags($episode)
|
||||||
{
|
{
|
||||||
|
helper('media');
|
||||||
|
|
||||||
$TextEncoding = 'UTF-8';
|
$TextEncoding = 'UTF-8';
|
||||||
|
|
||||||
// Initialize getID3 tag-writing module
|
// Initialize getID3 tag-writing module
|
||||||
$tagwriter = new WriteTags();
|
$tagwriter = new WriteTags();
|
||||||
$tagwriter->filename = $episode->enclosure_media_path;
|
$tagwriter->filename = media_path($episode->audio_file_path);
|
||||||
|
|
||||||
// set various options (optional)
|
// set various options (optional)
|
||||||
$tagwriter->tagformats = ['id3v2.4'];
|
$tagwriter->tagformats = ['id3v2.4'];
|
||||||
|
@ -12,15 +12,15 @@ use CodeIgniter\HTTP\ResponseInterface;
|
|||||||
/**
|
/**
|
||||||
* Saves a file to the corresponding podcast folder in `public/media`
|
* Saves a file to the corresponding podcast folder in `public/media`
|
||||||
*
|
*
|
||||||
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $file
|
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $filePath
|
||||||
* @param string $podcast_name
|
* @param string $folder
|
||||||
* @param string $file_name
|
* @param string $fileName
|
||||||
*
|
*
|
||||||
* @return string The episode's file path in media root
|
* @return string The episode's file path in media root
|
||||||
*/
|
*/
|
||||||
function save_media($file, $folder, $mediaName)
|
function save_media($filePath, $folder, $mediaName)
|
||||||
{
|
{
|
||||||
$file_name = $mediaName . '.' . $file->getExtension();
|
$fileName = $mediaName . '.' . $filePath->getExtension();
|
||||||
|
|
||||||
$mediaRoot = config('App')->mediaRoot . '/' . $folder;
|
$mediaRoot = config('App')->mediaRoot . '/' . $folder;
|
||||||
|
|
||||||
@ -30,9 +30,9 @@ function save_media($file, $folder, $mediaName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move to media folder and overwrite file if already existing
|
// move to media folder and overwrite file if already existing
|
||||||
$file->move($mediaRoot . '/', $file_name, true);
|
$filePath->move($mediaRoot . '/', $fileName, true);
|
||||||
|
|
||||||
return $folder . '/' . $file_name;
|
return $folder . '/' . $fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,13 +258,13 @@ function get_rss_feed($podcast, $serviceSlug = '')
|
|||||||
|
|
||||||
$enclosure->addAttribute(
|
$enclosure->addAttribute(
|
||||||
'url',
|
'url',
|
||||||
$episode->enclosure_url .
|
$episode->audio_file_analytics_url .
|
||||||
(empty($serviceSlug)
|
(empty($serviceSlug)
|
||||||
? ''
|
? ''
|
||||||
: '?_from=' . urlencode($serviceSlug)),
|
: '?_from=' . urlencode($serviceSlug)),
|
||||||
);
|
);
|
||||||
$enclosure->addAttribute('length', $episode->enclosure_filesize);
|
$enclosure->addAttribute('length', $episode->audio_file_size);
|
||||||
$enclosure->addAttribute('type', $episode->enclosure_mimetype);
|
$enclosure->addAttribute('type', $episode->audio_file_mimetype);
|
||||||
|
|
||||||
$item->addChild('guid', $episode->guid);
|
$item->addChild('guid', $episode->guid);
|
||||||
$item->addChild(
|
$item->addChild(
|
||||||
@ -290,7 +290,7 @@ function get_rss_feed($podcast, $serviceSlug = '')
|
|||||||
);
|
);
|
||||||
$item->addChild(
|
$item->addChild(
|
||||||
'duration',
|
'duration',
|
||||||
$episode->enclosure_duration,
|
$episode->audio_file_duration,
|
||||||
$itunes_namespace,
|
$itunes_namespace,
|
||||||
);
|
);
|
||||||
$item->addChild('link', $episode->link);
|
$item->addChild('link', $episode->link);
|
||||||
@ -318,17 +318,20 @@ function get_rss_feed($podcast, $serviceSlug = '')
|
|||||||
);
|
);
|
||||||
$item->addChild('episodeType', $episode->type, $itunes_namespace);
|
$item->addChild('episodeType', $episode->type, $itunes_namespace);
|
||||||
|
|
||||||
if ($episode->transcript) {
|
if ($episode->transcript_file_url) {
|
||||||
$transcriptElement = $item->addChild(
|
$transcriptElement = $item->addChild(
|
||||||
'transcript',
|
'transcript',
|
||||||
null,
|
null,
|
||||||
$podcast_namespace,
|
$podcast_namespace,
|
||||||
);
|
);
|
||||||
$transcriptElement->addAttribute('url', $episode->transcriptUrl);
|
$transcriptElement->addAttribute(
|
||||||
|
'url',
|
||||||
|
$episode->transcript_file_url,
|
||||||
|
);
|
||||||
$transcriptElement->addAttribute(
|
$transcriptElement->addAttribute(
|
||||||
'type',
|
'type',
|
||||||
Mimes::guessTypeFromExtension(
|
Mimes::guessTypeFromExtension(
|
||||||
pathinfo($episode->transcript_uri, PATHINFO_EXTENSION),
|
pathinfo($episode->transcript_file_url, PATHINFO_EXTENSION),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$transcriptElement->addAttribute(
|
$transcriptElement->addAttribute(
|
||||||
@ -337,13 +340,13 @@ function get_rss_feed($podcast, $serviceSlug = '')
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($episode->chapters) {
|
if ($episode->chapters_file_url) {
|
||||||
$chaptersElement = $item->addChild(
|
$chaptersElement = $item->addChild(
|
||||||
'chapters',
|
'chapters',
|
||||||
null,
|
null,
|
||||||
$podcast_namespace,
|
$podcast_namespace,
|
||||||
);
|
);
|
||||||
$chaptersElement->addAttribute('url', $episode->chaptersUrl);
|
$chaptersElement->addAttribute('url', $episode->chapters_file_url);
|
||||||
$chaptersElement->addAttribute('type', 'application/json+chapters');
|
$chaptersElement->addAttribute('type', 'application/json+chapters');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,5 +31,7 @@ return [
|
|||||||
],
|
],
|
||||||
'image_size_hint' =>
|
'image_size_hint' =>
|
||||||
'Image must be squared with at least 1400px wide and tall.',
|
'Image must be squared with at least 1400px wide and tall.',
|
||||||
|
'upload_file' => 'Upload a file',
|
||||||
|
'remote_url' => 'Remote URL',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -45,8 +45,8 @@ return [
|
|||||||
'form' => [
|
'form' => [
|
||||||
'warning' =>
|
'warning' =>
|
||||||
'In case of fatal error, try increasing the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server.<br />These values must be higher than the audio file you wish to upload.',
|
'In case of fatal error, try increasing the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server.<br />These values must be higher than the audio file you wish to upload.',
|
||||||
'enclosure' => 'Audio file',
|
'audio_file' => 'Audio file',
|
||||||
'enclosure_hint' => 'Choose an .mp3 or .m4a audio file.',
|
'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.',
|
||||||
'info_section_title' => 'Episode info',
|
'info_section_title' => 'Episode info',
|
||||||
'info_section_subtitle' => '',
|
'info_section_subtitle' => '',
|
||||||
'image' => 'Cover image',
|
'image' => 'Cover image',
|
||||||
@ -90,10 +90,14 @@ return [
|
|||||||
'location_name_hint' => 'This can be a real or fictional location',
|
'location_name_hint' => 'This can be a real or fictional location',
|
||||||
'transcript' => 'Transcript or closed captions',
|
'transcript' => 'Transcript or closed captions',
|
||||||
'transcript_hint' => 'Allowed formats are txt, html, srt or json.',
|
'transcript_hint' => 'Allowed formats are txt, html, srt or json.',
|
||||||
'transcript_delete' => 'Delete transcript',
|
'transcript_file' => 'Transcript file',
|
||||||
|
'transcript_file_remote_url' => 'Remote url for transcript',
|
||||||
|
'transcript_file_delete' => 'Delete transcript file',
|
||||||
'chapters' => 'Chapters',
|
'chapters' => 'Chapters',
|
||||||
'chapters_hint' => 'File should be in JSON Chapters Format.',
|
'chapters_hint' => 'File must be in JSON Chapters format.',
|
||||||
'chapters_delete' => 'Delete chapters',
|
'chapters_file' => 'Chapters file',
|
||||||
|
'chapters_file_remote_url' => 'Remote url for chapters file',
|
||||||
|
'chapters_file_delete' => 'Delete chapters file',
|
||||||
'advanced_section_title' => 'Advanced Parameters',
|
'advanced_section_title' => 'Advanced Parameters',
|
||||||
'advanced_section_subtitle' =>
|
'advanced_section_subtitle' =>
|
||||||
'If you need RSS tags that Castopod does not handle, set them here.',
|
'If you need RSS tags that Castopod does not handle, set them here.',
|
||||||
|
@ -22,6 +22,6 @@ return [
|
|||||||
'submit_edit' => 'Save',
|
'submit_edit' => 'Save',
|
||||||
],
|
],
|
||||||
'messages' => [
|
'messages' => [
|
||||||
'createSuccess' => 'The page "{pageTitle}" was created successfully!',
|
'createSuccess' => 'The page “{pageTitle}” was created successfully!',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -31,5 +31,7 @@ return [
|
|||||||
],
|
],
|
||||||
'image_size_hint' =>
|
'image_size_hint' =>
|
||||||
'L’image doit être carrée, avec au minimum 1400px de long et de large.',
|
'L’image doit être carrée, avec au minimum 1400px de long et de large.',
|
||||||
|
'upload_file' => 'Téléversez un fichier',
|
||||||
|
'remote_url' => 'URL distante',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -45,8 +45,8 @@ return [
|
|||||||
'form' => [
|
'form' => [
|
||||||
'warning' =>
|
'warning' =>
|
||||||
'En cas d’erreur fatale, essayez d’augmenter les valeurs de `memory_limit`, `upload_max_filesize` et `post_max_size` dans votre fichier de configuration php puis redémarrez votre serveur web.<br />Les valeurs doivent être plus grandes que le fichier audio que vous souhaitez téléverser.',
|
'En cas d’erreur fatale, essayez d’augmenter les valeurs de `memory_limit`, `upload_max_filesize` et `post_max_size` dans votre fichier de configuration php puis redémarrez votre serveur web.<br />Les valeurs doivent être plus grandes que le fichier audio que vous souhaitez téléverser.',
|
||||||
'enclosure' => 'Fichier audio',
|
'audio_file' => 'Fichier audio',
|
||||||
'enclosure_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
|
'audio_file_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
|
||||||
'info_section_title' => 'Informations épisode',
|
'info_section_title' => 'Informations épisode',
|
||||||
'info_section_subtitle' => '',
|
'info_section_subtitle' => '',
|
||||||
'image' => 'Image de couverture',
|
'image' => 'Image de couverture',
|
||||||
@ -91,10 +91,16 @@ return [
|
|||||||
'transcript' => 'Transcription ou sous-titrage',
|
'transcript' => 'Transcription ou sous-titrage',
|
||||||
'transcript_hint' =>
|
'transcript_hint' =>
|
||||||
'Les formats autorisés sont txt, html, srt ou json.',
|
'Les formats autorisés sont txt, html, srt ou json.',
|
||||||
'transcript_delete' => 'Supprimer la transcription',
|
'transcript_file' => 'Fichier de transcription',
|
||||||
|
'transcript_file_remote_url' =>
|
||||||
|
'URL distante pour le fichier de transcription',
|
||||||
|
'transcript_file_delete' => 'Supprimer le fichier de transcription',
|
||||||
'chapters' => 'Chapitrage',
|
'chapters' => 'Chapitrage',
|
||||||
'chapters_hint' => 'Le fichier doit être en "JSON Chapters Format".',
|
'chapters_hint' => 'Le fichier doit être en format “JSON Chapters”.',
|
||||||
'chapters_delete' => 'Supprimer le chapitrage',
|
'chapters_file' => 'Fichier de chapitrage',
|
||||||
|
'chapters_file_remote_url' =>
|
||||||
|
'URL distante pour le fichier de chapitrage',
|
||||||
|
'chapters_file_delete' => 'Supprimer le fichier de chapitrage',
|
||||||
'advanced_section_title' => 'Paramètres avancés',
|
'advanced_section_title' => 'Paramètres avancés',
|
||||||
'advanced_section_subtitle' =>
|
'advanced_section_subtitle' =>
|
||||||
'Si vous avez besoin d’une balise que Castopod ne couvre pas, définissez-la ici.',
|
'Si vous avez besoin d’une balise que Castopod ne couvre pas, définissez-la ici.',
|
||||||
|
@ -26,13 +26,13 @@ class Analytics extends BaseConfig
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the full enclosure url
|
* get the full audio file url
|
||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getEnclosureUrl(string $enclosureUri)
|
public function getAudioFileUrl(string $audioFilePath)
|
||||||
{
|
{
|
||||||
return base_url($enclosureUri);
|
return base_url($audioFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ class EpisodeAnalyticsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add one hit to this episode:
|
// Add one hit to this episode:
|
||||||
public function hit($base64EpisodeData, ...$enclosureUri)
|
public function hit($base64EpisodeData, ...$audioFilePath)
|
||||||
{
|
{
|
||||||
$session = \Config\Services::session();
|
$session = \Config\Services::session();
|
||||||
$session->start();
|
$session->start();
|
||||||
@ -78,6 +78,6 @@ class EpisodeAnalyticsController extends Controller
|
|||||||
$serviceName,
|
$serviceName,
|
||||||
);
|
);
|
||||||
|
|
||||||
return redirect()->to($this->config->getEnclosureUrl($enclosureUri));
|
return redirect()->to($this->config->getAudioFileUrl($audioFilePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,15 +30,15 @@ if (!function_exists('base64_url_decode')) {
|
|||||||
|
|
||||||
if (!function_exists('generate_episode_analytics_url')) {
|
if (!function_exists('generate_episode_analytics_url')) {
|
||||||
/**
|
/**
|
||||||
* Builds the episode analytics url that redirects to the enclosure url
|
* Builds the episode analytics url that redirects to the audio file url
|
||||||
* after analytics hit.
|
* after analytics hit.
|
||||||
*
|
*
|
||||||
* @param int $podcastId
|
* @param int $podcastId
|
||||||
* @param int $episodeId
|
* @param int $episodeId
|
||||||
* @param string $enclosureUri
|
* @param string $audioFilePath
|
||||||
* @param int $enclosureDuration
|
* @param int $audioFileDuration
|
||||||
* @param int $enclosureFilesize
|
* @param int $audioFileSize
|
||||||
* @param int $enclosureHeadersize
|
* @param int $audioFileHeaderSize
|
||||||
* @param \CodeIgniter\I18n\Time $publicationDate
|
* @param \CodeIgniter\I18n\Time $publicationDate
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
@ -47,10 +47,10 @@ if (!function_exists('generate_episode_analytics_url')) {
|
|||||||
function generate_episode_analytics_url(
|
function generate_episode_analytics_url(
|
||||||
$podcastId,
|
$podcastId,
|
||||||
$episodeId,
|
$episodeId,
|
||||||
$enclosureUri,
|
$audioFilePath,
|
||||||
$enclosureDuration,
|
$audioFileDuration,
|
||||||
$enclosureFilesize,
|
$audioFileFilesize,
|
||||||
$enclosureHeadersize,
|
$audioFileHeaderSize,
|
||||||
$publicationDate
|
$publicationDate
|
||||||
) {
|
) {
|
||||||
return url_to(
|
return url_to(
|
||||||
@ -61,22 +61,22 @@ if (!function_exists('generate_episode_analytics_url')) {
|
|||||||
$podcastId,
|
$podcastId,
|
||||||
$episodeId,
|
$episodeId,
|
||||||
// bytes_threshold: number of bytes that must be downloaded for an episode to be counted in download analytics
|
// bytes_threshold: number of bytes that must be downloaded for an episode to be counted in download analytics
|
||||||
// - if file is shorter than 60sec, then it's enclosure_filesize
|
// - if file is shorter than 60sec, then it's audio_file_size
|
||||||
// - if file is longer than 60 seconds then it's enclosure_headersize + 60 seconds
|
// - if file is longer than 60 seconds then it's audio_file_header_size + 60 seconds
|
||||||
$enclosureDuration <= 60
|
$audioFileDuration <= 60
|
||||||
? $enclosureFilesize
|
? $audioFileFilesize
|
||||||
: $enclosureHeadersize +
|
: $audioFileHeaderSize +
|
||||||
floor(
|
floor(
|
||||||
(($enclosureFilesize - $enclosureHeadersize) /
|
(($audioFileFilesize - $audioFileHeaderSize) /
|
||||||
$enclosureDuration) *
|
$audioFileDuration) *
|
||||||
60,
|
60,
|
||||||
),
|
),
|
||||||
$enclosureFilesize,
|
$audioFileFilesize,
|
||||||
$enclosureDuration,
|
$audioFileDuration,
|
||||||
strtotime($publicationDate),
|
strtotime($publicationDate),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
$enclosureUri,
|
$audioFilePath,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,17 +70,17 @@ class Image
|
|||||||
*/
|
*/
|
||||||
public $id3_path;
|
public $id3_path;
|
||||||
|
|
||||||
public function __construct($originalUri, $mimetype)
|
public function __construct($originalPath, $mimetype)
|
||||||
{
|
{
|
||||||
helper('media');
|
helper('media');
|
||||||
|
|
||||||
$originalPath = media_path($originalUri);
|
$originalMediaPath = media_path($originalPath);
|
||||||
|
|
||||||
[
|
[
|
||||||
'filename' => $filename,
|
'filename' => $filename,
|
||||||
'dirname' => $dirname,
|
'dirname' => $dirname,
|
||||||
'extension' => $extension,
|
'extension' => $extension,
|
||||||
] = pathinfo($originalPath);
|
] = pathinfo($originalMediaPath);
|
||||||
|
|
||||||
// load images extensions from config
|
// load images extensions from config
|
||||||
$this->config = config('Images');
|
$this->config = config('Images');
|
||||||
@ -100,8 +100,8 @@ class Image
|
|||||||
$feed = $dirname . '/' . $filename . $feedExtension . '.' . $extension;
|
$feed = $dirname . '/' . $filename . $feedExtension . '.' . $extension;
|
||||||
$id3 = $dirname . '/' . $filename . $id3Extension . '.' . $extension;
|
$id3 = $dirname . '/' . $filename . $id3Extension . '.' . $extension;
|
||||||
|
|
||||||
$this->original_path = $originalPath;
|
$this->original_path = $originalMediaPath;
|
||||||
$this->original_url = media_url($originalUri);
|
$this->original_url = media_url($originalMediaPath);
|
||||||
$this->thumbnail_path = $thumbnail;
|
$this->thumbnail_path = $thumbnail;
|
||||||
$this->thumbnail_url = base_url($thumbnail);
|
$this->thumbnail_url = base_url($thumbnail);
|
||||||
$this->medium_path = $medium;
|
$this->medium_path = $medium;
|
||||||
|
@ -21,17 +21,19 @@ class EpisodeModel extends Model
|
|||||||
'guid',
|
'guid',
|
||||||
'title',
|
'title',
|
||||||
'slug',
|
'slug',
|
||||||
'enclosure_uri',
|
'audio_file_path',
|
||||||
'enclosure_duration',
|
'audio_file_duration',
|
||||||
'enclosure_mimetype',
|
'audio_file_mimetype',
|
||||||
'enclosure_filesize',
|
'audio_file_size',
|
||||||
'enclosure_headersize',
|
'audio_file_header_size',
|
||||||
'description_markdown',
|
'description_markdown',
|
||||||
'description_html',
|
'description_html',
|
||||||
'image_uri',
|
'image_path',
|
||||||
'image_mimetype',
|
'image_mimetype',
|
||||||
'transcript_uri',
|
'transcript_file_path',
|
||||||
'chapters_uri',
|
'transcript_file_remote_url',
|
||||||
|
'chapters_file_path',
|
||||||
|
'chapters_file_remote_url',
|
||||||
'parental_advisory',
|
'parental_advisory',
|
||||||
'number',
|
'number',
|
||||||
'season_number',
|
'season_number',
|
||||||
@ -58,11 +60,13 @@ class EpisodeModel extends Model
|
|||||||
'podcast_id' => 'required',
|
'podcast_id' => 'required',
|
||||||
'title' => 'required',
|
'title' => 'required',
|
||||||
'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]',
|
'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]',
|
||||||
'enclosure_uri' => 'required',
|
'audio_file_path' => 'required',
|
||||||
'description_markdown' => 'required',
|
'description_markdown' => 'required',
|
||||||
'number' => 'is_natural_no_zero|permit_empty',
|
'number' => 'is_natural_no_zero|permit_empty',
|
||||||
'season_number' => 'is_natural_no_zero|permit_empty',
|
'season_number' => 'is_natural_no_zero|permit_empty',
|
||||||
'type' => 'required',
|
'type' => 'required',
|
||||||
|
'transcript_file_remote_url' => 'valid_url|permit_empty',
|
||||||
|
'chapters_file_remote_url' => 'valid_url|permit_empty',
|
||||||
'published_at' => 'valid_date|permit_empty',
|
'published_at' => 'valid_date|permit_empty',
|
||||||
'created_by' => 'required',
|
'created_by' => 'required',
|
||||||
'updated_by' => 'required',
|
'updated_by' => 'required',
|
||||||
@ -268,7 +272,7 @@ class EpisodeModel extends Model
|
|||||||
is_array($data['id']) ? $data['id'][0] : $data['id'],
|
is_array($data['id']) ? $data['id'][0] : $data['id'],
|
||||||
);
|
);
|
||||||
|
|
||||||
write_enclosure_tags($episode);
|
write_audio_file_tags($episode);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class PersonModel extends Model
|
|||||||
'full_name',
|
'full_name',
|
||||||
'unique_name',
|
'unique_name',
|
||||||
'information_url',
|
'information_url',
|
||||||
'image_uri',
|
'image_path',
|
||||||
'image_mimetype',
|
'image_mimetype',
|
||||||
'created_by',
|
'created_by',
|
||||||
'updated_by',
|
'updated_by',
|
||||||
@ -35,7 +35,7 @@ class PersonModel extends Model
|
|||||||
'full_name' => 'required',
|
'full_name' => 'required',
|
||||||
'unique_name' =>
|
'unique_name' =>
|
||||||
'required|regex_match[/^[a-z0-9\-]{1,191}$/]|is_unique[persons.unique_name,id,{id}]',
|
'required|regex_match[/^[a-z0-9\-]{1,191}$/]|is_unique[persons.unique_name,id,{id}]',
|
||||||
'image_uri' => 'required',
|
'image_path' => 'required',
|
||||||
'created_by' => 'required',
|
'created_by' => 'required',
|
||||||
'updated_by' => 'required',
|
'updated_by' => 'required',
|
||||||
];
|
];
|
||||||
|
@ -25,7 +25,7 @@ class PodcastModel extends Model
|
|||||||
'description_html',
|
'description_html',
|
||||||
'episode_description_footer_markdown',
|
'episode_description_footer_markdown',
|
||||||
'episode_description_footer_html',
|
'episode_description_footer_html',
|
||||||
'image_uri',
|
'image_path',
|
||||||
'image_mimetype',
|
'image_mimetype',
|
||||||
'language_code',
|
'language_code',
|
||||||
'category_id',
|
'category_id',
|
||||||
@ -62,7 +62,7 @@ class PodcastModel extends Model
|
|||||||
'name' =>
|
'name' =>
|
||||||
'required|regex_match[/^[a-zA-Z0-9\_]{1,191}$/]|is_unique[podcasts.name,id,{id}]',
|
'required|regex_match[/^[a-zA-Z0-9\_]{1,191}$/]|is_unique[podcasts.name,id,{id}]',
|
||||||
'description_markdown' => 'required',
|
'description_markdown' => 'required',
|
||||||
'image_uri' => 'required',
|
'image_path' => 'required',
|
||||||
'language_code' => 'required',
|
'language_code' => 'required',
|
||||||
'category_id' => 'required',
|
'category_id' => 'required',
|
||||||
'owner_email' => 'required|valid_email',
|
'owner_email' => 'required|valid_email',
|
||||||
|
36
app/Views/_assets/styles/formInputTabs.css
Normal file
36
app/Views/_assets/styles/formInputTabs.css
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@layer components {
|
||||||
|
.form-input-tabs > input[type="radio"] {
|
||||||
|
@apply absolute -left-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input-tabs .tab-panel {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logic for 2 tabs at most */
|
||||||
|
.form-input-tabs
|
||||||
|
> input:first-child:checked
|
||||||
|
~ .tab-panels
|
||||||
|
> .tab-panel:first-child,
|
||||||
|
.form-input-tabs
|
||||||
|
> input:nth-child(3):checked
|
||||||
|
~ .tab-panels
|
||||||
|
> .tab-panel:nth-child(2) {
|
||||||
|
@apply block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styling */
|
||||||
|
.form-input-tabs > label {
|
||||||
|
@apply relative inline-block px-1 py-2 text-xs text-center cursor-pointer opacity-70 hover:opacity-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input-tabs > input:checked + label::after {
|
||||||
|
@apply absolute inset-x-0 bottom-0 w-full mx-auto bg-pine-700;
|
||||||
|
content: "";
|
||||||
|
height: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input-tabs > input:checked + label {
|
||||||
|
@apply font-semibold opacity-100 text-pine-700;
|
||||||
|
}
|
||||||
|
}
|
@ -10,3 +10,4 @@
|
|||||||
@import "./note.css";
|
@import "./note.css";
|
||||||
@import "./tabs.css";
|
@import "./tabs.css";
|
||||||
@import "./radioToggler.css";
|
@import "./radioToggler.css";
|
||||||
|
@import "./formInputTabs.css";
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
@apply absolute -left-full;
|
@apply absolute -left-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-panel {
|
.tabset .tab-panel {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@
|
|||||||
@apply font-semibold opacity-100 text-pine-700;
|
@apply font-semibold opacity-100 text-pine-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-panels {
|
.tabset .tab-panels {
|
||||||
@apply col-span-2 p-6;
|
@apply col-span-2 p-6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,14 @@
|
|||||||
) ?>
|
) ?>
|
||||||
|
|
||||||
<?= form_label(
|
<?= form_label(
|
||||||
lang('Episode.form.enclosure'),
|
lang('Episode.form.audio_file'),
|
||||||
'enclosure',
|
'audio_file',
|
||||||
[],
|
[],
|
||||||
lang('Episode.form.enclosure_hint'),
|
lang('Episode.form.audio_file_hint'),
|
||||||
) ?>
|
) ?>
|
||||||
<?= form_input([
|
<?= form_input([
|
||||||
'id' => 'enclosure',
|
'id' => 'audio_file',
|
||||||
'name' => 'enclosure',
|
'name' => 'audio_file',
|
||||||
'class' => 'form-input mb-4',
|
'class' => 'form-input mb-4',
|
||||||
'required' => 'required',
|
'required' => 'required',
|
||||||
'type' => 'file',
|
'type' => 'file',
|
||||||
@ -263,34 +263,133 @@
|
|||||||
lang('Episode.form.additional_files_section_title'),
|
lang('Episode.form.additional_files_section_title'),
|
||||||
lang('Episode.form.additional_files_section_subtitle'),
|
lang('Episode.form.additional_files_section_subtitle'),
|
||||||
) ?>
|
) ?>
|
||||||
<?= form_label(
|
|
||||||
lang('Episode.form.transcript'),
|
<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?>
|
||||||
'transcript',
|
<legend><?= lang('Episode.form.transcript') .
|
||||||
[],
|
'<small class="ml-1 lowercase">(' .
|
||||||
lang('Episode.form.transcript_hint'),
|
lang('Common.optional') .
|
||||||
true,
|
')</small>' .
|
||||||
) ?>
|
hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend>
|
||||||
<?= form_input([
|
<div class="mb-4 form-input-tabs">
|
||||||
'id' => 'transcript',
|
<input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= old(
|
||||||
'name' => 'transcript',
|
'transcript-choice',
|
||||||
'class' => 'form-input mb-4',
|
) !== 'remote-url'
|
||||||
'type' => 'file',
|
? 'checked'
|
||||||
'accept' => '.txt,.html,.srt,.json',
|
: '' ?> />
|
||||||
]) ?>
|
<label for="transcript-file-upload-choice"><?= lang(
|
||||||
<?= form_label(
|
'Common.forms.upload_file',
|
||||||
lang('Episode.form.chapters'),
|
) ?></label>
|
||||||
'chapters',
|
|
||||||
[],
|
<input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= old(
|
||||||
lang('Episode.form.chapters_hint'),
|
'transcript-choice',
|
||||||
true,
|
) === 'remote-url'
|
||||||
) ?>
|
? 'checked'
|
||||||
<?= form_input([
|
: '' ?> />
|
||||||
'id' => 'chapters',
|
<label for="transcript-file-remote-url-choice"><?= lang(
|
||||||
'name' => 'chapters',
|
'Common.forms.remote_url',
|
||||||
'class' => 'form-input mb-4',
|
) ?></label>
|
||||||
'type' => 'file',
|
|
||||||
'accept' => '.json',
|
<div class="py-2 tab-panels">
|
||||||
]) ?>
|
<section id="transcript-file-upload" class="flex items-center tab-panel">
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.transcript_file'),
|
||||||
|
'transcript_file',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.transcript_file'),
|
||||||
|
true,
|
||||||
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'transcript_file',
|
||||||
|
'name' => 'transcript_file',
|
||||||
|
'class' => 'form-input',
|
||||||
|
'type' => 'file',
|
||||||
|
'accept' => '.txt,.html,.srt,.json',
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
<section id="transcript-file-remote-url" class="tab-panel">
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.transcript_file_remote_url'),
|
||||||
|
'transcript_file_remote_url',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.transcript_file_remote_url'),
|
||||||
|
true,
|
||||||
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'transcript_file_remote_url',
|
||||||
|
'name' => 'transcript_file_remote_url',
|
||||||
|
'class' => 'form-input w-full',
|
||||||
|
'type' => 'url',
|
||||||
|
'placeholder' => 'https://...',
|
||||||
|
'value' => old('transcript_file_remote_url'),
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?= form_fieldset_close() ?>
|
||||||
|
|
||||||
|
<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?>
|
||||||
|
<legend><?= lang('Episode.form.chapters') .
|
||||||
|
'<small class="ml-1 lowercase">(' .
|
||||||
|
lang('Common.optional') .
|
||||||
|
')</small>' .
|
||||||
|
hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?></legend>
|
||||||
|
<div class="mb-4 form-input-tabs">
|
||||||
|
<input type="radio" name="chapters-choice" id="chapters-file-upload-choice" aria-controls="chapters-file-upload-choice" value="upload-file" <?= old(
|
||||||
|
'chapters-choice',
|
||||||
|
) !== 'remote-url'
|
||||||
|
? 'checked'
|
||||||
|
: '' ?> />
|
||||||
|
<label for="chapters-file-upload-choice"><?= lang(
|
||||||
|
'Common.forms.upload_file',
|
||||||
|
) ?></label>
|
||||||
|
|
||||||
|
<input type="radio" name="chapters-choice" id="chapters-file-remote-url-choice" aria-controls="chapters-file-remote-url-choice" value="remote-url" <?= old(
|
||||||
|
'chapters-choice',
|
||||||
|
) === 'remote-url'
|
||||||
|
? 'checked'
|
||||||
|
: '' ?> />
|
||||||
|
<label for="chapters-file-remote-url-choice"><?= lang(
|
||||||
|
'Common.forms.remote_url',
|
||||||
|
) ?></label>
|
||||||
|
|
||||||
|
<div class="py-2 tab-panels">
|
||||||
|
<section id="chapters-file-upload" class="flex items-center tab-panel">
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.chapters_file'),
|
||||||
|
'chapters_file',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.chapters_file'),
|
||||||
|
true,
|
||||||
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'chapters_file',
|
||||||
|
'name' => 'chapters_file',
|
||||||
|
'class' => 'form-input',
|
||||||
|
'type' => 'file',
|
||||||
|
'accept' => '.json',
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
<section id="chapters-file-remote-url" class="tab-panel">
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.chapters_file_remote_url'),
|
||||||
|
'chapters_file_remote_url',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.chapters_file_remote_url'),
|
||||||
|
true,
|
||||||
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'chapters_file_remote_url',
|
||||||
|
'name' => 'chapters_file_remote_url',
|
||||||
|
'class' => 'form-input w-full',
|
||||||
|
'type' => 'url',
|
||||||
|
'placeholder' => 'https://...',
|
||||||
|
'value' => old('chapters_file_remote_url'),
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?= form_fieldset_close() ?>
|
||||||
|
|
||||||
<?= form_section_close() ?>
|
<?= form_section_close() ?>
|
||||||
|
|
||||||
<?= form_section(
|
<?= form_section(
|
||||||
|
@ -24,18 +24,26 @@
|
|||||||
|
|
||||||
<?= form_section(
|
<?= form_section(
|
||||||
lang('Episode.form.info_section_title'),
|
lang('Episode.form.info_section_title'),
|
||||||
lang('Episode.form.info_section_subtitle'),
|
'<img
|
||||||
|
src="' .
|
||||||
|
$episode->image->medium_url .
|
||||||
|
'"
|
||||||
|
alt="' .
|
||||||
|
$episode->title .
|
||||||
|
'"
|
||||||
|
class="w-48"
|
||||||
|
/>',
|
||||||
) ?>
|
) ?>
|
||||||
|
|
||||||
<?= form_label(
|
<?= form_label(
|
||||||
lang('Episode.form.enclosure'),
|
lang('Episode.form.audio_file'),
|
||||||
'enclosure',
|
'audio_file',
|
||||||
[],
|
[],
|
||||||
lang('Episode.form.enclosure_hint'),
|
lang('Episode.form.audio_file_hint'),
|
||||||
) ?>
|
) ?>
|
||||||
<?= form_input([
|
<?= form_input([
|
||||||
'id' => 'enclosure',
|
'id' => 'audio_file',
|
||||||
'name' => 'enclosure',
|
'name' => 'audio_file',
|
||||||
'class' => 'form-input mb-4',
|
'class' => 'form-input mb-4',
|
||||||
'type' => 'file',
|
'type' => 'file',
|
||||||
'accept' => '.mp3,.m4a',
|
'accept' => '.mp3,.m4a',
|
||||||
@ -48,11 +56,7 @@
|
|||||||
lang('Episode.form.image_hint'),
|
lang('Episode.form.image_hint'),
|
||||||
true,
|
true,
|
||||||
) ?>
|
) ?>
|
||||||
<img
|
|
||||||
src="<?= $episode->image->thumbnail_url ?>"
|
|
||||||
alt="<?= $episode->title ?>"
|
|
||||||
class="object-cover w-32 h-32"
|
|
||||||
/>
|
|
||||||
<?= form_input([
|
<?= form_input([
|
||||||
'id' => 'image',
|
'id' => 'image',
|
||||||
'name' => 'image',
|
'name' => 'image',
|
||||||
@ -272,86 +276,192 @@
|
|||||||
'“<a href="https://github.com/Podcastindex-org/podcast-namespace" target="_blank" rel="noreferrer noopener" style="text-decoration: underline;">podcast namespace</a>”',
|
'“<a href="https://github.com/Podcastindex-org/podcast-namespace" target="_blank" rel="noreferrer noopener" style="text-decoration: underline;">podcast namespace</a>”',
|
||||||
]),
|
]),
|
||||||
) ?>
|
) ?>
|
||||||
<div class="flex flex-col flex-1">
|
|
||||||
<?= form_label(
|
<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?>
|
||||||
lang('Episode.form.transcript'),
|
<legend><?= lang('Episode.form.transcript') .
|
||||||
'transcript',
|
'<small class="ml-1 lowercase">(' .
|
||||||
[],
|
lang('Common.optional') .
|
||||||
lang('Episode.form.transcript_hint'),
|
')</small>' .
|
||||||
true,
|
hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend>
|
||||||
) ?>
|
<div class="mb-4 form-input-tabs">
|
||||||
<?php if ($episode->transcript): ?>
|
<input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= !$episode->transcript_file_remote_url
|
||||||
<div class="flex justify-between">
|
? 'checked'
|
||||||
<?= anchor(
|
: '' ?> />
|
||||||
$episode->transcriptUrl,
|
<label for="transcript-file-upload-choice"><?= lang(
|
||||||
icon('file', 'mr-2') . $episode->transcript,
|
'Common.forms.upload_file',
|
||||||
[
|
) ?></label>
|
||||||
'class' => 'inline-flex items-center text-xs',
|
|
||||||
'target' => '_blank',
|
<input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= $episode->transcript_file_remote_url
|
||||||
'rel' => 'noreferrer noopener',
|
? 'checked'
|
||||||
],
|
: '' ?> />
|
||||||
) .
|
<label for="transcript-file-remote-url-choice"><?= lang(
|
||||||
anchor(
|
'Common.forms.remote_url',
|
||||||
route_to('transcript-delete', $podcast->id, $episode->id),
|
) ?></label>
|
||||||
icon('delete-bin', 'mx-auto'),
|
|
||||||
[
|
<div class="py-2 tab-panels">
|
||||||
'class' =>
|
<section id="transcript-file-upload" class="flex items-center tab-panel">
|
||||||
'p-1 bg-red-200 rounded-full text-red-700 hover:text-red-900',
|
<?php if ($episode->transcript_file): ?>
|
||||||
'data-toggle' => 'tooltip',
|
<div class="flex justify-between">
|
||||||
'data-placement' => 'bottom',
|
<?= anchor(
|
||||||
'title' => lang('Episode.form.transcript_delete'),
|
$episode->transcript_file_url,
|
||||||
],
|
icon('file', 'mr-2 text-gray-500') .
|
||||||
|
$episode->transcript_file,
|
||||||
|
[
|
||||||
|
'class' => 'inline-flex items-center text-xs',
|
||||||
|
'target' => '_blank',
|
||||||
|
'rel' => 'noreferrer noopener',
|
||||||
|
],
|
||||||
|
) .
|
||||||
|
anchor(
|
||||||
|
route_to(
|
||||||
|
'transcript-delete',
|
||||||
|
$podcast->id,
|
||||||
|
$episode->id,
|
||||||
|
),
|
||||||
|
icon('delete-bin', 'mx-auto'),
|
||||||
|
[
|
||||||
|
'class' =>
|
||||||
|
'p-1 bg-red-200 rounded-full text-red-700 hover:text-red-900',
|
||||||
|
'data-toggle' => 'tooltip',
|
||||||
|
'data-placement' => 'bottom',
|
||||||
|
'title' => lang(
|
||||||
|
'Episode.form.transcript_file_delete',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.transcript_file'),
|
||||||
|
'transcript_file',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.transcript_file'),
|
||||||
|
true,
|
||||||
) ?>
|
) ?>
|
||||||
</div>
|
<?= form_input([
|
||||||
<?php endif; ?>
|
'id' => 'transcript_file',
|
||||||
<?= form_input([
|
'name' => 'transcript_file',
|
||||||
'id' => 'transcript',
|
'class' => 'form-input',
|
||||||
'name' => 'transcript',
|
'type' => 'file',
|
||||||
'class' => 'form-input mb-4',
|
'accept' => '.txt,.html,.srt,.json',
|
||||||
'type' => 'file',
|
]) ?>
|
||||||
'accept' => '.txt,.html,.srt,.json',
|
</section>
|
||||||
]) ?>
|
<section id="transcript-file-remote-url" class="tab-panel">
|
||||||
</div>
|
<?= form_label(
|
||||||
<div class="flex flex-col flex-1">
|
lang('Episode.form.transcript_file_remote_url'),
|
||||||
<?= form_label(
|
'transcript_file_remote_url',
|
||||||
lang('Episode.form.chapters'),
|
['class' => 'sr-only'],
|
||||||
'chapters',
|
lang('Episode.form.transcript_file_remote_url'),
|
||||||
[],
|
true,
|
||||||
lang('Episode.form.chapters_hint'),
|
|
||||||
true,
|
|
||||||
) ?>
|
|
||||||
<?php if ($episode->chapters): ?>
|
|
||||||
<div class="flex justify-between">
|
|
||||||
<?= anchor(
|
|
||||||
$episode->chaptersUrl,
|
|
||||||
icon('file', 'mr-2') . $episode->chapters,
|
|
||||||
[
|
|
||||||
'class' => 'inline-flex items-center text-xs',
|
|
||||||
'target' => '_blank',
|
|
||||||
'rel' => 'noreferrer noopener',
|
|
||||||
],
|
|
||||||
) .
|
|
||||||
anchor(
|
|
||||||
route_to('chapters-delete', $podcast->id, $episode->id),
|
|
||||||
icon('delete-bin', 'mx-auto'),
|
|
||||||
[
|
|
||||||
'class' =>
|
|
||||||
'p-1 bg-red-200 rounded-full text-red-700 hover:text-red-900',
|
|
||||||
'data-toggle' => 'tooltip',
|
|
||||||
'data-placement' => 'bottom',
|
|
||||||
'title' => lang('Episode.form.chapters_delete'),
|
|
||||||
],
|
|
||||||
) ?>
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'transcript_file_remote_url',
|
||||||
|
'name' => 'transcript_file_remote_url',
|
||||||
|
'class' => 'form-input w-full',
|
||||||
|
'type' => 'url',
|
||||||
|
'placeholder' => 'https://...',
|
||||||
|
'value' => old(
|
||||||
|
'transcript_file_remote_url',
|
||||||
|
$episode->transcript_file_remote_url,
|
||||||
|
),
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?= form_fieldset_close() ?>
|
||||||
<?= form_input([
|
|
||||||
'id' => 'chapters',
|
<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?>
|
||||||
'name' => 'chapters',
|
<legend><?= lang('Episode.form.chapters') .
|
||||||
'class' => 'form-input mb-4',
|
'<small class="ml-1 lowercase">(' .
|
||||||
'type' => 'file',
|
lang('Common.optional') .
|
||||||
'accept' => '.json',
|
')</small>' .
|
||||||
]) ?>
|
hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?></legend>
|
||||||
</div>
|
<div class="mb-4 form-input-tabs">
|
||||||
|
<input type="radio" name="chapters-choice" id="chapters-file-upload-choice" aria-controls="chapters-file-upload-choice" value="upload-file" <?= !$episode->chapters_file_remote_url
|
||||||
|
? 'checked'
|
||||||
|
: '' ?> />
|
||||||
|
<label for="chapters-file-upload-choice"><?= lang(
|
||||||
|
'Common.forms.upload_file',
|
||||||
|
) ?></label>
|
||||||
|
|
||||||
|
<input type="radio" name="chapters-choice" id="chapters-file-remote-url-choice" aria-controls="chapters-file-remote-url-choice" value="remote-url" <?= $episode->chapters_file_remote_url
|
||||||
|
? 'checked'
|
||||||
|
: '' ?> />
|
||||||
|
<label for="chapters-file-remote-url-choice"><?= lang(
|
||||||
|
'Common.forms.remote_url',
|
||||||
|
) ?></label>
|
||||||
|
|
||||||
|
<div class="py-2 tab-panels">
|
||||||
|
<section id="chapters-file-upload" class="flex items-center tab-panel">
|
||||||
|
<?php if ($episode->chapters_file): ?>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<?= anchor(
|
||||||
|
$episode->chapters_file_url,
|
||||||
|
icon('file', 'mr-2') . $episode->chapters_file,
|
||||||
|
[
|
||||||
|
'class' => 'inline-flex items-center text-xs',
|
||||||
|
'target' => '_blank',
|
||||||
|
'rel' => 'noreferrer noopener',
|
||||||
|
],
|
||||||
|
) .
|
||||||
|
anchor(
|
||||||
|
route_to(
|
||||||
|
'chapters-delete',
|
||||||
|
$podcast->id,
|
||||||
|
$episode->id,
|
||||||
|
),
|
||||||
|
icon('delete-bin', 'mx-auto'),
|
||||||
|
[
|
||||||
|
'class' =>
|
||||||
|
'p-1 bg-red-200 rounded-full text-red-700 hover:text-red-900',
|
||||||
|
'data-toggle' => 'tooltip',
|
||||||
|
'data-placement' => 'bottom',
|
||||||
|
'title' => lang(
|
||||||
|
'Episode.form.chapters_file_delete',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.chapters_file'),
|
||||||
|
'chapters_file',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.chapters_file'),
|
||||||
|
true,
|
||||||
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'chapters_file',
|
||||||
|
'name' => 'chapters_file',
|
||||||
|
'class' => 'form-input',
|
||||||
|
'type' => 'file',
|
||||||
|
'accept' => '.json',
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
<section id="chapters-file-remote-url" class="tab-panel">
|
||||||
|
<?= form_label(
|
||||||
|
lang('Episode.form.chapters_file_remote_url'),
|
||||||
|
'chapters_file_remote_url',
|
||||||
|
['class' => 'sr-only'],
|
||||||
|
lang('Episode.form.chapters_file_remote_url'),
|
||||||
|
true,
|
||||||
|
) ?>
|
||||||
|
<?= form_input([
|
||||||
|
'id' => 'chapters_file_remote_url',
|
||||||
|
'name' => 'chapters_file_remote_url',
|
||||||
|
'class' => 'form-input w-full',
|
||||||
|
'type' => 'url',
|
||||||
|
'placeholder' => 'https://...',
|
||||||
|
'value' => old(
|
||||||
|
'chapters_file_remote_url',
|
||||||
|
$episode->chapters_file_remote_url,
|
||||||
|
),
|
||||||
|
]) ?>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?= form_fieldset_close() ?>
|
||||||
|
|
||||||
<?= form_section_close() ?>
|
<?= form_section_close() ?>
|
||||||
|
|
||||||
<?= form_section(
|
<?= form_section(
|
||||||
|
@ -107,12 +107,14 @@
|
|||||||
$episode->publication_status,
|
$episode->publication_status,
|
||||||
) ?>
|
) ?>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration($episode->enclosure_duration) ?>
|
<?= format_duration(
|
||||||
|
$episode->audio_file_duration,
|
||||||
|
) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source src="/<?= $episode->enclosure_media_path ?>" type="<?= $episode->enclosure_type ?>">
|
<source src="<?= $episode->audio_file_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
|
@ -62,15 +62,15 @@
|
|||||||
) ?>
|
) ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-gray-600">
|
<div class="text-xs text-gray-600">
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration($episode->enclosure_duration) ?>
|
<?= format_duration($episode->audio_file_duration) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source
|
<source
|
||||||
src="<?= $episode->enclosure_web_url ?>"
|
src="<?= $episode->audio_file_url ?>"
|
||||||
type="<?= $episode->enclosure_mimetype ?>">
|
type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,13 +78,13 @@
|
|||||||
]) ?>
|
]) ?>
|
||||||
</time>
|
</time>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration($episode->enclosure_duration) ?>
|
<?= format_duration($episode->audio_file_duration) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source src="<?= $episode->enclosure_web_url ?>" type="<?= $episode->enclosure_mimetype ?>">
|
<source src="<?= $episode->audio_file_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
|
|
||||||
<?= form_open_multipart(
|
<?= form_open_multipart(
|
||||||
route_to('episode-soundbites-edit', $podcast->id, $episode->id),
|
route_to('episode-soundbites-edit', $podcast->id, $episode->id),
|
||||||
['method' => 'post', 'class' => 'flex flex-col']
|
['method' => 'post', 'class' => 'flex flex-col'],
|
||||||
) ?>
|
) ?>
|
||||||
<?= csrf_field() ?>
|
<?= csrf_field() ?>
|
||||||
|
|
||||||
<?= form_section(
|
<?= form_section(
|
||||||
lang('Episode.soundbites_form.info_section_title'),
|
lang('Episode.soundbites_form.info_section_title'),
|
||||||
lang('Episode.soundbites_form.info_section_subtitle')
|
lang('Episode.soundbites_form.info_section_subtitle'),
|
||||||
) ?>
|
) ?>
|
||||||
|
|
||||||
<table class="w-full table-fixed">
|
<table class="w-full table-fixed">
|
||||||
@ -30,20 +30,20 @@
|
|||||||
lang('Episode.soundbites_form.start_time'),
|
lang('Episode.soundbites_form.start_time'),
|
||||||
'start_time',
|
'start_time',
|
||||||
[],
|
[],
|
||||||
lang('Episode.soundbites_form.start_time_hint')
|
lang('Episode.soundbites_form.start_time_hint'),
|
||||||
) ?></th>
|
) ?></th>
|
||||||
<th class="w-3/12 px-1 py-2"><?= form_label(
|
<th class="w-3/12 px-1 py-2"><?= form_label(
|
||||||
lang('Episode.soundbites_form.duration'),
|
lang('Episode.soundbites_form.duration'),
|
||||||
'duration',
|
'duration',
|
||||||
[],
|
[],
|
||||||
lang('Episode.soundbites_form.duration_hint')
|
lang('Episode.soundbites_form.duration_hint'),
|
||||||
) ?></th>
|
) ?></th>
|
||||||
<th class="w-7/12 px-1 py-2"><?= form_label(
|
<th class="w-7/12 px-1 py-2"><?= form_label(
|
||||||
lang('Episode.soundbites_form.label'),
|
lang('Episode.soundbites_form.label'),
|
||||||
'label',
|
'label',
|
||||||
[],
|
[],
|
||||||
lang('Episode.soundbites_form.label_hint'),
|
lang('Episode.soundbites_form.label_hint'),
|
||||||
true
|
true,
|
||||||
) ?></th>
|
) ?></th>
|
||||||
<th class="w-1/12 px-1 py-2"></th>
|
<th class="w-1/12 px-1 py-2"></th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
'data-soundbite-id' => $soundbite->id,
|
'data-soundbite-id' => $soundbite->id,
|
||||||
'required' => 'required',
|
'required' => 'required',
|
||||||
'min' => '0',
|
'min' => '0',
|
||||||
]
|
],
|
||||||
) ?></td>
|
) ?></td>
|
||||||
<td class="px-1 py-2 font-medium bg-white border border-light-blue-500"><?= form_input(
|
<td class="px-1 py-2 font-medium bg-white border border-light-blue-500"><?= form_input(
|
||||||
[
|
[
|
||||||
@ -75,7 +75,7 @@
|
|||||||
'data-soundbite-id' => $soundbite->id,
|
'data-soundbite-id' => $soundbite->id,
|
||||||
'required' => 'required',
|
'required' => 'required',
|
||||||
'min' => '0',
|
'min' => '0',
|
||||||
]
|
],
|
||||||
) ?></td>
|
) ?></td>
|
||||||
<td class="px-1 py-2 font-medium bg-white border border-light-blue-500"><?= form_input(
|
<td class="px-1 py-2 font-medium bg-white border border-light-blue-500"><?= form_input(
|
||||||
[
|
[
|
||||||
@ -83,7 +83,7 @@
|
|||||||
'name' => "soundbites_array[{$soundbite->id}][label]",
|
'name' => "soundbites_array[{$soundbite->id}][label]",
|
||||||
'class' => 'form-input w-full border-none',
|
'class' => 'form-input w-full border-none',
|
||||||
'value' => $soundbite->label,
|
'value' => $soundbite->label,
|
||||||
]
|
],
|
||||||
) ?></td>
|
) ?></td>
|
||||||
<td class="px-4 py-2"><?= icon_button(
|
<td class="px-4 py-2"><?= icon_button(
|
||||||
'play',
|
'play',
|
||||||
@ -96,7 +96,7 @@
|
|||||||
'data-soundbite-id' => $soundbite->id,
|
'data-soundbite-id' => $soundbite->id,
|
||||||
'data-soundbite-start-time' => $soundbite->start_time,
|
'data-soundbite-start-time' => $soundbite->start_time,
|
||||||
'data-soundbite-duration' => $soundbite->duration,
|
'data-soundbite-duration' => $soundbite->duration,
|
||||||
]
|
],
|
||||||
) ?>
|
) ?>
|
||||||
<?= icon_button(
|
<?= icon_button(
|
||||||
'delete-bin',
|
'delete-bin',
|
||||||
@ -105,10 +105,10 @@
|
|||||||
'soundbite-delete',
|
'soundbite-delete',
|
||||||
$podcast->id,
|
$podcast->id,
|
||||||
$episode->id,
|
$episode->id,
|
||||||
$soundbite->id
|
$soundbite->id,
|
||||||
),
|
),
|
||||||
['variant' => 'danger'],
|
['variant' => 'danger'],
|
||||||
[]
|
[],
|
||||||
) ?>
|
) ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -124,7 +124,7 @@
|
|||||||
'data-type' => 'soundbite-field',
|
'data-type' => 'soundbite-field',
|
||||||
'data-field-type' => 'start-time',
|
'data-field-type' => 'start-time',
|
||||||
'min' => '0',
|
'min' => '0',
|
||||||
]
|
],
|
||||||
) ?></td>
|
) ?></td>
|
||||||
<td class="px-1 py-4 font-medium bg-white border border-light-blue-500"><?= form_input(
|
<td class="px-1 py-4 font-medium bg-white border border-light-blue-500"><?= form_input(
|
||||||
[
|
[
|
||||||
@ -136,7 +136,7 @@
|
|||||||
'data-type' => 'soundbite-field',
|
'data-type' => 'soundbite-field',
|
||||||
'data-field-type' => 'duration',
|
'data-field-type' => 'duration',
|
||||||
'min' => '0',
|
'min' => '0',
|
||||||
]
|
],
|
||||||
) ?></td>
|
) ?></td>
|
||||||
<td class="px-1 py-4 font-medium bg-white border border-light-blue-500"><?= form_input(
|
<td class="px-1 py-4 font-medium bg-white border border-light-blue-500"><?= form_input(
|
||||||
[
|
[
|
||||||
@ -144,7 +144,7 @@
|
|||||||
'name' => 'soundbites_array[0][label]',
|
'name' => 'soundbites_array[0][label]',
|
||||||
'class' => 'form-input w-full border-none',
|
'class' => 'form-input w-full border-none',
|
||||||
'value' => old('label'),
|
'value' => old('label'),
|
||||||
]
|
],
|
||||||
) ?></td>
|
) ?></td>
|
||||||
<td class="px-4 py-2"><?= icon_button(
|
<td class="px-4 py-2"><?= icon_button(
|
||||||
'play',
|
'play',
|
||||||
@ -156,7 +156,7 @@
|
|||||||
'data-soundbite-id' => 0,
|
'data-soundbite-id' => 0,
|
||||||
'data-soundbite-start-time' => 0,
|
'data-soundbite-start-time' => 0,
|
||||||
'data-soundbite-duration' => 0,
|
'data-soundbite-duration' => 0,
|
||||||
]
|
],
|
||||||
) ?>
|
) ?>
|
||||||
|
|
||||||
|
|
||||||
@ -164,7 +164,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr><td colspan="3">
|
<tr><td colspan="3">
|
||||||
<audio controls preload="auto" class="w-full">
|
<audio controls preload="auto" class="w-full">
|
||||||
<source src="/<?= $episode->enclosure_media_path ?>" type="<?= $episode->enclosure_type ?>">
|
<source src="<?= $episode->audio_file_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</td><td class="px-4 py-2"><?= icon_button(
|
</td><td class="px-4 py-2"><?= icon_button(
|
||||||
@ -177,7 +177,7 @@
|
|||||||
'data-start-time-field-name' =>
|
'data-start-time-field-name' =>
|
||||||
'soundbites_array[0][start_time]',
|
'soundbites_array[0][start_time]',
|
||||||
'data-duration-field-name' => 'soundbites_array[0][duration]',
|
'data-duration-field-name' => 'soundbites_array[0][duration]',
|
||||||
]
|
],
|
||||||
) ?></td></tr>
|
) ?></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -189,7 +189,7 @@
|
|||||||
lang('Episode.soundbites_form.submit_edit'),
|
lang('Episode.soundbites_form.submit_edit'),
|
||||||
null,
|
null,
|
||||||
['variant' => 'primary'],
|
['variant' => 'primary'],
|
||||||
['type' => 'submit', 'class' => 'self-end']
|
['type' => 'submit', 'class' => 'self-end'],
|
||||||
) ?>
|
) ?>
|
||||||
|
|
||||||
<?= form_close() ?>
|
<?= form_close() ?>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
class="object-cover w-full"
|
class="object-cover w-full"
|
||||||
/>
|
/>
|
||||||
<audio controls preload="auto" class="w-full mb-6">
|
<audio controls preload="auto" class="w-full mb-6">
|
||||||
<source src="/<?= $episode->enclosure_media_path ?>" type="<?= $episode->enclosure_type ?>">
|
<source src="<?= $episode->audio_file_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
|
|
||||||
|
@ -50,11 +50,11 @@
|
|||||||
) ?>
|
) ?>
|
||||||
</a>
|
</a>
|
||||||
<audio controls preload="none" class="flex w-full mt-auto">
|
<audio controls preload="none" class="flex w-full mt-auto">
|
||||||
<source src="<?= $episode->enclosure_url .
|
<source src="<?= $episode->audio_file_analytics_url .
|
||||||
(isset($_SERVER['HTTP_REFERER'])
|
(isset($_SERVER['HTTP_REFERER'])
|
||||||
? '?_from=' .
|
? '?_from=' .
|
||||||
parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)
|
parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)
|
||||||
: '') ?>" type="<?= $episode->enclosure_type ?>" />
|
: '') ?>" type="<?= $episode->audio_file_mimetype ?>" />
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,15 +21,15 @@
|
|||||||
<?= lang('Common.mediumDate', [$episode->published_at]) ?>
|
<?= lang('Common.mediumDate', [$episode->published_at]) ?>
|
||||||
</time>
|
</time>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration($episode->enclosure_duration) ?>
|
<?= format_duration($episode->audio_file_duration) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source
|
<source
|
||||||
src="<?= $episode->enclosure_web_url ?>"
|
src="<?= $episode->audio_file_web_url ?>"
|
||||||
type="<?= $episode->enclosure_mimetype ?>">
|
type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
<meta property="og:description" content="$description" />
|
<meta property="og:description" content="$description" />
|
||||||
<meta property="article:published_time" content="<?= $episode->published_at ?>" />
|
<meta property="article:published_time" content="<?= $episode->published_at ?>" />
|
||||||
<meta property="article:modified_time" content="<?= $episode->updated_at ?>" />
|
<meta property="article:modified_time" content="<?= $episode->updated_at ?>" />
|
||||||
<meta property="og:audio" content="<?= $episode->enclosure_opengraph_url ?>" />
|
<meta property="og:audio" content="<?= $episode->audio_file_opengraph_url ?>" />
|
||||||
<meta property="og:audio:type" content="<?= $episode->enclosure_mimetype ?>" />
|
<meta property="og:audio:type" content="<?= $episode->audio_file_mimetype ?>" />
|
||||||
<link rel="alternate" type="application/json+oembed" href="<?= base_url(
|
<link rel="alternate" type="application/json+oembed" href="<?= base_url(
|
||||||
route_to('episode-oembed-json', $podcast->name, $episode->slug),
|
route_to('episode-oembed-json', $podcast->name, $episode->slug),
|
||||||
) ?>" title="<?= $episode->title ?> oEmbed json" />
|
) ?>" title="<?= $episode->title ?> oEmbed json" />
|
||||||
@ -67,8 +67,8 @@
|
|||||||
]) ?>
|
]) ?>
|
||||||
</time>
|
</time>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration($episode->enclosure_duration) ?>
|
<?= format_duration($episode->audio_file_duration) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2 space-x-4 text-sm">
|
<div class="mb-2 space-x-4 text-sm">
|
||||||
@ -150,7 +150,7 @@ data-placement="bottom" title="[<?= $person['full_name'] ?>] <?= $person[
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source src="<?= $episode->enclosure_web_url ?>" type="<?= $episode->enclosure_type ?>">
|
<source src="<?= $episode->audio_file_web_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</header>
|
</header>
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
<meta property="og:description" content="$description" />
|
<meta property="og:description" content="$description" />
|
||||||
<meta property="article:published_time" content="<?= $episode->published_at ?>" />
|
<meta property="article:published_time" content="<?= $episode->published_at ?>" />
|
||||||
<meta property="article:modified_time" content="<?= $episode->updated_at ?>" />
|
<meta property="article:modified_time" content="<?= $episode->updated_at ?>" />
|
||||||
<meta property="og:audio" content="<?= $episode->enclosure_opengraph_url ?>" />
|
<meta property="og:audio" content="<?= $episode->audio_file_opengraph_url ?>" />
|
||||||
<meta property="og:audio:type" content="<?= $episode->enclosure_mimetype ?>" />
|
<meta property="og:audio:type" content="<?= $episode->audio_file_mimetype ?>" />
|
||||||
<link rel="alternate" type="application/json+oembed" href="<?= base_url(
|
<link rel="alternate" type="application/json+oembed" href="<?= base_url(
|
||||||
route_to('episode-oembed-json', $podcast->name, $episode->slug),
|
route_to('episode-oembed-json', $podcast->name, $episode->slug),
|
||||||
) ?>" title="<?= $episode->title ?> oEmbed json" />
|
) ?>" title="<?= $episode->title ?> oEmbed json" />
|
||||||
@ -67,8 +67,8 @@
|
|||||||
]) ?>
|
]) ?>
|
||||||
</time>
|
</time>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration($episode->enclosure_duration) ?>
|
<?= format_duration($episode->audio_file_duration) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2 space-x-4 text-sm">
|
<div class="mb-2 space-x-4 text-sm">
|
||||||
@ -148,7 +148,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source src="<?= $episode->enclosure_web_url ?>" type="<?= $episode->enclosure_type ?>">
|
<source src="<?= $episode->audio_file_web_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</header>
|
</header>
|
||||||
|
@ -105,14 +105,14 @@
|
|||||||
]) ?>
|
]) ?>
|
||||||
</time>
|
</time>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration(
|
<?= format_duration(
|
||||||
$episode->enclosure_duration,
|
$episode->audio_file_duration,
|
||||||
) ?>
|
) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source src="<?= $episode->enclosure_web_url ?>" type="<?= $episode->enclosure_mimetype ?>">
|
<source src="<?= $episode->audio_file_web_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
@ -168,4 +168,5 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?= $this->endSection() ?>
|
<?= $this->endSection()
|
||||||
|
?>
|
||||||
|
@ -105,14 +105,14 @@
|
|||||||
]) ?>
|
]) ?>
|
||||||
</time>
|
</time>
|
||||||
<span class="mx-1">•</span>
|
<span class="mx-1">•</span>
|
||||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
<time datetime="PT<?= $episode->audio_file_duration ?>S">
|
||||||
<?= format_duration(
|
<?= format_duration(
|
||||||
$episode->enclosure_duration,
|
$episode->audio_file_duration,
|
||||||
) ?>
|
) ?>
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
<audio controls preload="none" class="w-full mt-auto">
|
<audio controls preload="none" class="w-full mt-auto">
|
||||||
<source src="<?= $episode->enclosure_web_url ?>" type="<?= $episode->enclosure_mimetype ?>">
|
<source src="<?= $episode->audio_file_web_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||||
Your browser does not support the audio tag.
|
Your browser does not support the audio tag.
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user