image: php:7.2-fpm
image: php:7.3-fpm
stages:
- bundle
......
# [1.0.0-alpha.55](https://code.podlibre.org/podlibre/castopod-host/compare/v1.0.0-alpha.54...v1.0.0-alpha.55) (2021-05-03)
### Features
* add remote_url alternative for transcript and chapters files ([3143c9a](https://code.podlibre.org/podlibre/castopod-host/commit/3143c9ad36e4cf1364205cf2be39c0c96f80fdd2))
# [1.0.0-alpha.54](https://code.podlibre.org/podlibre/castopod-host/compare/v1.0.0-alpha.53...v1.0.0-alpha.54) (2021-05-03)
......
......@@ -26,10 +26,10 @@ class Analytics extends AnalyticsBase
$this->gateway = config('App')->adminGateway . '/analytics';
}
public function getEnclosureUrl($enclosureUri)
public function getAudioFileUrl($audioFilePath)
{
helper('media');
return media_base_url($enclosureUri);
return media_base_url($audioFilePath);
}
}
......@@ -9,7 +9,7 @@
|
| NOTE: this constant is updated upon release with Continuous Integration.
*/
defined('CP_VERSION') || define('CP_VERSION', '1.0.0-alpha.54');
defined('CP_VERSION') || define('CP_VERSION', '1.0.0-alpha.55');
/*
| --------------------------------------------------------------------
......
......@@ -108,11 +108,12 @@ class Episode extends BaseController
public function attemptCreate()
{
$rules = [
'enclosure' => 'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]',
'audio_file' => 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]',
'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',
'chapters' => 'ext_in[chapters,json]|permit_empty',
'transcript_file' =>
'ext_in[transcript,txt,html,srt,json]|permit_empty',
'chapters_file' => 'ext_in[chapters,json]|permit_empty',
];
if (!$this->validate($rules)) {
......@@ -127,7 +128,7 @@ class Episode extends BaseController
'title' => $this->request->getPost('title'),
'slug' => $this->request->getPost('slug'),
'guid' => '',
'enclosure' => $this->request->getFile('enclosure'),
'audio_file' => $this->request->getFile('audio_file'),
'description_markdown' => $this->request->getPost('description'),
'image' => $this->request->getFile('image'),
'location' => $this->request->getPost('location_name'),
......@@ -151,6 +152,30 @@ class Episode extends BaseController
'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();
if (!($newEpisodeId = $episodeModel->insert($newEpisode, true))) {
......@@ -201,12 +226,13 @@ class Episode extends BaseController
public function attemptEdit()
{
$rules = [
'enclosure' =>
'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]|permit_empty',
'audio_file' =>
'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]|permit_empty',
'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',
'chapters' => 'ext_in[chapters,json]|permit_empty',
'transcript_file' =>
'ext_in[transcript_file,txt,html,srt,json]|permit_empty',
'chapters_file' => 'ext_in[chapters_file,json]|permit_empty',
];
if (!$this->validate($rules)) {
......@@ -240,21 +266,61 @@ class Episode extends BaseController
$this->episode->updated_by = user()->id;
$enclosure = $this->request->getFile('enclosure');
if ($enclosure->isValid()) {
$this->episode->enclosure = $enclosure;
$audioFile = $this->request->getFile('audio_file');
if ($audioFile) {
$this->episode->audio_file = $audioFile;
}
$image = $this->request->getFile('image');
if ($image) {
$this->episode->image = $image;
}
$transcript = $this->request->getFile('transcript');
if ($transcript->isValid()) {
$this->episode->transcript = $transcript;
$transcriptChoice = $this->request->getPost('transcript-choice');
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()) {
$this->episode->chapters = $chapters;
$chaptersChoice = $this->request->getPost('chapters-choice');
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();
......@@ -289,8 +355,8 @@ class Episode extends BaseController
public function transcriptDelete()
{
unlink($this->episode->transcript);
$this->episode->transcript_uri = null;
unlink($this->episode->transcript_file);
$this->episode->transcript_file_path = null;
$episodeModel = new EpisodeModel();
......@@ -306,8 +372,8 @@ class Episode extends BaseController
public function chaptersDelete()
{
unlink($this->episode->chapters);
$this->episode->chapters_uri = null;
unlink($this->episode->chapters_file);
$this->episode->chapters_file_path = null;
$episodeModel = new EpisodeModel();
......
......@@ -345,7 +345,7 @@ class PodcastImport extends BaseController
'guid' => empty($item->guid) ? null : $item->guid,
'title' => $item->title,
'slug' => $slug,
'enclosure' => download_file($item->enclosure->attributes()),
'audio_file' => download_file($item->enclosure->attributes()),
'description_markdown' => $converter->convert(
$itemDescriptionHtml,
),
......
......@@ -41,7 +41,7 @@ class AddPodcasts extends Migration
'description_html' => [
'type' => 'TEXT',
],
'image_uri' => [
'image_path' => [
'type' => 'VARCHAR',
'constraint' => 255,
],
......
......@@ -39,25 +39,25 @@ class AddEpisodes extends Migration
'type' => 'VARCHAR',
'constraint' => 191,
],
'enclosure_uri' => [
'audio_file_path' => [
'type' => 'VARCHAR',
'constraint' => 255,
],
'enclosure_duration' => [
'audio_file_duration' => [
'type' => 'INT',
'unsigned' => true,
'comment' => 'Playtime in seconds',
],
'enclosure_mimetype' => [
'audio_file_mimetype' => [
'type' => 'VARCHAR',
'constraint' => 255,
],
'enclosure_filesize' => [
'audio_file_size' => [
'type' => 'INT',
'unsigned' => true,
'comment' => 'File size in bytes',
],
'enclosure_headersize' => [
'audio_file_header_size' => [
'type' => 'INT',
'unsigned' => true,
'comment' => 'Header size in bytes',
......@@ -68,7 +68,7 @@ class AddEpisodes extends Migration
'description_html' => [
'type' => 'TEXT',
],
'image_uri' => [
'image_path' => [
'type' => 'VARCHAR',
'constraint' => 255,
'null' => true,
......@@ -80,16 +80,26 @@ class AddEpisodes extends Migration
'constraint' => 13,
'null' => true,
],
'transcript_uri' => [
'transcript_file_path' => [
'type' => 'VARCHAR',
'constraint' => 255,
'null' => true,
],
'chapters_uri' => [
'transcript_file_remote_url' => [
'type' => 'VARCHAR',
'constraint' => 512,
'null' => true,
],
'chapters_file_path' => [
'type' => 'VARCHAR',
'constraint' => 255,
'null' => true,
],
'chapters_file_remote_url' => [
'type' => 'VARCHAR',
'constraint' => 512,
'null' => true,
],
'parental_advisory' => [
'type' => 'ENUM',
'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.',
'null' => true,
],
'image_uri' => [
'image_path' => [
'type' => 'VARCHAR',
'constraint' => 255,
],
......
......@@ -13,6 +13,8 @@ use App\Models\SoundbiteModel;
use App\Models\EpisodePersonModel;
use App\Models\NoteModel;
use CodeIgniter\Entity;
use CodeIgniter\Files\Exceptions\FileNotFoundException;
use CodeIgniter\HTTP\Exceptions\HTTPException;
use CodeIgniter\I18n\Time;
use League\CommonMark\CommonMarkConverter;
......@@ -36,47 +38,37 @@ class Episode extends Entity
/**
* @var \CodeIgniter\Files\File
*/
protected $enclosure;
protected $audioFile;
/**
* @var \CodeIgniter\Files\File
*/
protected $transcript;
protected $transcript_file;
/**
* @var \CodeIgniter\Files\File
*/
protected $chapters;
protected $chapters_file;
/**
* @var string
*/
protected $enclosure_media_path;
protected $audio_file_url;
/**
* @var string
*/
protected $enclosure_url;
protected $audio_file_analytics_url;
/**
* @var string
*/
protected $enclosure_web_url;
protected $audio_file_web_url;
/**
* @var string
*/
protected $enclosure_opengraph_url;
/**
* @var string
*/
protected $transcript_url;
/**
* @var string
*/
protected $chapters_url;
protected $audio_file_opengraph_url;
/**
* @var \App\Entities\EpisodePerson[]
......@@ -132,17 +124,19 @@ class Episode extends Entity
'guid' => 'string',
'slug' => 'string',
'title' => 'string',
'enclosure_uri' => 'string',
'enclosure_duration' => 'integer',
'enclosure_mimetype' => 'string',
'enclosure_filesize' => 'integer',
'enclosure_headersize' => 'integer',
'audio_file_path' => 'string',
'audio_file_duration' => 'integer',
'audio_file_mimetype' => 'string',
'audio_file_size' => 'integer',
'audio_file_header_size' => 'integer',
'description_markdown' => 'string',
'description_html' => 'string',
'image_uri' => '?string',
'image_path' => '?string',
'image_mimetype' => '?string',
'transcript_uri' => '?string',
'chapters_uri' => '?string',
'transcript_file_path' => '?string',
'transcript_file_remote_url' => '?string',
'chapters_file_path' => '?string',
'chapters_file_remote_url' => '?string',
'parental_advisory' => '?string',
'number' => '?integer',
'season_number' => '?integer',
......@@ -176,13 +170,13 @@ class Episode extends Entity
// check whether the user has inputted an image and store
$this->attributes['image_mimetype'] = $image->getMimeType();
$this->attributes['image_uri'] = save_media(
$this->attributes['image_path'] = save_media(
$image,
'podcasts/' . $this->getPodcast()->name,
$this->attributes['slug'],
);
$this->image = new \App\Libraries\Image(
$this->attributes['image_uri'],
$this->attributes['image_path'],
$this->attributes['image_mimetype'],
);
$this->image->saveSizes();
......@@ -193,9 +187,9 @@ class Episode extends Entity
public function getImage(): \App\Libraries\Image
{
if ($image_uri = $this->attributes['image_uri']) {
if ($imagePath = $this->attributes['image_path']) {
return new \App\Libraries\Image(
$image_uri,
$imagePath,
$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 (
!empty($enclosure) &&
(!($enclosure instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
$enclosure->isValid())
!empty($audioFile) &&
(!($audioFile instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
$audioFile->isValid())
) {
helper(['media', 'id3']);
$enclosure_metadata = get_file_tags($enclosure);
$audio_metadata = get_file_tags($audioFile);
$this->attributes['enclosure_uri'] = save_media(
$enclosure,
$this->attributes['audio_file_path'] = save_media(
$audioFile,
'podcasts/' . $this->getPodcast()->name,
$this->attributes['slug'],
);
$this->attributes['enclosure_duration'] = round(
$enclosure_metadata['playtime_seconds'],
$this->attributes['audio_file_duration'] = round(
$audio_metadata['playtime_seconds'],
);
$this->attributes['enclosure_mimetype'] =
$enclosure_metadata['mime_type'];
$this->attributes['enclosure_filesize'] =
$enclosure_metadata['filesize'];
$this->attributes['enclosure_headersize'] =
$enclosure_metadata['avdataoffset'];
$this->attributes['audio_file_mimetype'] =
$audio_metadata['mime_type'];
$this->attributes['audio_file_size'] = $audio_metadata['filesize'];
$this->attributes['audio_file_header_size'] =
$audio_metadata['avdataoffset'];
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 (
!empty($transcript) &&
(!($transcript instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
$transcript->isValid())
!empty($transcriptFile) &&
(!(
$transcriptFile instanceof \CodeIgniter\HTTP\Files\UploadedFile
) ||
$transcriptFile->isValid())
) {
helper('media');
$this->attributes['transcript_uri'] = save_media(
$transcript,
$this->attributes['transcript_file_path'] = save_media(
$transcriptFile,
$this->getPodcast()->name,
$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 (
!empty($chapters) &&
(!($chapters instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
$chapters->isValid())
!empty($chaptersFile) &&
(!($chaptersFile instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
$chaptersFile->isValid())
) {
helper('media');
$this->attributes['chapters_uri'] = save_media(
$chapters,
$this->attributes['chapters_file_path'] = save_media(
$chaptersFile,
$this->getPodcast()->name,
$this->attributes['slug'] . '-chapters',
);
......@@ -288,87 +283,102 @@ class Episode extends Entity
return $this;
}
public function getEnclosure()
public function getAudioFile()
{
return new \CodeIgniter\Files\File($this->getEnclosureMediaPath());
}
helper('media');
public function getTranscript()
{
return $this->attributes['transcript_uri']
? new \CodeIgniter\Files\File($this->getTranscriptMediaPath())
: null;
return new \CodeIgniter\Files\File(media_path($this->audio_file_path));
}
public function getChapters()
public function getTranscriptFile()
{
return $this->attributes['chapters_uri']
? new \CodeIgniter\Files\File($this->getChaptersMediaPath())
: null;
}
if ($this->attributes['transcript_file_path']) {
helper('media');
public function getEnclosureMediaPath()
{
helper('media');
return new \CodeIgniter\Files\File(
media_path($this->attributes['transcript_file_path']),
);
}
return media_path($this->attributes['enclosure_uri']);
return null;
}
public function getTranscriptMediaPath()
public function getChaptersFile()
{
helper('media');
if ($this->attributes['chapters_file_path']) {
helper('media');
return new \CodeIgniter\Files\File(
media_path($this->attributes['chapters_file_path']),
);
}
return $this->attributes['transcript_uri']
? media_path($this->attributes['transcript_uri'])
: null;
return null;
}
public function getChaptersMediaPath()
public function getAudioFileUrl()
{
helper('media');
return $this->attributes['chapters_uri']
? media_path($this->attributes['chapters_uri'])
: null;
return media_url($this->audio_file_path);
}
public function getEnclosureUrl()
public function getAudioFileAnalyticsUrl()
{
helper('analytics');
return generate_episode_analytics_url(
$this->podcast_id,
$this->id,
$this->enclosure_uri,
$this->enclosure_duration,
$this->enclosure_filesize,
$this->enclosure_headersize,
$this->audio_file_path,
$this->audio_file_duration,
$this->audio_file_size,
$this->audio_file_header_size,
$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']
? base_url($this->getTranscriptMediaPath())
: null;
if ($this->attributes['transcript_file_path']) {
return media_url($this->attributes['transcript_file_path']);
} 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']
? base_url($this->getChaptersMediaPath())
: null;
if ($this->attributes['chapters_file_path']) {
return media_url($this->attributes['chapters_file_path']);
} else {
return $this->attributes['chapters_file_remote_url'];
}
}
/**
......
......@@ -22,7 +22,7 @@ class Person extends Entity
'full_name' => 'string',
'unique_name' => 'string',
'information_url' => '?string',
'image_uri' => 'string',
'image_path' => 'string',
'image_mimetype' => 'string',
'created_by' => 'integer',
'updated_by' => 'integer',
......@@ -40,13 +40,13 @@ class Person extends Entity
helper('media');
$this->attributes['image_mimetype'] = $image->getMimeType();
$this->attributes['image_uri'] = save_media(
$this->attributes['image_path'] = save_media(
$image,
'persons',
$this->attributes['unique_name'],
);
$this->image = new \App\Libraries\Image(
$this->attributes['image_uri'],
$this->attributes['image_path'],
$this->attributes['image_mimetype'],
);
$this->image->saveSizes();
......@@ -58,7 +58,7 @@ class Person extends Entity
public function getImage()
{
return new \App\Libraries\Image(
$this->attributes['image_uri'],
$this->attributes['image_path'],
$this->attributes['image_mimetype'],
);
}
......
......@@ -100,7 +100,7 @@ class Podcast extends Entity
'title' => 'string',
'description_markdown' => 'string',
'description_html' => 'string',
'image_uri' => 'string',
'image_path' => 'string',
'image_mimetype' => 'string',
'language_code' => 'string',
'category_id' => 'integer',
......@@ -161,14 +161,14 @@ class Podcast extends Entity
helper('media');
$this->attributes['image_mimetype'] = $image->getMimeType();
$this->attributes['image_uri'] = save_media(
$this->attributes['image_path'] = save_media(
$image,
'podcasts/' . $this->attributes['name'],
'cover',
);
$this->image = new \App\Libraries\Image(
$this->attributes['image_uri'],
$this->attributes['image_path'],
$this->attributes['image_mimetype'],
);
$this->image->saveSizes();
......@@ -180,7 +180,7 @@ class Podcast extends Entity
public function getImage()
{
return new \App\Libraries\Image(
$this->attributes['image_uri'],
$this->attributes['image_path'],
$this->attributes['image_mimetype'],
);
}
......
......@@ -36,13 +36,15 @@ function get_file_tags($file)
*
* @return UploadedFile
*/
function write_enclosure_tags($episode)
function write_audio_file_tags($episode)
{
helper('media');
$TextEncoding = 'UTF-8';
// Initialize getID3 tag-writing module
$tagwriter = new WriteTags();
$tagwriter->filename = $episode->enclosure_media_path;
$tagwriter->filename = media_path($episode->audio_file_path);
// set various options (optional)
$tagwriter->tagformats = ['id3v2.4'];
......
......@@ -12,15 +12,15 @@ use CodeIgniter\HTTP\ResponseInterface;
/**
* Saves a file to the corresponding podcast folder in `public/media`
*
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $file
* @param string $podcast_name
* @param string $file_name
* @param \CodeIgniter\HTTP\Files\UploadedFile|\CodeIgniter\Files\File $filePath
* @param string $folder
* @param string $fileName
*
* @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;
......@@ -30,9 +30,9 @@ function save_media($file, $folder, $mediaName)
}
// 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(
'url',
$episode->enclosure_url .
$episode->audio_file_analytics_url .
(empty($serviceSlug)
? ''
: '?_from=' . urlencode($serviceSlug)),
);
$enclosure->addAttribute('length', $episode->enclosure_filesize);
$enclosure->addAttribute('type', $episode->enclosure_mimetype);
$enclosure->addAttribute('length', $episode->audio_file_size);
$enclosure->addAttribute('type', $episode->audio_file_mimetype);
$item->addChild('guid', $episode->guid);
$item->addChild(
......@@ -290,7 +290,7 @@ function get_rss_feed($podcast, $serviceSlug = '')
);
$item->addChild(
'duration',
$episode->enclosure_duration,
$episode->audio_file_duration,
$itunes_namespace,
);
$item->addChild('link', $episode->link);
......@@ -318,17 +318,20 @@ function get_rss_feed($podcast, $serviceSlug = '')
);
$item->addChild('episodeType', $episode->type, $itunes_namespace);
if ($episode->transcript) {
if ($episode->transcript_file_url) {
$transcriptElement = $item->addChild(
'transcript',
null,
$podcast_namespace,
);
$transcriptElement->addAttribute('url', $episode->transcriptUrl);
$transcriptElement->addAttribute(
'url',
$episode->transcript_file_url,
);
$transcriptElement->addAttribute(
'type',
Mimes::guessTypeFromExtension(
pathinfo($episode->transcript_uri, PATHINFO_EXTENSION),
pathinfo($episode->transcript_file_url, PATHINFO_EXTENSION),
),
);
$transcriptElement->addAttribute(
......@@ -337,13 +340,13 @@ function get_rss_feed($podcast, $serviceSlug = '')
);
}
if ($episode->chapters) {
if ($episode->chapters_file_url) {
$chaptersElement = $item->addChild(
'chapters',
null,
$podcast_namespace,
);
$chaptersElement->addAttribute('url', $episode->chaptersUrl);
$chaptersElement->addAttribute('url', $episode->chapters_file_url);
$chaptersElement->addAttribute('type', 'application/json+chapters');
}
......
......@@ -31,5 +31,7 @@ return [
],
'image_size_hint' =>
'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' => [
'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.',
'enclosure' => 'Audio file',
'enclosure_hint' => 'Choose an .mp3 or .m4a audio file.',
'audio_file' => 'Audio file',
'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.',
'info_section_title' => 'Episode info',
'info_section_subtitle' => '',
'image' => 'Cover image',
......@@ -90,10 +90,14 @@ return [
'location_name_hint' => 'This can be a real or fictional location',
'transcript' => 'Transcript or closed captions',
'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_hint' => 'File should be in JSON Chapters Format.',
'chapters_delete' => 'Delete chapters',
'chapters_hint' => 'File must be in JSON Chapters format.',
'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_subtitle' =>
'If you need RSS tags that Castopod does not handle, set them here.',
......
......@@ -22,6 +22,6 @@ return [
'submit_edit' => 'Save',
],
'messages' => [
'createSuccess' => 'The page "{pageTitle}" was created successfully!',
'createSuccess' => 'The page {pageTitle} was created successfully!',
],
];
......@@ -31,5 +31,7 @@ return [
],
'image_size_hint' =>
'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' => [
'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.',
'enclosure' => 'Fichier audio',
'enclosure_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
'audio_file' => 'Fichier audio',
'audio_file_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
'info_section_title' => 'Informations épisode',
'info_section_subtitle' => '',
'image' => 'Image de couverture',
......@@ -91,10 +91,16 @@ return [
'transcript' => 'Transcription ou sous-titrage',
'transcript_hint' =>
'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_hint' => 'Le fichier doit être en "JSON Chapters Format".',
'chapters_delete' => 'Supprimer le chapitrage',
'chapters_hint' => 'Le fichier doit être en format “JSON Chapters”.',
'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_subtitle' =>
'Si vous avez besoin d’une balise que Castopod ne couvre pas, définissez-la ici.',
......