From 3143c9ad36e4cf1364205cf2be39c0c96f80fdd2 Mon Sep 17 00:00:00 2001 From: Yassine Doghri <yassine@doghri.fr> Date: Mon, 3 May 2021 17:39:58 +0000 Subject: [PATCH] feat: add remote_url alternative for transcript and chapters files --- .gitlab-ci.yml | 2 +- app/Config/Analytics.php | 4 +- app/Controllers/Admin/Episode.php | 108 +++++-- app/Controllers/Admin/PodcastImport.php | 2 +- .../2020-05-30-101500_add_podcasts.php | 2 +- .../2020-06-05-170000_add_episodes.php | 26 +- .../2020-12-25-120000_add_persons.php | 2 +- app/Entities/Episode.php | 220 +++++++------- app/Entities/Person.php | 8 +- app/Entities/Podcast.php | 8 +- app/Helpers/id3_helper.php | 6 +- app/Helpers/media_helper.php | 14 +- app/Helpers/rss_helper.php | 21 +- app/Language/en/Common.php | 2 + app/Language/en/Episode.php | 14 +- app/Language/en/Page.php | 2 +- app/Language/fr/Common.php | 2 + app/Language/fr/Episode.php | 16 +- app/Libraries/Analytics/Config/Analytics.php | 6 +- .../EpisodeAnalyticsController.php | 4 +- .../Analytics/Helpers/analytics_helper.php | 38 +-- app/Libraries/Image.php | 10 +- app/Models/EpisodeModel.php | 24 +- app/Models/PersonModel.php | 4 +- app/Models/PodcastModel.php | 4 +- app/Views/_assets/styles/formInputTabs.css | 36 +++ app/Views/_assets/styles/index.css | 1 + app/Views/_assets/styles/tabs.css | 4 +- app/Views/admin/episode/create.php | 165 ++++++++-- app/Views/admin/episode/edit.php | 284 ++++++++++++------ app/Views/admin/episode/list.php | 8 +- app/Views/admin/episode/publish.php | 8 +- app/Views/admin/episode/publish_edit.php | 6 +- app/Views/admin/episode/soundbites.php | 36 +-- app/Views/admin/episode/view.php | 2 +- app/Views/embeddable_player.php | 4 +- app/Views/podcast/_partials/episode_card.php | 8 +- app/Views/podcast/episode.php | 10 +- app/Views/podcast/episode_authenticated.php | 10 +- app/Views/podcast/episodes.php | 9 +- app/Views/podcast/episodes_authenticated.php | 6 +- 41 files changed, 752 insertions(+), 394 deletions(-) create mode 100644 app/Views/_assets/styles/formInputTabs.css diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 94f14a8101..6e1cc393fa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: php:7.2-fpm +image: php:7.3-fpm stages: - bundle diff --git a/app/Config/Analytics.php b/app/Config/Analytics.php index 4391703d4d..c349725297 100644 --- a/app/Config/Analytics.php +++ b/app/Config/Analytics.php @@ -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); } } diff --git a/app/Controllers/Admin/Episode.php b/app/Controllers/Admin/Episode.php index 01c8412f80..619f420ef0 100644 --- a/app/Controllers/Admin/Episode.php +++ b/app/Controllers/Admin/Episode.php @@ -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(); diff --git a/app/Controllers/Admin/PodcastImport.php b/app/Controllers/Admin/PodcastImport.php index daad6c4234..6a29326156 100644 --- a/app/Controllers/Admin/PodcastImport.php +++ b/app/Controllers/Admin/PodcastImport.php @@ -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, ), diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php index d052c278af..675fa83c5c 100644 --- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php +++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php @@ -41,7 +41,7 @@ class AddPodcasts extends Migration 'description_html' => [ 'type' => 'TEXT', ], - 'image_uri' => [ + 'image_path' => [ 'type' => 'VARCHAR', 'constraint' => 255, ], diff --git a/app/Database/Migrations/2020-06-05-170000_add_episodes.php b/app/Database/Migrations/2020-06-05-170000_add_episodes.php index 775e64c12d..cafca23779 100644 --- a/app/Database/Migrations/2020-06-05-170000_add_episodes.php +++ b/app/Database/Migrations/2020-06-05-170000_add_episodes.php @@ -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'], diff --git a/app/Database/Migrations/2020-12-25-120000_add_persons.php b/app/Database/Migrations/2020-12-25-120000_add_persons.php index f993360479..84b34ccf9a 100644 --- a/app/Database/Migrations/2020-12-25-120000_add_persons.php +++ b/app/Database/Migrations/2020-12-25-120000_add_persons.php @@ -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, ], diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php index d0cdf64296..338e987989 100644 --- a/app/Entities/Episode.php +++ b/app/Entities/Episode.php @@ -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']; + } } /** diff --git a/app/Entities/Person.php b/app/Entities/Person.php index 222aa56fbb..d6c9c50fdd 100644 --- a/app/Entities/Person.php +++ b/app/Entities/Person.php @@ -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'], ); } diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index db7af33717..740a0134ad 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -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'], ); } diff --git a/app/Helpers/id3_helper.php b/app/Helpers/id3_helper.php index 5046c72c46..ab0a567cf7 100644 --- a/app/Helpers/id3_helper.php +++ b/app/Helpers/id3_helper.php @@ -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']; diff --git a/app/Helpers/media_helper.php b/app/Helpers/media_helper.php index a7e2eb6926..cd71e3e608 100644 --- a/app/Helpers/media_helper.php +++ b/app/Helpers/media_helper.php @@ -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; } /** diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php index 112b4648a8..a49562cc98 100644 --- a/app/Helpers/rss_helper.php +++ b/app/Helpers/rss_helper.php @@ -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'); } diff --git a/app/Language/en/Common.php b/app/Language/en/Common.php index d2a5966c16..da350b4322 100644 --- a/app/Language/en/Common.php +++ b/app/Language/en/Common.php @@ -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', ], ]; diff --git a/app/Language/en/Episode.php b/app/Language/en/Episode.php index 83210875ed..5eaa06caae 100644 --- a/app/Language/en/Episode.php +++ b/app/Language/en/Episode.php @@ -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.', diff --git a/app/Language/en/Page.php b/app/Language/en/Page.php index 4ddf960222..cafd882084 100644 --- a/app/Language/en/Page.php +++ b/app/Language/en/Page.php @@ -22,6 +22,6 @@ return [ 'submit_edit' => 'Save', ], 'messages' => [ - 'createSuccess' => 'The page "{pageTitle}" was created successfully!', + 'createSuccess' => 'The page “{pageTitle}†was created successfully!', ], ]; diff --git a/app/Language/fr/Common.php b/app/Language/fr/Common.php index 48b599e0fd..8d466bf28d 100644 --- a/app/Language/fr/Common.php +++ b/app/Language/fr/Common.php @@ -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', ], ]; diff --git a/app/Language/fr/Episode.php b/app/Language/fr/Episode.php index a2989f6797..df4a5d90b2 100644 --- a/app/Language/fr/Episode.php +++ b/app/Language/fr/Episode.php @@ -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.', diff --git a/app/Libraries/Analytics/Config/Analytics.php b/app/Libraries/Analytics/Config/Analytics.php index fa5ff6a4f5..64a85b5d25 100644 --- a/app/Libraries/Analytics/Config/Analytics.php +++ b/app/Libraries/Analytics/Config/Analytics.php @@ -26,13 +26,13 @@ class Analytics extends BaseConfig ]; /** - * get the full enclosure url + * get the full audio file url * * @param string $filename * @return string */ - public function getEnclosureUrl(string $enclosureUri) + public function getAudioFileUrl(string $audioFilePath) { - return base_url($enclosureUri); + return base_url($audioFilePath); } } diff --git a/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php b/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php index 7e372d9ae9..b9a2cb4376 100644 --- a/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php +++ b/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php @@ -50,7 +50,7 @@ class EpisodeAnalyticsController extends Controller } // Add one hit to this episode: - public function hit($base64EpisodeData, ...$enclosureUri) + public function hit($base64EpisodeData, ...$audioFilePath) { $session = \Config\Services::session(); $session->start(); @@ -78,6 +78,6 @@ class EpisodeAnalyticsController extends Controller $serviceName, ); - return redirect()->to($this->config->getEnclosureUrl($enclosureUri)); + return redirect()->to($this->config->getAudioFileUrl($audioFilePath)); } } diff --git a/app/Libraries/Analytics/Helpers/analytics_helper.php b/app/Libraries/Analytics/Helpers/analytics_helper.php index a9fc7c5791..e18806a8af 100644 --- a/app/Libraries/Analytics/Helpers/analytics_helper.php +++ b/app/Libraries/Analytics/Helpers/analytics_helper.php @@ -30,15 +30,15 @@ if (!function_exists('base64_url_decode')) { 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. * * @param int $podcastId * @param int $episodeId - * @param string $enclosureUri - * @param int $enclosureDuration - * @param int $enclosureFilesize - * @param int $enclosureHeadersize + * @param string $audioFilePath + * @param int $audioFileDuration + * @param int $audioFileSize + * @param int $audioFileHeaderSize * @param \CodeIgniter\I18n\Time $publicationDate * * @return string @@ -47,10 +47,10 @@ if (!function_exists('generate_episode_analytics_url')) { function generate_episode_analytics_url( $podcastId, $episodeId, - $enclosureUri, - $enclosureDuration, - $enclosureFilesize, - $enclosureHeadersize, + $audioFilePath, + $audioFileDuration, + $audioFileFilesize, + $audioFileHeaderSize, $publicationDate ) { return url_to( @@ -61,22 +61,22 @@ if (!function_exists('generate_episode_analytics_url')) { $podcastId, $episodeId, // 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 longer than 60 seconds then it's enclosure_headersize + 60 seconds - $enclosureDuration <= 60 - ? $enclosureFilesize - : $enclosureHeadersize + + // - if file is shorter than 60sec, then it's audio_file_size + // - if file is longer than 60 seconds then it's audio_file_header_size + 60 seconds + $audioFileDuration <= 60 + ? $audioFileFilesize + : $audioFileHeaderSize + floor( - (($enclosureFilesize - $enclosureHeadersize) / - $enclosureDuration) * + (($audioFileFilesize - $audioFileHeaderSize) / + $audioFileDuration) * 60, ), - $enclosureFilesize, - $enclosureDuration, + $audioFileFilesize, + $audioFileDuration, strtotime($publicationDate), ), ), - $enclosureUri, + $audioFilePath, ); } } diff --git a/app/Libraries/Image.php b/app/Libraries/Image.php index c713393709..78a5c2ac7e 100644 --- a/app/Libraries/Image.php +++ b/app/Libraries/Image.php @@ -70,17 +70,17 @@ class Image */ public $id3_path; - public function __construct($originalUri, $mimetype) + public function __construct($originalPath, $mimetype) { helper('media'); - $originalPath = media_path($originalUri); + $originalMediaPath = media_path($originalPath); [ 'filename' => $filename, 'dirname' => $dirname, 'extension' => $extension, - ] = pathinfo($originalPath); + ] = pathinfo($originalMediaPath); // load images extensions from config $this->config = config('Images'); @@ -100,8 +100,8 @@ class Image $feed = $dirname . '/' . $filename . $feedExtension . '.' . $extension; $id3 = $dirname . '/' . $filename . $id3Extension . '.' . $extension; - $this->original_path = $originalPath; - $this->original_url = media_url($originalUri); + $this->original_path = $originalMediaPath; + $this->original_url = media_url($originalMediaPath); $this->thumbnail_path = $thumbnail; $this->thumbnail_url = base_url($thumbnail); $this->medium_path = $medium; diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index 8d36325bb0..9679d717c5 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -21,17 +21,19 @@ class EpisodeModel extends Model 'guid', 'title', 'slug', - 'enclosure_uri', - 'enclosure_duration', - 'enclosure_mimetype', - 'enclosure_filesize', - 'enclosure_headersize', + 'audio_file_path', + 'audio_file_duration', + 'audio_file_mimetype', + 'audio_file_size', + 'audio_file_header_size', 'description_markdown', 'description_html', - 'image_uri', + 'image_path', 'image_mimetype', - 'transcript_uri', - 'chapters_uri', + 'transcript_file_path', + 'transcript_file_remote_url', + 'chapters_file_path', + 'chapters_file_remote_url', 'parental_advisory', 'number', 'season_number', @@ -58,11 +60,13 @@ class EpisodeModel extends Model 'podcast_id' => 'required', 'title' => 'required', 'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]', - 'enclosure_uri' => 'required', + 'audio_file_path' => 'required', 'description_markdown' => 'required', 'number' => 'is_natural_no_zero|permit_empty', 'season_number' => 'is_natural_no_zero|permit_empty', 'type' => 'required', + 'transcript_file_remote_url' => 'valid_url|permit_empty', + 'chapters_file_remote_url' => 'valid_url|permit_empty', 'published_at' => 'valid_date|permit_empty', 'created_by' => 'required', 'updated_by' => 'required', @@ -268,7 +272,7 @@ class EpisodeModel extends Model is_array($data['id']) ? $data['id'][0] : $data['id'], ); - write_enclosure_tags($episode); + write_audio_file_tags($episode); return $data; } diff --git a/app/Models/PersonModel.php b/app/Models/PersonModel.php index fc19b3988d..41dee4f269 100644 --- a/app/Models/PersonModel.php +++ b/app/Models/PersonModel.php @@ -20,7 +20,7 @@ class PersonModel extends Model 'full_name', 'unique_name', 'information_url', - 'image_uri', + 'image_path', 'image_mimetype', 'created_by', 'updated_by', @@ -35,7 +35,7 @@ class PersonModel extends Model 'full_name' => 'required', 'unique_name' => 'required|regex_match[/^[a-z0-9\-]{1,191}$/]|is_unique[persons.unique_name,id,{id}]', - 'image_uri' => 'required', + 'image_path' => 'required', 'created_by' => 'required', 'updated_by' => 'required', ]; diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index a332f763c5..f8d79e00ab 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -25,7 +25,7 @@ class PodcastModel extends Model 'description_html', 'episode_description_footer_markdown', 'episode_description_footer_html', - 'image_uri', + 'image_path', 'image_mimetype', 'language_code', 'category_id', @@ -62,7 +62,7 @@ class PodcastModel extends Model 'name' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,191}$/]|is_unique[podcasts.name,id,{id}]', 'description_markdown' => 'required', - 'image_uri' => 'required', + 'image_path' => 'required', 'language_code' => 'required', 'category_id' => 'required', 'owner_email' => 'required|valid_email', diff --git a/app/Views/_assets/styles/formInputTabs.css b/app/Views/_assets/styles/formInputTabs.css new file mode 100644 index 0000000000..011d39a96e --- /dev/null +++ b/app/Views/_assets/styles/formInputTabs.css @@ -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; + } +} diff --git a/app/Views/_assets/styles/index.css b/app/Views/_assets/styles/index.css index eb98956f1e..b4b795a546 100644 --- a/app/Views/_assets/styles/index.css +++ b/app/Views/_assets/styles/index.css @@ -10,3 +10,4 @@ @import "./note.css"; @import "./tabs.css"; @import "./radioToggler.css"; +@import "./formInputTabs.css"; diff --git a/app/Views/_assets/styles/tabs.css b/app/Views/_assets/styles/tabs.css index 4414c5174e..f0f279b48b 100644 --- a/app/Views/_assets/styles/tabs.css +++ b/app/Views/_assets/styles/tabs.css @@ -7,7 +7,7 @@ @apply absolute -left-full; } - .tab-panel { + .tabset .tab-panel { @apply hidden; } @@ -31,7 +31,7 @@ @apply font-semibold opacity-100 text-pine-700; } - .tab-panels { + .tabset .tab-panels { @apply col-span-2 p-6; } } diff --git a/app/Views/admin/episode/create.php b/app/Views/admin/episode/create.php index 4d6061c924..883af9f72c 100644 --- a/app/Views/admin/episode/create.php +++ b/app/Views/admin/episode/create.php @@ -29,14 +29,14 @@ ) ?> <?= form_label( - lang('Episode.form.enclosure'), - 'enclosure', + lang('Episode.form.audio_file'), + 'audio_file', [], - lang('Episode.form.enclosure_hint'), + lang('Episode.form.audio_file_hint'), ) ?> <?= form_input([ - 'id' => 'enclosure', - 'name' => 'enclosure', + 'id' => 'audio_file', + 'name' => 'audio_file', 'class' => 'form-input mb-4', 'required' => 'required', 'type' => 'file', @@ -263,34 +263,133 @@ lang('Episode.form.additional_files_section_title'), lang('Episode.form.additional_files_section_subtitle'), ) ?> -<?= form_label( - lang('Episode.form.transcript'), - 'transcript', - [], - lang('Episode.form.transcript_hint'), - true, -) ?> -<?= form_input([ - 'id' => 'transcript', - 'name' => 'transcript', - 'class' => 'form-input mb-4', - 'type' => 'file', - 'accept' => '.txt,.html,.srt,.json', -]) ?> -<?= form_label( - lang('Episode.form.chapters'), - 'chapters', - [], - lang('Episode.form.chapters_hint'), - true, -) ?> -<?= form_input([ - 'id' => 'chapters', - 'name' => 'chapters', - 'class' => 'form-input mb-4', - 'type' => 'file', - 'accept' => '.json', -]) ?> + +<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?> + <legend><?= lang('Episode.form.transcript') . + '<small class="ml-1 lowercase">(' . + lang('Common.optional') . + ')</small>' . + hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend> + <div class="mb-4 form-input-tabs"> + <input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= old( + 'transcript-choice', + ) !== 'remote-url' + ? 'checked' + : '' ?> /> + <label for="transcript-file-upload-choice"><?= lang( + 'Common.forms.upload_file', + ) ?></label> + + <input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= old( + 'transcript-choice', + ) === 'remote-url' + ? 'checked' + : '' ?> /> + <label for="transcript-file-remote-url-choice"><?= lang( + 'Common.forms.remote_url', + ) ?></label> + + <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( diff --git a/app/Views/admin/episode/edit.php b/app/Views/admin/episode/edit.php index 7a75b95107..1965b0c68c 100644 --- a/app/Views/admin/episode/edit.php +++ b/app/Views/admin/episode/edit.php @@ -24,18 +24,26 @@ <?= form_section( 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( - lang('Episode.form.enclosure'), - 'enclosure', + lang('Episode.form.audio_file'), + 'audio_file', [], - lang('Episode.form.enclosure_hint'), + lang('Episode.form.audio_file_hint'), ) ?> <?= form_input([ - 'id' => 'enclosure', - 'name' => 'enclosure', + 'id' => 'audio_file', + 'name' => 'audio_file', 'class' => 'form-input mb-4', 'type' => 'file', 'accept' => '.mp3,.m4a', @@ -48,11 +56,7 @@ lang('Episode.form.image_hint'), true, ) ?> -<img - src="<?= $episode->image->thumbnail_url ?>" - alt="<?= $episode->title ?>" - class="object-cover w-32 h-32" -/> + <?= form_input([ 'id' => '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>â€', ]), ) ?> -<div class="flex flex-col flex-1"> -<?= form_label( - lang('Episode.form.transcript'), - 'transcript', - [], - lang('Episode.form.transcript_hint'), - true, -) ?> -<?php if ($episode->transcript): ?> - <div class="flex justify-between"> - <?= anchor( - $episode->transcriptUrl, - icon('file', 'mr-2') . $episode->transcript, - [ - '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_delete'), - ], + +<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?> + <legend><?= lang('Episode.form.transcript') . + '<small class="ml-1 lowercase">(' . + lang('Common.optional') . + ')</small>' . + hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend> + <div class="mb-4 form-input-tabs"> + <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 + ? 'checked' + : '' ?> /> + <label for="transcript-file-upload-choice"><?= lang( + 'Common.forms.upload_file', + ) ?></label> + + <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 + ? 'checked' + : '' ?> /> + <label for="transcript-file-remote-url-choice"><?= lang( + 'Common.forms.remote_url', + ) ?></label> + + <div class="py-2 tab-panels"> + <section id="transcript-file-upload" class="flex items-center tab-panel"> + <?php if ($episode->transcript_file): ?> + <div class="flex justify-between"> + <?= anchor( + $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, ) ?> + <?= 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', + $episode->transcript_file_remote_url, + ), + ]) ?> + </section> + </div> </div> -<?php endif; ?> -<?= form_input([ - 'id' => 'transcript', - 'name' => 'transcript', - 'class' => 'form-input mb-4', - 'type' => 'file', - 'accept' => '.txt,.html,.srt,.json', -]) ?> -</div> -<div class="flex flex-col flex-1"> -<?= form_label( - lang('Episode.form.chapters'), - 'chapters', - [], - 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_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" <?= !$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> -<?php endif; ?> -<?= form_input([ - 'id' => 'chapters', - 'name' => 'chapters', - 'class' => 'form-input mb-4', - 'type' => 'file', - 'accept' => '.json', -]) ?> -</div> +<?= form_fieldset_close() ?> + <?= form_section_close() ?> <?= form_section( diff --git a/app/Views/admin/episode/list.php b/app/Views/admin/episode/list.php index ef0650c250..d0f455d3ff 100644 --- a/app/Views/admin/episode/list.php +++ b/app/Views/admin/episode/list.php @@ -107,12 +107,14 @@ $episode->publication_status, ) ?> <span class="mx-1">•</span> - <time datetime="PT<?= $episode->enclosure_duration ?>S"> - <?= format_duration($episode->enclosure_duration) ?> + <time datetime="PT<?= $episode->audio_file_duration ?>S"> + <?= format_duration( + $episode->audio_file_duration, + ) ?> </time> </div> <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. </audio> </div> diff --git a/app/Views/admin/episode/publish.php b/app/Views/admin/episode/publish.php index f491092b3b..4cc1d7c71a 100644 --- a/app/Views/admin/episode/publish.php +++ b/app/Views/admin/episode/publish.php @@ -62,15 +62,15 @@ ) ?> </div> <div class="text-xs text-gray-600"> - <time datetime="PT<?= $episode->enclosure_duration ?>S"> - <?= format_duration($episode->enclosure_duration) ?> + <time datetime="PT<?= $episode->audio_file_duration ?>S"> + <?= format_duration($episode->audio_file_duration) ?> </time> </div> </a> <audio controls preload="none" class="w-full mt-auto"> <source - src="<?= $episode->enclosure_web_url ?>" - type="<?= $episode->enclosure_mimetype ?>"> + src="<?= $episode->audio_file_url ?>" + type="<?= $episode->audio_file_mimetype ?>"> Your browser does not support the audio tag. </audio> </div> diff --git a/app/Views/admin/episode/publish_edit.php b/app/Views/admin/episode/publish_edit.php index 64246aef0d..973dc5d546 100644 --- a/app/Views/admin/episode/publish_edit.php +++ b/app/Views/admin/episode/publish_edit.php @@ -78,13 +78,13 @@ ]) ?> </time> <span class="mx-1">•</span> - <time datetime="PT<?= $episode->enclosure_duration ?>S"> - <?= format_duration($episode->enclosure_duration) ?> + <time datetime="PT<?= $episode->audio_file_duration ?>S"> + <?= format_duration($episode->audio_file_duration) ?> </time> </div> </a> <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. </audio> </div> diff --git a/app/Views/admin/episode/soundbites.php b/app/Views/admin/episode/soundbites.php index 1a5ff48404..e4893e77a6 100644 --- a/app/Views/admin/episode/soundbites.php +++ b/app/Views/admin/episode/soundbites.php @@ -13,13 +13,13 @@ <?= form_open_multipart( route_to('episode-soundbites-edit', $podcast->id, $episode->id), - ['method' => 'post', 'class' => 'flex flex-col'] + ['method' => 'post', 'class' => 'flex flex-col'], ) ?> <?= csrf_field() ?> <?= form_section( 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"> @@ -30,20 +30,20 @@ lang('Episode.soundbites_form.start_time'), 'start_time', [], - lang('Episode.soundbites_form.start_time_hint') + lang('Episode.soundbites_form.start_time_hint'), ) ?></th> <th class="w-3/12 px-1 py-2"><?= form_label( lang('Episode.soundbites_form.duration'), 'duration', [], - lang('Episode.soundbites_form.duration_hint') + lang('Episode.soundbites_form.duration_hint'), ) ?></th> <th class="w-7/12 px-1 py-2"><?= form_label( lang('Episode.soundbites_form.label'), 'label', [], lang('Episode.soundbites_form.label_hint'), - true + true, ) ?></th> <th class="w-1/12 px-1 py-2"></th> </tr> @@ -62,7 +62,7 @@ 'data-soundbite-id' => $soundbite->id, 'required' => 'required', 'min' => '0', - ] + ], ) ?></td> <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, 'required' => 'required', 'min' => '0', - ] + ], ) ?></td> <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]", 'class' => 'form-input w-full border-none', 'value' => $soundbite->label, - ] + ], ) ?></td> <td class="px-4 py-2"><?= icon_button( 'play', @@ -96,7 +96,7 @@ 'data-soundbite-id' => $soundbite->id, 'data-soundbite-start-time' => $soundbite->start_time, 'data-soundbite-duration' => $soundbite->duration, - ] + ], ) ?> <?= icon_button( 'delete-bin', @@ -105,10 +105,10 @@ 'soundbite-delete', $podcast->id, $episode->id, - $soundbite->id + $soundbite->id, ), ['variant' => 'danger'], - [] + [], ) ?> </td> </tr> @@ -124,7 +124,7 @@ 'data-type' => 'soundbite-field', 'data-field-type' => 'start-time', 'min' => '0', - ] + ], ) ?></td> <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-field-type' => 'duration', 'min' => '0', - ] + ], ) ?></td> <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]', 'class' => 'form-input w-full border-none', 'value' => old('label'), - ] + ], ) ?></td> <td class="px-4 py-2"><?= icon_button( 'play', @@ -156,7 +156,7 @@ 'data-soundbite-id' => 0, 'data-soundbite-start-time' => 0, 'data-soundbite-duration' => 0, - ] + ], ) ?> @@ -164,7 +164,7 @@ </tr> <tr><td colspan="3"> <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. </audio> </td><td class="px-4 py-2"><?= icon_button( @@ -177,7 +177,7 @@ 'data-start-time-field-name' => 'soundbites_array[0][start_time]', 'data-duration-field-name' => 'soundbites_array[0][duration]', - ] + ], ) ?></td></tr> </tbody> </table> @@ -189,7 +189,7 @@ lang('Episode.soundbites_form.submit_edit'), null, ['variant' => 'primary'], - ['type' => 'submit', 'class' => 'self-end'] + ['type' => 'submit', 'class' => 'self-end'], ) ?> <?= form_close() ?> diff --git a/app/Views/admin/episode/view.php b/app/Views/admin/episode/view.php index cd90f1cc00..c5a0a88323 100644 --- a/app/Views/admin/episode/view.php +++ b/app/Views/admin/episode/view.php @@ -39,7 +39,7 @@ class="object-cover w-full" /> <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. </audio> diff --git a/app/Views/embeddable_player.php b/app/Views/embeddable_player.php index b9d9365a37..59fd77598d 100644 --- a/app/Views/embeddable_player.php +++ b/app/Views/embeddable_player.php @@ -50,11 +50,11 @@ ) ?> </a> <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']) ? '?_from=' . 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. </audio> </div> diff --git a/app/Views/podcast/_partials/episode_card.php b/app/Views/podcast/_partials/episode_card.php index a3bec75b23..c64e82bde1 100644 --- a/app/Views/podcast/_partials/episode_card.php +++ b/app/Views/podcast/_partials/episode_card.php @@ -21,15 +21,15 @@ <?= lang('Common.mediumDate', [$episode->published_at]) ?> </time> <span class="mx-1">•</span> - <time datetime="PT<?= $episode->enclosure_duration ?>S"> - <?= format_duration($episode->enclosure_duration) ?> + <time datetime="PT<?= $episode->audio_file_duration ?>S"> + <?= format_duration($episode->audio_file_duration) ?> </time> </div> </a> <audio controls preload="none" class="w-full mt-auto"> <source - src="<?= $episode->enclosure_web_url ?>" - type="<?= $episode->enclosure_mimetype ?>"> + src="<?= $episode->audio_file_web_url ?>" + type="<?= $episode->audio_file_mimetype ?>"> Your browser does not support the audio tag. </audio> </div> diff --git a/app/Views/podcast/episode.php b/app/Views/podcast/episode.php index 464e24415f..005e8cbf3e 100644 --- a/app/Views/podcast/episode.php +++ b/app/Views/podcast/episode.php @@ -17,8 +17,8 @@ <meta property="og:description" content="$description" /> <meta property="article:published_time" content="<?= $episode->published_at ?>" /> <meta property="article:modified_time" content="<?= $episode->updated_at ?>" /> -<meta property="og:audio" content="<?= $episode->enclosure_opengraph_url ?>" /> -<meta property="og:audio:type" content="<?= $episode->enclosure_mimetype ?>" /> +<meta property="og:audio" content="<?= $episode->audio_file_opengraph_url ?>" /> +<meta property="og:audio:type" content="<?= $episode->audio_file_mimetype ?>" /> <link rel="alternate" type="application/json+oembed" href="<?= base_url( route_to('episode-oembed-json', $podcast->name, $episode->slug), ) ?>" title="<?= $episode->title ?> oEmbed json" /> @@ -67,8 +67,8 @@ ]) ?> </time> <span class="mx-1">•</span> - <time datetime="PT<?= $episode->enclosure_duration ?>S"> - <?= format_duration($episode->enclosure_duration) ?> + <time datetime="PT<?= $episode->audio_file_duration ?>S"> + <?= format_duration($episode->audio_file_duration) ?> </time> </div> <div class="mb-2 space-x-4 text-sm"> @@ -150,7 +150,7 @@ data-placement="bottom" title="[<?= $person['full_name'] ?>] <?= $person[ </div> </div> <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. </audio> </header> diff --git a/app/Views/podcast/episode_authenticated.php b/app/Views/podcast/episode_authenticated.php index b8c4b90398..38ea9ab811 100644 --- a/app/Views/podcast/episode_authenticated.php +++ b/app/Views/podcast/episode_authenticated.php @@ -17,8 +17,8 @@ <meta property="og:description" content="$description" /> <meta property="article:published_time" content="<?= $episode->published_at ?>" /> <meta property="article:modified_time" content="<?= $episode->updated_at ?>" /> -<meta property="og:audio" content="<?= $episode->enclosure_opengraph_url ?>" /> -<meta property="og:audio:type" content="<?= $episode->enclosure_mimetype ?>" /> +<meta property="og:audio" content="<?= $episode->audio_file_opengraph_url ?>" /> +<meta property="og:audio:type" content="<?= $episode->audio_file_mimetype ?>" /> <link rel="alternate" type="application/json+oembed" href="<?= base_url( route_to('episode-oembed-json', $podcast->name, $episode->slug), ) ?>" title="<?= $episode->title ?> oEmbed json" /> @@ -67,8 +67,8 @@ ]) ?> </time> <span class="mx-1">•</span> - <time datetime="PT<?= $episode->enclosure_duration ?>S"> - <?= format_duration($episode->enclosure_duration) ?> + <time datetime="PT<?= $episode->audio_file_duration ?>S"> + <?= format_duration($episode->audio_file_duration) ?> </time> </div> <div class="mb-2 space-x-4 text-sm"> @@ -148,7 +148,7 @@ </div> </div> <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. </audio> </header> diff --git a/app/Views/podcast/episodes.php b/app/Views/podcast/episodes.php index 8e76c01f6e..5496241b6f 100644 --- a/app/Views/podcast/episodes.php +++ b/app/Views/podcast/episodes.php @@ -105,14 +105,14 @@ ]) ?> </time> <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, + $episode->audio_file_duration, ) ?> </time> </div> <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. </audio> </div> @@ -168,4 +168,5 @@ <?php endif; ?> </section> -<?= $this->endSection() ?> +<?= $this->endSection() +?> diff --git a/app/Views/podcast/episodes_authenticated.php b/app/Views/podcast/episodes_authenticated.php index 1d37f1a5b8..9f63b0cd08 100644 --- a/app/Views/podcast/episodes_authenticated.php +++ b/app/Views/podcast/episodes_authenticated.php @@ -105,14 +105,14 @@ ]) ?> </time> <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, + $episode->audio_file_duration, ) ?> </time> </div> <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. </audio> </div> -- GitLab