From dbba8dc58133967c778514268cbfed8098ed1dbc Mon Sep 17 00:00:00 2001 From: Benjamin Bellamy Date: Wed, 18 Nov 2020 17:17:56 +0000 Subject: [PATCH] feat(rss): add podcast-namespace tags for platforms + previousUrl tag - add podcast:id tag - add podcast:funding tag - add podcast:social tag - add podcast:previousUrl tag - add missing platforms with icons - update platforms table to include social and funding platforms - rename platform_links table to podcasts_platforms - move podcast import methods from podcast controller - update import functionality to insert platforms from rss closes #73, #75, #76, #80 --- app/Config/Routes.php | 62 ++-- app/Controllers/Admin/Podcast.php | 228 ------------- app/Controllers/Admin/PodcastImport.php | 307 ++++++++++++++++++ ...odcastSettings.php => PodcastPlatform.php} | 50 +-- app/Controllers/Platform.php | 24 ++ .../2020-06-05-190000_add_platforms.php | 26 +- ...20-06-08-160000_add_podcasts_platforms.php | 23 +- app/Database/Seeds/PlatformSeeder.php | 218 +++++++++++-- app/Entities/Platform.php | 5 +- app/Entities/Podcast.php | 73 ++++- app/Helpers/rss_helper.php | 65 ++++ app/Helpers/svg_helper.php | 4 +- app/Language/en/Breadcrumb.php | 17 +- app/Language/en/Platforms.php | 5 + app/Language/en/PodcastNavigation.php | 6 +- app/Language/fr/Breadcrumb.php | 17 +- app/Language/fr/Platforms.php | 5 + app/Language/fr/PodcastNavigation.php | 5 +- app/Models/PlatformModel.php | 146 ++++++--- app/Models/PodcastModel.php | 1 - app/Views/_assets/icons/add-box.svg | 1 + app/Views/_assets/icons/links.svg | 1 + app/Views/_assets/icons/upload.svg | 6 - .../_assets/images/platforms/_default.svg | 33 +- .../images/platforms/funding/liberapay.svg | 20 ++ .../images/platforms/funding/patreon.svg | 24 ++ .../images/platforms/funding/paypal.svg | 11 + .../images/platforms/funding/tipeee.svg | 14 + .../images/platforms/google-podcasts.svg | 14 - .../images/platforms/podcast-index.svg | 4 - .../images/platforms/podcasting/amazon.svg | 9 + .../apple.svg} | 0 .../platforms/{ => podcasting}/blubrry.svg | 0 .../platforms/{ => podcasting}/castbox.svg | 0 .../platforms/{ => podcasting}/castro.svg | 0 .../images/platforms/podcasting/chartable.svg | 5 + .../platforms/{ => podcasting}/deezer.svg | 0 .../images/platforms/podcasting/fyyd.svg | 6 + .../images/platforms/podcasting/google.svg | 14 + .../platforms/{ => podcasting}/ivoox.svg | 0 .../{ => podcasting}/listennotes.svg | 0 .../platforms/{ => podcasting}/overcast.svg | 0 .../platforms/{ => podcasting}/playerfm.svg | 0 .../{ => podcasting}/pocketcasts.svg | 0 .../platforms/{ => podcasting}/podbean.svg | 0 .../podcastaddict.svg} | 0 .../platforms/podcasting/podcastindex.svg | 4 + .../platforms/{ => podcasting}/podchaser.svg | 0 .../images/platforms/podcasting/podcloud.svg | 8 + .../platforms/podcasting/podinstall.svg | 4 + .../platforms/{ => podcasting}/podtail.svg | 0 .../images/platforms/podcasting/podverse.svg | 4 + .../{ => podcasting}/radiopublic.svg | 0 .../platforms/{ => podcasting}/spotify.svg | 0 .../platforms/{ => podcasting}/spreaker.svg | 0 .../platforms/{ => podcasting}/stitcher.svg | 0 .../platforms/{ => podcasting}/tunein.svg | 0 .../images/platforms/social/discord.svg | 1 + .../images/platforms/social/facebook.svg | 1 + .../images/platforms/social/instagram.svg | 1 + .../images/platforms/social/linkedin.svg | 1 + .../images/platforms/social/mastodon.svg | 1 + .../images/platforms/social/pixelfed.svg | 1 + .../_assets/images/platforms/social/slack.svg | 1 + .../images/platforms/social/twitch.svg | 1 + .../images/platforms/social/twitter.svg | 1 + .../images/platforms/social/youtube.svg | 1 + app/Views/admin/podcast/_sidebar.php | 10 +- .../podcast/{settings => }/platforms.php | 41 ++- app/Views/podcast.php | 56 +++- 70 files changed, 1121 insertions(+), 465 deletions(-) create mode 100644 app/Controllers/Admin/PodcastImport.php rename app/Controllers/Admin/{PodcastSettings.php => PodcastPlatform.php} (57%) create mode 100644 app/Controllers/Platform.php create mode 100644 app/Views/_assets/icons/add-box.svg create mode 100644 app/Views/_assets/icons/links.svg delete mode 100644 app/Views/_assets/icons/upload.svg create mode 100644 app/Views/_assets/images/platforms/funding/liberapay.svg create mode 100644 app/Views/_assets/images/platforms/funding/patreon.svg create mode 100644 app/Views/_assets/images/platforms/funding/paypal.svg create mode 100644 app/Views/_assets/images/platforms/funding/tipeee.svg delete mode 100644 app/Views/_assets/images/platforms/google-podcasts.svg delete mode 100644 app/Views/_assets/images/platforms/podcast-index.svg create mode 100644 app/Views/_assets/images/platforms/podcasting/amazon.svg rename app/Views/_assets/images/platforms/{apple-podcasts.svg => podcasting/apple.svg} (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/blubrry.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/castbox.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/castro.svg (100%) create mode 100644 app/Views/_assets/images/platforms/podcasting/chartable.svg rename app/Views/_assets/images/platforms/{ => podcasting}/deezer.svg (100%) create mode 100644 app/Views/_assets/images/platforms/podcasting/fyyd.svg create mode 100644 app/Views/_assets/images/platforms/podcasting/google.svg rename app/Views/_assets/images/platforms/{ => podcasting}/ivoox.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/listennotes.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/overcast.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/playerfm.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/pocketcasts.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/podbean.svg (100%) rename app/Views/_assets/images/platforms/{podcast-addict.svg => podcasting/podcastaddict.svg} (100%) create mode 100644 app/Views/_assets/images/platforms/podcasting/podcastindex.svg rename app/Views/_assets/images/platforms/{ => podcasting}/podchaser.svg (100%) create mode 100644 app/Views/_assets/images/platforms/podcasting/podcloud.svg create mode 100644 app/Views/_assets/images/platforms/podcasting/podinstall.svg rename app/Views/_assets/images/platforms/{ => podcasting}/podtail.svg (100%) create mode 100644 app/Views/_assets/images/platforms/podcasting/podverse.svg rename app/Views/_assets/images/platforms/{ => podcasting}/radiopublic.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/spotify.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/spreaker.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/stitcher.svg (100%) rename app/Views/_assets/images/platforms/{ => podcasting}/tunein.svg (100%) create mode 100644 app/Views/_assets/images/platforms/social/discord.svg create mode 100644 app/Views/_assets/images/platforms/social/facebook.svg create mode 100644 app/Views/_assets/images/platforms/social/instagram.svg create mode 100644 app/Views/_assets/images/platforms/social/linkedin.svg create mode 100644 app/Views/_assets/images/platforms/social/mastodon.svg create mode 100644 app/Views/_assets/images/platforms/social/pixelfed.svg create mode 100644 app/Views/_assets/images/platforms/social/slack.svg create mode 100644 app/Views/_assets/images/platforms/social/twitch.svg create mode 100644 app/Views/_assets/images/platforms/social/twitter.svg create mode 100644 app/Views/_assets/images/platforms/social/youtube.svg rename app/Views/admin/podcast/{settings => }/platforms.php (67%) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 1173388c..ada6c2c1 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -32,6 +32,7 @@ $routes->setAutoRoute(false); $routes->addPlaceholder('podcastName', '[a-zA-Z0-9\_]{1,191}'); $routes->addPlaceholder('slug', '[a-zA-Z0-9\-]{1,191}'); $routes->addPlaceholder('base64', '[A-Za-z0-9\.\_]+\-{0,2}'); +$routes->addPlaceholder('platformType', '\bpodcasting|\bsocial|\bfunding'); /** * -------------------------------------------------------------------- @@ -69,6 +70,8 @@ $routes->add('audio/(:base64)/(:any)', 'Analytics::hit/$1/$2', [ $routes->get('.well-known/unknown-useragents', 'UnknownUserAgents'); $routes->get('.well-known/unknown-useragents/(:num)', 'UnknownUserAgents/$1'); +$routes->get('.well-known/platforms', 'Platform'); + // Admin area $routes->group( config('App')->adminGateway, @@ -94,11 +97,11 @@ $routes->group( $routes->post('new', 'Podcast::attemptCreate', [ 'filter' => 'permission:podcasts-create', ]); - $routes->get('import', 'Podcast::import', [ + $routes->get('import', 'PodcastImport', [ 'as' => 'podcast-import', 'filter' => 'permission:podcasts-import', ]); - $routes->post('import', 'Podcast::attemptImport', [ + $routes->post('import', 'PodcastImport::attemptImport', [ 'filter' => 'permission:podcasts-import', ]); @@ -280,25 +283,44 @@ $routes->group( }); }); - $routes->group('settings', function ($routes) { - $routes->get('/', 'PodcastSettings/$1', [ - 'as' => 'podcast-settings', - ]); - $routes->get('platforms', 'PodcastSettings::platforms/$1', [ - 'as' => 'platforms', - 'filter' => 'permission:podcast-manage_platforms', - ]); - $routes->post( - 'platforms', - 'PodcastSettings::attemptPlatformsUpdate/$1', - ['filter' => 'permission:podcast-manage_platforms'] - ); - - $routes->add( - 'platforms/(:num)/remove-link', - 'PodcastSettings::removePlatformLink/$1/$2', + $routes->group('platforms', function ($routes) { + $routes->get( + '/', + 'PodcastPlatform::platforms/$1/podcasting', [ - 'as' => 'platforms-remove', + 'as' => 'platforms-podcasting', + 'filter' => 'permission:podcast-manage_platforms', + ] + ); + $routes->get( + 'social', + 'PodcastPlatform::platforms/$1/social', + [ + 'as' => 'platforms-social', + 'filter' => 'permission:podcast-manage_platforms', + ] + ); + $routes->get( + 'funding', + 'PodcastPlatform::platforms/$1/funding', + [ + 'as' => 'platforms-funding', + 'filter' => 'permission:podcast-manage_platforms', + ] + ); + $routes->post( + 'save/(:platformType)', + 'PodcastPlatform::attemptPlatformsUpdate/$1/$2', + [ + 'as' => 'platforms-save', + 'filter' => 'permission:podcast-manage_platforms', + ] + ); + $routes->add( + '(:slug)/podcast-platform-remove', + 'PodcastPlatform::removePodcastPlatform/$1/$2', + [ + 'as' => 'podcast-platform-remove', 'filter' => 'permission:podcast-manage_platforms', ] ); diff --git a/app/Controllers/Admin/Podcast.php b/app/Controllers/Admin/Podcast.php index 1e51120e..10c153a6 100644 --- a/app/Controllers/Admin/Podcast.php +++ b/app/Controllers/Admin/Podcast.php @@ -13,7 +13,6 @@ use App\Models\LanguageModel; use App\Models\PodcastModel; use App\Models\EpisodeModel; use Config\Services; -use League\HTMLToMarkdown\HtmlConverter; class Podcast extends BaseController { @@ -202,233 +201,6 @@ class Podcast extends BaseController return redirect()->route('podcast-view', [$newPodcastId]); } - public function import() - { - helper(['form', 'misc']); - - $languageOptions = (new LanguageModel())->getLanguageOptions(); - $categoryOptions = (new CategoryModel())->getCategoryOptions(); - - $data = [ - 'languageOptions' => $languageOptions, - 'categoryOptions' => $categoryOptions, - 'browserLang' => get_browser_language( - $this->request->getServer('HTTP_ACCEPT_LANGUAGE') - ), - ]; - - return view('admin/podcast/import', $data); - } - - public function attemptImport() - { - helper(['media', 'misc']); - - $rules = [ - 'imported_feed_url' => 'required|validate_url', - 'season_number' => 'is_natural_no_zero|permit_empty', - 'max_episodes' => 'is_natural_no_zero|permit_empty', - ]; - - if (!$this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - try { - $feed = simplexml_load_file( - $this->request->getPost('imported_feed_url') - ); - } catch (\ErrorException $ex) { - return redirect() - ->back() - ->withInput() - ->with('errors', [ - $ex->getMessage() . - ': ' . - $this->request->getPost('imported_feed_url') . - ' ⎋', - ]); - } - $nsItunes = $feed->channel[0]->children( - 'http://www.itunes.com/dtds/podcast-1.0.dtd' - ); - $nsPodcast = $feed->channel[0]->children( - 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md' - ); - - if ((string) $nsPodcast->locked === 'yes') { - return redirect() - ->back() - ->withInput() - ->with('errors', [lang('PodcastImport.lock_import')]); - } - - $converter = new HtmlConverter(); - - $channelDescriptionHtml = $feed->channel[0]->description; - - $podcast = new \App\Entities\Podcast([ - 'name' => $this->request->getPost('name'), - 'imported_feed_url' => $this->request->getPost('imported_feed_url'), - 'new_feed_url' => base_url( - route_to('podcast_feed', $this->request->getPost('name')) - ), - 'title' => $feed->channel[0]->title, - 'description_markdown' => $converter->convert( - $channelDescriptionHtml - ), - 'description_html' => $channelDescriptionHtml, - 'image' => download_file($nsItunes->image->attributes()), - 'language_code' => $this->request->getPost('language'), - 'category_id' => $this->request->getPost('category'), - 'parental_advisory' => empty($nsItunes->explicit) - ? null - : (in_array($nsItunes->explicit, ['yes', 'true']) - ? 'explicit' - : (in_array($nsItunes->explicit, ['no', 'false']) - ? 'clean' - : null)), - 'owner_name' => $nsItunes->owner->name, - 'owner_email' => $nsItunes->owner->email, - 'publisher' => $nsItunes->author, - 'type' => empty($nsItunes->type) ? 'episodic' : $nsItunes->type, - 'copyright' => $feed->channel[0]->copyright, - 'is_blocked' => empty($nsItunes->block) - ? false - : $nsItunes->block === 'yes', - 'is_completed' => empty($nsItunes->complete) - ? false - : $nsItunes->complete === 'yes', - 'created_by' => user(), - 'updated_by' => user(), - ]); - - $podcastModel = new PodcastModel(); - $db = \Config\Database::connect(); - - $db->transStart(); - - if (!($newPodcastId = $podcastModel->insert($podcast, true))) { - $db->transRollback(); - return redirect() - ->back() - ->withInput() - ->with('errors', $podcastModel->errors()); - } - - $authorize = Services::authorization(); - $podcastAdminGroup = $authorize->group('podcast_admin'); - - $podcastModel->addPodcastContributor( - user()->id, - $newPodcastId, - $podcastAdminGroup->id - ); - - $numberItems = $feed->channel[0]->item->count(); - $lastItem = - !empty($this->request->getPost('max_episodes')) && - $this->request->getPost('max_episodes') < $numberItems - ? $this->request->getPost('max_episodes') - : $numberItems; - - $slugs = []; - - // For each Episode: - for ($itemNumber = 1; $itemNumber <= $lastItem; $itemNumber++) { - $item = $feed->channel[0]->item[$numberItems - $itemNumber]; - - $nsItunes = $item->children( - 'http://www.itunes.com/dtds/podcast-1.0.dtd' - ); - - $slug = slugify( - $this->request->getPost('slug_field') === 'title' - ? $item->title - : basename($item->link) - ); - if (in_array($slug, $slugs)) { - $slugNumber = 2; - while (in_array($slug . '-' . $slugNumber, $slugs)) { - $slugNumber++; - } - $slug = $slug . '-' . $slugNumber; - } - $slugs[] = $slug; - - $itemDescriptionHtml = - $this->request->getPost('description_field') === 'summary' - ? $nsItunes->summary - : ($this->request->getPost('description_field') === - 'subtitle_summary' - ? $nsItunes->subtitle . '
' . $nsItunes->summary - : $item->description); - - $newEpisode = new \App\Entities\Episode([ - 'podcast_id' => $newPodcastId, - 'guid' => empty($item->guid) ? null : $item->guid, - 'title' => $item->title, - 'slug' => $slug, - 'enclosure' => download_file($item->enclosure->attributes()), - 'description_markdown' => $converter->convert( - $itemDescriptionHtml - ), - 'description_html' => $itemDescriptionHtml, - 'image' => - !$nsItunes->image || empty($nsItunes->image->attributes()) - ? null - : download_file($nsItunes->image->attributes()), - 'parental_advisory' => empty($nsItunes->explicit) - ? null - : (in_array($nsItunes->explicit, ['yes', 'true']) - ? 'explicit' - : (in_array($nsItunes->explicit, ['no', 'false']) - ? 'clean' - : null)), - 'number' => - $this->request->getPost('force_renumber') === 'yes' - ? $itemNumber - : (!empty($nsItunes->episode) - ? $nsItunes->episode - : null), - 'season_number' => empty( - $this->request->getPost('season_number') - ) - ? (!empty($nsItunes->season) - ? $nsItunes->season - : null) - : $this->request->getPost('season_number'), - 'type' => empty($nsItunes->episodeType) - ? 'full' - : $nsItunes->episodeType, - 'is_blocked' => empty($nsItunes->block) - ? false - : $nsItunes->block === 'yes', - 'created_by' => user(), - 'updated_by' => user(), - 'published_at' => strtotime($item->pubDate), - ]); - - $episodeModel = new EpisodeModel(); - - if (!$episodeModel->insert($newEpisode)) { - // FIXME: What shall we do? - return redirect() - ->back() - ->withInput() - ->with('errors', $episodeModel->errors()); - } - } - - $db->transComplete(); - - return redirect()->route('podcast-view', [$newPodcastId]); - } - public function edit() { helper('form'); diff --git a/app/Controllers/Admin/PodcastImport.php b/app/Controllers/Admin/PodcastImport.php new file mode 100644 index 00000000..c30ed390 --- /dev/null +++ b/app/Controllers/Admin/PodcastImport.php @@ -0,0 +1,307 @@ + 0) { + if ( + !($this->podcast = (new PodcastModel())->getPodcastById( + $params[0] + )) + ) { + throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); + } + } + + return $this->$method(); + } + + public function index() + { + helper(['form', 'misc']); + + $languageOptions = (new LanguageModel())->getLanguageOptions(); + $categoryOptions = (new CategoryModel())->getCategoryOptions(); + + $data = [ + 'languageOptions' => $languageOptions, + 'categoryOptions' => $categoryOptions, + 'browserLang' => get_browser_language( + $this->request->getServer('HTTP_ACCEPT_LANGUAGE') + ), + ]; + + return view('admin/podcast/import', $data); + } + + public function attemptImport() + { + helper(['media', 'misc']); + + $rules = [ + 'imported_feed_url' => 'required|validate_url', + 'season_number' => 'is_natural_no_zero|permit_empty', + 'max_episodes' => 'is_natural_no_zero|permit_empty', + ]; + + if (!$this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); + } + try { + $feed = simplexml_load_file( + $this->request->getPost('imported_feed_url') + ); + } catch (\ErrorException $ex) { + return redirect() + ->back() + ->withInput() + ->with('errors', [ + $ex->getMessage() . + ': ' . + $this->request->getPost('imported_feed_url') . + ' ⎋', + ]); + } + $nsItunes = $feed->channel[0]->children( + 'http://www.itunes.com/dtds/podcast-1.0.dtd' + ); + $nsPodcast = $feed->channel[0]->children( + 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md' + ); + + if ((string) $nsPodcast->locked === 'yes') { + return redirect() + ->back() + ->withInput() + ->with('errors', [lang('PodcastImport.lock_import')]); + } + + $converter = new HtmlConverter(); + + $channelDescriptionHtml = $feed->channel[0]->description; + + $podcast = new \App\Entities\Podcast([ + 'name' => $this->request->getPost('name'), + 'imported_feed_url' => $this->request->getPost('imported_feed_url'), + 'new_feed_url' => base_url( + route_to('podcast_feed', $this->request->getPost('name')) + ), + 'title' => $feed->channel[0]->title, + 'description_markdown' => $converter->convert( + $channelDescriptionHtml + ), + 'description_html' => $channelDescriptionHtml, + 'image' => download_file($nsItunes->image->attributes()), + 'language_code' => $this->request->getPost('language'), + 'category_id' => $this->request->getPost('category'), + 'parental_advisory' => empty($nsItunes->explicit) + ? null + : (in_array($nsItunes->explicit, ['yes', 'true']) + ? 'explicit' + : (in_array($nsItunes->explicit, ['no', 'false']) + ? 'clean' + : null)), + 'owner_name' => $nsItunes->owner->name, + 'owner_email' => $nsItunes->owner->email, + 'publisher' => $nsItunes->author, + 'type' => empty($nsItunes->type) ? 'episodic' : $nsItunes->type, + 'copyright' => $feed->channel[0]->copyright, + 'is_blocked' => empty($nsItunes->block) + ? false + : $nsItunes->block === 'yes', + 'is_completed' => empty($nsItunes->complete) + ? false + : $nsItunes->complete === 'yes', + 'created_by' => user(), + 'updated_by' => user(), + ]); + + $podcastModel = new PodcastModel(); + $db = \Config\Database::connect(); + + $db->transStart(); + + if (!($newPodcastId = $podcastModel->insert($podcast, true))) { + $db->transRollback(); + return redirect() + ->back() + ->withInput() + ->with('errors', $podcastModel->errors()); + } + + $authorize = Services::authorization(); + $podcastAdminGroup = $authorize->group('podcast_admin'); + + $podcastModel->addPodcastContributor( + user()->id, + $newPodcastId, + $podcastAdminGroup->id + ); + + $platformModel = new PlatformModel(); + $podcastsPlatformsData = []; + foreach ($nsPodcast->id as $podcastingPlatform) { + $slug = $podcastingPlatform->attributes()['platform']; + $platformModel->getOrCreatePlatform($slug, 'podcasting'); + array_push($podcastsPlatformsData, [ + 'platform_slug' => $slug, + 'podcast_id' => $newPodcastId, + 'link_url' => $podcastingPlatform->attributes()['url'], + 'link_content' => $podcastingPlatform->attributes()['id'], + 'is_visible' => false, + ]); + } + foreach ($nsPodcast->social as $socialPlatform) { + $slug = $socialPlatform->attributes()['platform']; + $platformModel->getOrCreatePlatform($slug, 'social'); + array_push($podcastsPlatformsData, [ + 'platform_slug' => $socialPlatform->attributes()['platform'], + 'podcast_id' => $newPodcastId, + 'link_url' => $socialPlatform->attributes()['url'], + 'link_content' => $socialPlatform, + 'is_visible' => false, + ]); + } + foreach ($nsPodcast->funding as $fundingPlatform) { + $slug = $fundingPlatform->attributes()['platform']; + $platformModel->getOrCreatePlatform($slug, 'funding'); + array_push($podcastsPlatformsData, [ + 'platform_slug' => $fundingPlatform->attributes()['platform'], + 'podcast_id' => $newPodcastId, + 'link_url' => $fundingPlatform->attributes()['url'], + 'link_content' => $fundingPlatform->attributes()['id'], + 'is_visible' => false, + ]); + } + $platformModel->createPodcastPlatforms( + $newPodcastId, + $podcastsPlatformsData + ); + + $numberItems = $feed->channel[0]->item->count(); + $lastItem = + !empty($this->request->getPost('max_episodes')) && + $this->request->getPost('max_episodes') < $numberItems + ? $this->request->getPost('max_episodes') + : $numberItems; + + $slugs = []; + + // For each Episode: + for ($itemNumber = 1; $itemNumber <= $lastItem; $itemNumber++) { + $item = $feed->channel[0]->item[$numberItems - $itemNumber]; + + $nsItunes = $item->children( + 'http://www.itunes.com/dtds/podcast-1.0.dtd' + ); + + $slug = slugify( + $this->request->getPost('slug_field') === 'title' + ? $item->title + : basename($item->link) + ); + if (in_array($slug, $slugs)) { + $slugNumber = 2; + while (in_array($slug . '-' . $slugNumber, $slugs)) { + $slugNumber++; + } + $slug = $slug . '-' . $slugNumber; + } + $slugs[] = $slug; + + $itemDescriptionHtml = + $this->request->getPost('description_field') === 'summary' + ? $nsItunes->summary + : ($this->request->getPost('description_field') === + 'subtitle_summary' + ? $nsItunes->subtitle . '
' . $nsItunes->summary + : $item->description); + + $newEpisode = new \App\Entities\Episode([ + 'podcast_id' => $newPodcastId, + 'guid' => empty($item->guid) ? null : $item->guid, + 'title' => $item->title, + 'slug' => $slug, + 'enclosure' => download_file($item->enclosure->attributes()), + 'description_markdown' => $converter->convert( + $itemDescriptionHtml + ), + 'description_html' => $itemDescriptionHtml, + 'image' => + !$nsItunes->image || empty($nsItunes->image->attributes()) + ? null + : download_file($nsItunes->image->attributes()), + 'parental_advisory' => empty($nsItunes->explicit) + ? null + : (in_array($nsItunes->explicit, ['yes', 'true']) + ? 'explicit' + : (in_array($nsItunes->explicit, ['no', 'false']) + ? 'clean' + : null)), + 'number' => + $this->request->getPost('force_renumber') === 'yes' + ? $itemNumber + : (!empty($nsItunes->episode) + ? $nsItunes->episode + : null), + 'season_number' => empty( + $this->request->getPost('season_number') + ) + ? (!empty($nsItunes->season) + ? $nsItunes->season + : null) + : $this->request->getPost('season_number'), + 'type' => empty($nsItunes->episodeType) + ? 'full' + : $nsItunes->episodeType, + 'is_blocked' => empty($nsItunes->block) + ? false + : $nsItunes->block === 'yes', + 'created_by' => user(), + 'updated_by' => user(), + 'published_at' => strtotime($item->pubDate), + ]); + + $episodeModel = new EpisodeModel(); + + if (!$episodeModel->insert($newEpisode)) { + // FIXME: What shall we do? + return redirect() + ->back() + ->withInput() + ->with('errors', $episodeModel->errors()); + } + } + + $db->transComplete(); + + return redirect()->route('podcast-view', [$newPodcastId]); + } +} diff --git a/app/Controllers/Admin/PodcastSettings.php b/app/Controllers/Admin/PodcastPlatform.php similarity index 57% rename from app/Controllers/Admin/PodcastSettings.php rename to app/Controllers/Admin/PodcastPlatform.php index 9beabef1..9229cbd0 100644 --- a/app/Controllers/Admin/PodcastSettings.php +++ b/app/Controllers/Admin/PodcastPlatform.php @@ -12,7 +12,7 @@ use App\Models\PlatformModel; use App\Models\PodcastModel; use Config\Services; -class PodcastSettings extends BaseController +class PodcastPlatform extends BaseController { /** * @var \App\Entities\Podcast|null @@ -33,46 +33,53 @@ class PodcastSettings extends BaseController public function index() { - return view('admin/podcast/settings/dashboard'); + return view('admin/podcast/platforms/dashboard'); } - public function platforms() + public function platforms($platformType) { helper('form'); $data = [ 'podcast' => $this->podcast, + 'platformType' => $platformType, 'platforms' => (new PlatformModel())->getPlatformsWithLinks( - $this->podcast->id + $this->podcast->id, + $platformType ), ]; replace_breadcrumb_params([0 => $this->podcast->title]); - return view('admin/podcast/settings/platforms', $data); + return view('admin/podcast/platforms', $data); } - public function attemptPlatformsUpdate() + public function attemptPlatformsUpdate($platformType) { $platformModel = new PlatformModel(); $validation = Services::validation(); - $platformLinksData = []; + $podcastsPlatformsData = []; + foreach ( $this->request->getPost('platforms') - as $platformName => $platformLink + as $platformSlug => $podcastPlatform ) { - $platformLinkUrl = $platformLink['url']; + $podcastPlatformUrl = $podcastPlatform['url']; + if ( - !empty($platformLinkUrl) && - $validation->check($platformLinkUrl, 'validate_url') + !empty($podcastPlatformUrl) && + $validation->check($podcastPlatformUrl, 'validate_url') ) { - $platformId = $platformModel->getPlatformId($platformName); - array_push($platformLinksData, [ - 'platform_id' => $platformId, + array_push($podcastsPlatformsData, [ + 'platform_slug' => $platformSlug, 'podcast_id' => $this->podcast->id, - 'link_url' => $platformLinkUrl, - 'is_visible' => array_key_exists('visible', $platformLink) - ? $platformLink['visible'] == 'yes' + 'link_url' => $podcastPlatformUrl, + 'link_content' => $podcastPlatform['content'], + 'is_visible' => array_key_exists( + 'visible', + $podcastPlatform + ) + ? $podcastPlatform['visible'] == 'yes' : false, ]); } @@ -80,7 +87,8 @@ class PodcastSettings extends BaseController $platformModel->savePodcastPlatforms( $this->podcast->id, - $platformLinksData + $platformType, + $podcastsPlatformsData ); return redirect() @@ -88,11 +96,11 @@ class PodcastSettings extends BaseController ->with('message', lang('Platforms.messages.updateSuccess')); } - public function removePlatformLink($platformId) + public function removePodcastPlatform($platformSlug) { - (new PlatformModel())->removePlatformLink( + (new PlatformModel())->removePodcastPlatform( $this->podcast->id, - $platformId + $platformSlug ); return redirect() diff --git a/app/Controllers/Platform.php b/app/Controllers/Platform.php new file mode 100644 index 00000000..cca77114 --- /dev/null +++ b/app/Controllers/Platform.php @@ -0,0 +1,24 @@ +response->setJSON($model->getPlatforms()); + } +} diff --git a/app/Database/Migrations/2020-06-05-190000_add_platforms.php b/app/Database/Migrations/2020-06-05-190000_add_platforms.php index 6fbcc032..bbb231e9 100644 --- a/app/Database/Migrations/2020-06-05-190000_add_platforms.php +++ b/app/Database/Migrations/2020-06-05-190000_add_platforms.php @@ -18,15 +18,13 @@ class AddPlatforms extends Migration public function up() { $this->forge->addField([ - 'id' => [ - 'type' => 'INT', - 'unsigned' => true, - 'auto_increment' => true, - ], - 'name' => [ + 'slug' => [ 'type' => 'VARCHAR', 'constraint' => 32, - 'unique' => true, + ], + 'type' => [ + 'type' => 'ENUM', + 'constraint' => ['podcasting', 'social', 'funding'], ], 'label' => [ 'type' => 'VARCHAR', @@ -42,14 +40,14 @@ class AddPlatforms extends Migration 'null' => true, 'default' => null, ], - 'created_at' => [ - 'type' => 'DATETIME', - ], - 'updated_at' => [ - 'type' => 'DATETIME', - ], ]); - $this->forge->addKey('id', true); + $this->forge->addField( + '`created_at` timestamp NOT NULL DEFAULT current_timestamp()' + ); + $this->forge->addField( + '`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()' + ); + $this->forge->addKey('slug', true); $this->forge->createTable('platforms'); } diff --git a/app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php b/app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php index da9a15b1..c353a5d7 100644 --- a/app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php +++ b/app/Database/Migrations/2020-06-08-160000_add_podcasts_platforms.php @@ -1,8 +1,8 @@ 'INT', 'unsigned' => true, ], - 'platform_id' => [ - 'type' => 'INT', - 'unsigned' => true, + 'platform_slug' => [ + 'type' => 'VARCHAR', + 'constraint' => 32, ], 'link_url' => [ 'type' => 'VARCHAR', 'constraint' => 512, ], + 'link_content' => [ + 'type' => 'VARCHAR', + 'constraint' => 128, + 'null' => true, + ], 'is_visible' => [ 'type' => 'TINYINT', 'constraint' => 1, @@ -43,14 +48,14 @@ class AddPodcastsPlatforms extends Migration ], ]); - $this->forge->addPrimaryKey(['podcast_id', 'platform_id']); + $this->forge->addPrimaryKey(['podcast_id', 'platform_slug']); $this->forge->addForeignKey('podcast_id', 'podcasts', 'id'); - $this->forge->addForeignKey('platform_id', 'platforms', 'id'); - $this->forge->createTable('platform_links'); + $this->forge->addForeignKey('platform_slug', 'platforms', 'slug'); + $this->forge->createTable('podcasts_platforms'); } public function down() { - $this->forge->dropTable('platform_links'); + $this->forge->dropTable('podcasts_platforms'); } } diff --git a/app/Database/Seeds/PlatformSeeder.php b/app/Database/Seeds/PlatformSeeder.php index 2257f949..b645810e 100644 --- a/app/Database/Seeds/PlatformSeeder.php +++ b/app/Database/Seeds/PlatformSeeder.php @@ -19,135 +19,303 @@ class PlatformSeeder extends Seeder { $data = [ [ - 'name' => 'apple-podcasts', + 'slug' => 'amazon', + 'type' => 'podcasting', + 'label' => 'Amazon Music and Audible', + 'home_url' => 'https://music.amazon.com/podcasts', + 'submit_url' => 'http://amazon.com/podcasters', + ], + [ + 'slug' => 'apple', + 'type' => 'podcasting', 'label' => 'Apple Podcasts', 'home_url' => 'https://www.apple.com/itunes/podcasts/', 'submit_url' => 'https://podcastsconnect.apple.com/my-podcasts/new-feed', ], [ - 'name' => 'blubrry', + 'slug' => 'blubrry', + 'type' => 'podcasting', 'label' => 'Blubrry', 'home_url' => 'https://www.blubrry.com/', 'submit_url' => 'https://www.blubrry.com/addpodcast.php', ], [ - 'name' => 'castbox', + 'slug' => 'castbox', + 'type' => 'podcasting', 'label' => 'Castbox', 'home_url' => 'https://castbox.fm/', 'submit_url' => 'https://helpcenter.castbox.fm/portal/kb/articles/submit-my-podcast', ], [ - 'name' => 'castro', + 'slug' => 'castro', + 'type' => 'podcasting', 'label' => 'Castro', 'home_url' => 'http://castro.fm/', - 'submit_url' => null, + 'submit_url' => + 'https://castro.fm/support/link-to-your-podcast-in-castro', ], [ - 'name' => 'deezer', + 'slug' => 'chartable', + 'type' => 'podcasting', + 'label' => 'Chartable', + 'home_url' => 'https://chartable.com/', + 'submit_url' => 'https://chartable.com/podcasts/submit', + ], + [ + 'slug' => 'deezer', + 'type' => 'podcasting', 'label' => 'Deezer', 'home_url' => 'https://www.deezer.com/', 'submit_url' => 'https://podcasters.deezer.com/submission', ], [ - 'name' => 'google-podcasts', + 'slug' => 'fyyd', + 'type' => 'podcasting', + 'label' => 'fyyd', + 'home_url' => 'https://fyyd.de/', + 'submit_url' => 'https://fyyd.de/add-feed', + ], + + [ + 'slug' => 'google', + 'type' => 'podcasting', 'label' => 'Google Podcasts', 'home_url' => 'https://podcasts.google.com/about', 'submit_url' => 'https://search.google.com/search-console/about', ], [ - 'name' => 'ivoox', + 'slug' => 'ivoox', + 'type' => 'podcasting', 'label' => 'Ivoox', 'home_url' => 'https://www.ivoox.com/', - 'submit_url' => null, + 'submit_url' => 'http://www.ivoox.com/upload-podcast_u.html', ], [ - 'name' => 'listennotes', + 'slug' => 'listennotes', + 'type' => 'podcasting', 'label' => 'ListenNotes', 'home_url' => 'https://www.listennotes.com/', 'submit_url' => 'https://www.listennotes.com/submit/', ], [ - 'name' => 'overcast', + 'slug' => 'overcast', + 'type' => 'podcasting', 'label' => 'Overcast', 'home_url' => 'https://overcast.fm/', 'submit_url' => 'https://overcast.fm/podcasterinfo', ], [ - 'name' => 'playerfm', + 'slug' => 'playerfm', + 'type' => 'podcasting', 'label' => 'Player.Fm', 'home_url' => 'https://player.fm/', 'submit_url' => 'https://player.fm/importer/feed', ], [ - 'name' => 'pocketcasts', + 'slug' => 'pocketcasts', + 'type' => 'podcasting', 'label' => 'Pocketcasts', 'home_url' => 'https://www.pocketcasts.com/', 'submit_url' => 'https://www.pocketcasts.com/submit/', ], [ - 'name' => 'podbean', + 'slug' => 'podbean', + 'type' => 'podcasting', 'label' => 'Podbean', 'home_url' => 'https://www.podbean.com/', 'submit_url' => 'https://www.podbean.com/site/submitPodcast', ], [ - 'name' => 'podcast-addict', + 'slug' => 'podcastaddict', + 'type' => 'podcasting', 'label' => 'Podcast Addict', 'home_url' => 'https://podcastaddict.com/', 'submit_url' => 'https://podcastaddict.com/submit', ], [ - 'name' => 'podcast-index', + 'slug' => 'podcastindex', + 'type' => 'podcasting', 'label' => 'Podcast Index', 'home_url' => 'https://podcastindex.org/', 'submit_url' => 'https://api.podcastindex.org/signup', ], [ - 'name' => 'podchaser', + 'slug' => 'podchaser', + 'type' => 'podcasting', 'label' => 'Podchaser', 'home_url' => 'https://www.podchaser.com/', 'submit_url' => 'https://www.podchaser.com/creators/edit', ], [ - 'name' => 'podtail', + 'slug' => 'podcloud', + 'type' => 'podcasting', + 'label' => 'podCloud', + 'home_url' => 'https://podcloud.fr/', + 'submit_url' => 'https://podcloud.fr/studio/podcasts/new', + ], + [ + 'slug' => 'podinstall', + 'type' => 'podcasting', + 'label' => 'Podinstall', + 'home_url' => 'https://www.podinstall.com/', + 'submit_url' => 'https://www.podinstall.com/claim.html', + ], + [ + 'slug' => 'podtail', + 'type' => 'podcasting', 'label' => 'Podtail', 'home_url' => 'https://podtail.com/', 'submit_url' => 'https://podtail.com/about/faq/', ], [ - 'name' => 'radiopublic', - 'label' => 'Radiopublic', + 'slug' => 'podverse', + 'type' => 'podcasting', + 'label' => 'Podverse', + 'home_url' => 'https://podverse.fm/', + 'submit_url' => + 'https://docs.google.com/forms/d/e/1FAIpQLSdewKP-YrE8zGjDPrkmoJEwCxPl_gizEkmzAlTYsiWAuAk1Ng/viewform', + ], + [ + 'slug' => 'radiopublic', + 'type' => 'podcasting', + 'label' => 'RadioPublic', 'home_url' => 'https://radiopublic.com/', 'submit_url' => 'https://podcasters.radiopublic.com/signup', ], [ - 'name' => 'spotify', + 'slug' => 'spotify', + 'type' => 'podcasting', 'label' => 'Spotify', 'home_url' => 'https://www.spotify.com/', 'submit_url' => 'https://podcasters.spotify.com/submit', ], [ - 'name' => 'spreaker', + 'slug' => 'spreaker', + 'type' => 'podcasting', 'label' => 'Spreaker', 'home_url' => 'https://www.spreaker.com/', 'submit_url' => 'https://www.spreaker.com/cms/shows/rss-import', ], [ - 'name' => 'stitcher', + 'slug' => 'stitcher', + 'type' => 'podcasting', 'label' => 'Stitcher', 'home_url' => 'https://www.stitcher.com/', - 'submit_url' => 'https://www.stitcher.com/content-providers', + 'submit_url' => 'https://partners.stitcher.com/join', ], [ - 'name' => 'tunein', + 'slug' => 'tunein', + 'type' => 'podcasting', 'label' => 'TuneIn', 'home_url' => 'https://tunein.com/', 'submit_url' => 'https://help.tunein.com/contact/add-podcast-S19TR3Sdf', ], + + [ + 'slug' => 'paypal', + 'type' => 'funding', + 'label' => 'Paypal', + 'home_url' => 'https://www.paypal.com/', + 'submit_url' => 'https://www.paypal.com/paypalme/my/grab', + ], + [ + 'slug' => 'liberapay', + 'type' => 'funding', + 'label' => 'Liberapay', + 'home_url' => 'https://liberapay.com/', + 'submit_url' => 'https://liberapay.com/sign-up', + ], + [ + 'slug' => 'patreon', + 'type' => 'funding', + 'label' => 'Patreon', + 'home_url' => 'https://www.patreon.com/', + 'submit_url' => 'https://www.patreon.com/create', + ], + [ + 'slug' => 'tipeee', + 'type' => 'funding', + 'label' => 'Tipeee', + 'home_url' => 'https://tipeee.com/', + 'submit_url' => 'https://tipeee.com/register/', + ], + + [ + 'slug' => 'discord', + 'type' => 'social', + 'label' => 'Discord', + 'home_url' => 'https://discord.com/', + 'submit_url' => 'https://discord.com/register', + ], + [ + 'slug' => 'facebook', + 'type' => 'social', + 'label' => 'Facebook', + 'home_url' => 'https://www.facebook.com/', + 'submit_url' => + 'https://www.facebook.com/pages/creation/?ref_type=comet_home', + ], + [ + 'slug' => 'instagram', + 'type' => 'social', + 'label' => 'Instagram', + 'home_url' => 'https://www.instagram.com/', + 'submit_url' => + 'https://www.instagram.com/accounts/emailsignup/', + ], + [ + 'slug' => 'linkedin', + 'type' => 'social', + 'label' => 'LinkedIn', + 'home_url' => 'https://www.linkedin.com/', + 'submit_url' => 'https://www.linkedin.com/company/setup/new/', + ], + [ + 'slug' => 'mastodon', + 'type' => 'social', + 'label' => 'Mastodon', + 'home_url' => 'https://joinmastodon.org/', + 'submit_url' => 'https://joinmastodon.org/communities', + ], + [ + 'slug' => 'pixelfed', + 'type' => 'social', + 'label' => 'Pixelfed', + 'home_url' => 'https://pixelfed.org/', + 'submit_url' => 'https://beta.joinpixelfed.org/', + ], + [ + 'slug' => 'slack', + 'type' => 'social', + 'label' => 'Slack', + 'home_url' => 'https://slack.com/', + 'submit_url' => 'https://slack.com/get-started#/create', + ], + [ + 'slug' => 'twitch', + 'type' => 'social', + 'label' => 'Twitch', + 'home_url' => 'https://www.twitch.tv/', + 'submit_url' => 'https://www.twitch.tv/signup', + ], + [ + 'slug' => 'twitter', + 'type' => 'social', + 'label' => 'Twitter', + 'home_url' => 'https://twitter.com/', + 'submit_url' => 'https://twitter.com/i/flow/signup', + ], + [ + 'slug' => 'youtube', + 'type' => 'social', + 'label' => 'Youtube', + 'home_url' => 'https://www.youtube.com/', + 'submit_url' => 'https://creatoracademy.youtube.com/page/home', + ], ]; $this->db ->table('platforms') diff --git a/app/Entities/Platform.php b/app/Entities/Platform.php index 7496900f..90460326 100644 --- a/app/Entities/Platform.php +++ b/app/Entities/Platform.php @@ -13,12 +13,13 @@ use CodeIgniter\Entity; class Platform extends Entity { protected $casts = [ - 'id' => 'integer', - 'name' => 'string', + 'slug' => 'string', + 'type' => 'string', 'label' => 'string', 'home_url' => 'string', 'submit_url' => '?string', 'link_url' => '?string', + 'link_content' => '?string', 'is_visible' => '?boolean', ]; } diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index 258a425a..d86851c5 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -55,7 +55,17 @@ class Podcast extends Entity /** * @var \App\Entities\Platform */ - protected $platforms; + protected $podcastingPlatforms; + + /** + * @var \App\Entities\Platform + */ + protected $socialPlatforms; + + /** + * @var \App\Entities\Platform + */ + protected $fundingPlatforms; /** * Holds text only description, striped of any markdown or html special characters @@ -260,25 +270,72 @@ class Podcast extends Entity } /** - * Returns the podcast's platform links + * Returns the podcast's podcasting platform links * * @return \App\Entities\Platform[] */ - public function getPlatforms() + public function getPodcastingPlatforms() { if (empty($this->id)) { throw new \RuntimeException( - 'Podcast must be created before getting platform links.' + 'Podcast must be created before getting podcasting platform links.' ); } - if (empty($this->platforms)) { - $this->platforms = (new PlatformModel())->getPodcastPlatforms( - $this->id + if (empty($this->podcastingPlatforms)) { + $this->podcastingPlatforms = (new PlatformModel())->getPodcastPlatforms( + $this->id, + 'podcasting' ); } - return $this->platforms; + return $this->podcastingPlatforms; + } + + /** + * Returns the podcast's social platform links + * + * @return \App\Entities\Platform[] + */ + public function getSocialPlatforms() + { + if (empty($this->id)) { + throw new \RuntimeException( + 'Podcast must be created before getting social platform links.' + ); + } + + if (empty($this->socialPlatforms)) { + $this->socialPlatforms = (new PlatformModel())->getPodcastPlatforms( + $this->id, + 'social' + ); + } + + return $this->socialPlatforms; + } + + /** + * Returns the podcast's funding platform links + * + * @return \App\Entities\Platform[] + */ + public function getFundingPlatforms() + { + if (empty($this->id)) { + throw new \RuntimeException( + 'Podcast must be created before getting funding platform links.' + ); + } + + if (empty($this->fundingPlatforms)) { + $this->fundingPlatforms = (new PlatformModel())->getPodcastPlatforms( + $this->id, + 'funding' + ); + } + + return $this->fundingPlatforms; } public function getOtherCategories() diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php index f09da92b..db7dad44 100644 --- a/app/Helpers/rss_helper.php +++ b/app/Helpers/rss_helper.php @@ -71,6 +71,71 @@ function get_rss_feed($podcast, $serviceName = '') $podcast_namespace ) ->addAttribute('owner', $podcast->owner_email); + if (!empty($podcast->imported_feed_url)) { + $channel->addChildWithCDATA( + 'previousUrl', + $podcast->imported_feed_url, + $podcast_namespace + ); + } + + foreach ($podcast->podcastingPlatforms as $podcastingPlatform) { + $podcastingPlatformElement = $channel->addChild( + 'id', + null, + $podcast_namespace + ); + $podcastingPlatformElement->addAttribute( + 'platform', + $podcastingPlatform->slug + ); + if (!empty($podcastingPlatform->link_content)) { + $podcastingPlatformElement->addAttribute( + 'id', + $podcastingPlatform->link_content + ); + } + if (!empty($podcastingPlatform->link_url)) { + $podcastingPlatformElement->addAttribute( + 'url', + htmlspecialchars($podcastingPlatform->link_url) + ); + } + } + + foreach ($podcast->socialPlatforms as $socialPlatform) { + $socialPlatformElement = $channel->addChild( + 'social', + $socialPlatform->link_content, + $podcast_namespace + ); + $socialPlatformElement->addAttribute('platform', $socialPlatform->slug); + if (!empty($socialPlatform->link_url)) { + $socialPlatformElement->addAttribute( + 'url', + htmlspecialchars($socialPlatform->link_url) + ); + } + } + + foreach ($podcast->fundingPlatforms as $fundingPlatform) { + $fundingPlatformElement = $channel->addChild( + 'funding', + $fundingPlatform->link_content, + $podcast_namespace + ); + $fundingPlatformElement->addAttribute( + 'platform', + $fundingPlatform->slug + ); + if (!empty($socialPlatform->link_url)) { + $fundingPlatformElement->addAttribute( + 'url', + htmlspecialchars($fundingPlatform->link_url) + ); + } + } + // set main category first, then other categories as apple add_category_tag($channel, $podcast->category); foreach ($podcast->other_categories as $other_category) { diff --git a/app/Helpers/svg_helper.php b/app/Helpers/svg_helper.php index ba776527..9474c4a0 100644 --- a/app/Helpers/svg_helper.php +++ b/app/Helpers/svg_helper.php @@ -54,11 +54,11 @@ function svg($name, $class = null) * @param string $class to be added to the svg string * @return string svg contents */ -function platform_icon($name, $class = null) +function platform_icon($type, $name, $class = null) { try { $svg_contents = file_get_contents( - 'assets/images/platforms/' . $name . '.svg' + 'assets/images/platforms/' . $type . '/' . $name . '.svg' ); } catch (\Exception $e) { $svg_contents = file_get_contents( diff --git a/app/Language/en/Breadcrumb.php b/app/Language/en/Breadcrumb.php index a7b26ff7..8fcfcbeb 100644 --- a/app/Language/en/Breadcrumb.php +++ b/app/Language/en/Breadcrumb.php @@ -20,13 +20,14 @@ return [ 'my-account' => 'my account', 'change-password' => 'change password', 'import' => 'feed import', - 'settings' => 'settings', 'platforms' => 'platforms', - 'analytics' => 'Analytics', - 'locations' => 'Locations', - 'webpages' => 'Web pages', - 'unique-listeners' => 'Unique listeners', - 'players' => 'Players', - 'listening-time' => 'Listening time', - 'time-periods' => 'Time periods', + 'social' => 'social networks', + 'funding' => 'funding', + 'analytics' => 'analytics', + 'locations' => 'locations', + 'webpages' => 'web pages', + 'unique-listeners' => 'unique listeners', + 'players' => 'players', + 'listening-time' => 'listening time', + 'time-periods' => 'time periods', ]; diff --git a/app/Language/en/Platforms.php b/app/Language/en/Platforms.php index d0367524..da822c97 100644 --- a/app/Language/en/Platforms.php +++ b/app/Language/en/Platforms.php @@ -19,4 +19,9 @@ return [ 'removeLinkError' => 'The platform link could not be removed. Try again.', ], + 'description' => [ + 'podcasting' => 'The podcast ID on this platform', + 'social' => 'The podcast account ID on this platform', + 'funding' => 'Call to action message', + ], ]; diff --git a/app/Language/en/PodcastNavigation.php b/app/Language/en/PodcastNavigation.php index 712fc8bd..048ca8be 100644 --- a/app/Language/en/PodcastNavigation.php +++ b/app/Language/en/PodcastNavigation.php @@ -18,8 +18,10 @@ return [ 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'settings' => 'Settings', - 'platforms' => 'Podcast platforms', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', + 'platforms-social' => 'Social Networks', + 'platforms-funding' => 'Funding', 'podcast-analytics' => 'Audience overview', 'podcast-analytics-webpages' => 'Web pages visits', 'podcast-analytics-locations' => 'Locations', diff --git a/app/Language/fr/Breadcrumb.php b/app/Language/fr/Breadcrumb.php index 5c55f168..de8d5f80 100644 --- a/app/Language/fr/Breadcrumb.php +++ b/app/Language/fr/Breadcrumb.php @@ -20,13 +20,14 @@ return [ 'my-account' => 'mon compte', 'change-password' => 'changer le mot de passe', 'import' => 'importer un flux', - 'settings' => 'paramètres', 'platforms' => 'plateformes', - 'analytics' => 'Mesures d’audience', - 'locations' => 'Localisations', - 'webpages' => 'Pages web', - 'unique-listeners' => 'Auditeurs uniques', - 'players' => 'Lecteurs', - 'listening-time' => 'Durée d’écoute', - 'time-periods' => 'Périodes', + 'social' => 'réseaux sociaux', + 'funding' => 'financement', + 'analytics' => 'mesures d’audience', + 'locations' => 'localisations', + 'webpages' => 'pages web', + 'unique-listeners' => 'auditeurs uniques', + 'players' => 'lecteurs', + 'listening-time' => 'drée d’écoute', + 'time-periods' => 'périodes', ]; diff --git a/app/Language/fr/Platforms.php b/app/Language/fr/Platforms.php index 3895de2d..d7b66d63 100644 --- a/app/Language/fr/Platforms.php +++ b/app/Language/fr/Platforms.php @@ -19,4 +19,9 @@ return [ 'removeLinkError' => 'Le lien n’a pas pu être supprimé. Merci d’essayer à nouveau.', ], + 'description' => [ + 'podcasting' => 'L’identifiant du podcast sur cette plate-forme', + 'social' => 'L’identifiant du compte du podcast sur cette plate-forme', + 'funding' => 'Message d’incitation à l’action', + ], ]; diff --git a/app/Language/fr/PodcastNavigation.php b/app/Language/fr/PodcastNavigation.php index 39852186..5ac59cd2 100644 --- a/app/Language/fr/PodcastNavigation.php +++ b/app/Language/fr/PodcastNavigation.php @@ -18,7 +18,10 @@ return [ 'contributors' => 'Contributeurs', 'contributor-list' => 'Tous les contributeurs', 'contributor-add' => 'Ajouter un contributeur', - 'settings' => 'Paramètres', + 'platforms' => 'Plate-formes externes', + 'platforms-podcasting' => 'Podcasts', + 'platforms-social' => 'Réseaux Sociaux', + 'platforms-funding' => 'Financement', 'platforms' => 'Plateformes du podcast', 'podcast-analytics' => 'Vue d’ensemble', 'podcast-analytics-webpages' => 'Visites des pages web', diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php index 684135ac..f13586dc 100644 --- a/app/Models/PlatformModel.php +++ b/app/Models/PlatformModel.php @@ -18,47 +18,63 @@ class PlatformModel extends Model protected $table = 'platforms'; protected $primaryKey = 'id'; - protected $allowedFields = ['name', 'label', 'home_url', 'submit_url']; + protected $allowedFields = ['slug', 'label', 'home_url', 'submit_url']; protected $returnType = \App\Entities\Platform::class; protected $useSoftDeletes = false; protected $useTimestamps = true; - public function getPlatformsWithLinks($podcastId) + public function getPlatforms() { - if (!($found = cache("podcast{$podcastId}_platforms"))) { + if (!($found = cache('platforms'))) { + $baseUrl = rtrim(config('app')->baseURL, '/'); $found = $this->select( - 'platforms.*, platform_links.link_url, platform_links.is_visible' - ) - ->join( - 'platform_links', - "platform_links.platform_id = platforms.id AND platform_links.podcast_id = $podcastId", - 'left' - ) - ->findAll(); - - cache()->save("podcast{$podcastId}_platforms", $found, DECADE); + "*, CONCAT('{$baseUrl}/assets/images/platforms/',`type`,'/',`slug`,'.svg') as icon" + )->findAll(); + cache()->save('platforms', $found, DECADE); } - return $found; } - public function getPodcastPlatforms($podcastId) + public function getOrCreatePlatform($slug, $platformType) { - if (!($found = cache("podcast{$podcastId}_podcastPlatforms"))) { + if (!($found = cache("platforms_$slug"))) { + $found = $this->where('slug', $slug)->first(); + if (!$found) { + $data = [ + 'slug' => $slug, + 'type' => $platformType, + 'label' => $slug, + 'home_url' => '', + 'submit_url' => null, + ]; + $this->insert($data); + $found = $this->where('slug', $slug)->first(); + } + cache()->save("platforms_$slug", $found, DECADE); + } + return $found; + } + + public function getPlatformsWithLinks($podcastId, $platformType) + { + if ( + !($found = cache("podcast{$podcastId}_platforms_{$platformType}")) + ) { $found = $this->select( - 'platforms.*, platform_links.link_url, platform_links.is_visible' + 'platforms.*, podcasts_platforms.link_url, podcasts_platforms.link_content, podcasts_platforms.is_visible' ) ->join( - 'platform_links', - 'platform_links.platform_id = platforms.id' + 'podcasts_platforms', + "podcasts_platforms.platform_slug = platforms.slug AND podcasts_platforms.podcast_id = $podcastId", + 'left' ) - ->where('platform_links.podcast_id', $podcastId) + ->where('platforms.type', $platformType) ->findAll(); cache()->save( - "podcast{$podcastId}_podcastPlatforms", + "podcast{$podcastId}_platforms_{$platformType}", $found, DECADE ); @@ -67,49 +83,85 @@ class PlatformModel extends Model return $found; } - public function savePodcastPlatforms($podcastId, $platformLinksData) + public function getPodcastPlatforms($podcastId, $platformType) { + if ( + !($found = cache( + "podcast{$podcastId}_podcastPlatforms_{$platformType}" + )) + ) { + $found = $this->select( + 'platforms.*, podcasts_platforms.link_url, podcasts_platforms.link_content, podcasts_platforms.is_visible' + ) + ->join( + 'podcasts_platforms', + 'podcasts_platforms.platform_slug = platforms.slug' + ) + ->where('podcasts_platforms.podcast_id', $podcastId) + ->where('platforms.type', $platformType) + ->findAll(); + + cache()->save( + "podcast{$podcastId}_podcastPlatforms_{$platformType}", + $found, + DECADE + ); + } + + return $found; + } + + public function savePodcastPlatforms( + $podcastId, + $platformType, + $podcastsPlatformsData + ) { $this->clearCache($podcastId); - // Remove already previously set platforms to overwrite them - $this->db - ->table('platform_links') - ->delete(['podcast_id' => $podcastId]); + $podcastsPlatformsTable = $this->db->prefixTable('podcasts_platforms'); + $platformsTable = $this->db->prefixTable('platforms'); + $deleteJoinQuery = <<db->query($deleteJoinQuery, [$podcastId, $platformType]); // Set podcastPlatforms return $this->db - ->table('platform_links') - ->insertBatch($platformLinksData); + ->table('podcasts_platforms') + ->insertBatch($podcastsPlatformsData); } - public function getPlatformId(string $platformName) - { - $p = $this->where('name', $platformName)->first(); - - if (!$p) { - $this->error = lang('Platform.platformNotFound', [$platformName]); - - return false; - } - - return (int) $p->id; - } - - public function removePodcastPlatform($podcastId, $platformId) + public function createPodcastPlatforms($podcastId, $podcastsPlatformsData) { $this->clearCache($podcastId); - return $this->db->table('platform_links')->delete([ + // Set podcastPlatforms + return $this->db + ->table('podcasts_platforms') + ->insertBatch($podcastsPlatformsData); + } + + public function removePodcastPlatform($podcastId, $platformSlug) + { + $this->clearCache($podcastId); + + return $this->db->table('podcasts_platforms')->delete([ 'podcast_id' => $podcastId, - 'platform_id' => $platformId, + 'platform_slug' => $platformSlug, ]); } public function clearCache($podcastId) { - cache()->delete("podcast{$podcastId}_platforms"); - cache()->delete("podcast{$podcastId}_podcastPlatforms"); - + foreach (['podcasting', 'social', 'funding'] as $platformType) { + cache()->delete("podcast{$podcastId}_platforms_{$platformType}"); + cache()->delete( + "podcast{$podcastId}_podcastPlatforms_{$platformType}" + ); + } // delete localized podcast page cache $episodeModel = new EpisodeModel(); $years = $episodeModel->getYears($podcastId); diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index 1ac4531d..7ac59412 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -69,7 +69,6 @@ class PodcastModel extends Model { if (!($found = cache("podcast@{$podcastName}"))) { $found = $this->where('name', $podcastName)->first(); - cache()->save("podcast@{$podcastName}", $found, DECADE); } diff --git a/app/Views/_assets/icons/add-box.svg b/app/Views/_assets/icons/add-box.svg new file mode 100644 index 00000000..dc56100a --- /dev/null +++ b/app/Views/_assets/icons/add-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/icons/links.svg b/app/Views/_assets/icons/links.svg new file mode 100644 index 00000000..3bff8657 --- /dev/null +++ b/app/Views/_assets/icons/links.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/icons/upload.svg b/app/Views/_assets/icons/upload.svg deleted file mode 100644 index ad478afc..00000000 --- a/app/Views/_assets/icons/upload.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/Views/_assets/images/platforms/_default.svg b/app/Views/_assets/images/platforms/_default.svg index 42640a76..e3b5c641 100644 --- a/app/Views/_assets/images/platforms/_default.svg +++ b/app/Views/_assets/images/platforms/_default.svg @@ -1,26 +1,11 @@ - -image/svg+xml - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/funding/liberapay.svg b/app/Views/_assets/images/platforms/funding/liberapay.svg new file mode 100644 index 00000000..21a14fd9 --- /dev/null +++ b/app/Views/_assets/images/platforms/funding/liberapay.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/funding/patreon.svg b/app/Views/_assets/images/platforms/funding/patreon.svg new file mode 100644 index 00000000..fba04ee9 --- /dev/null +++ b/app/Views/_assets/images/platforms/funding/patreon.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/funding/paypal.svg b/app/Views/_assets/images/platforms/funding/paypal.svg new file mode 100644 index 00000000..33552f57 --- /dev/null +++ b/app/Views/_assets/images/platforms/funding/paypal.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/funding/tipeee.svg b/app/Views/_assets/images/platforms/funding/tipeee.svg new file mode 100644 index 00000000..72063b9a --- /dev/null +++ b/app/Views/_assets/images/platforms/funding/tipeee.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/google-podcasts.svg b/app/Views/_assets/images/platforms/google-podcasts.svg deleted file mode 100644 index 5903413a..00000000 --- a/app/Views/_assets/images/platforms/google-podcasts.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/Views/_assets/images/platforms/podcast-index.svg b/app/Views/_assets/images/platforms/podcast-index.svg deleted file mode 100644 index e52f8999..00000000 --- a/app/Views/_assets/images/platforms/podcast-index.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/Views/_assets/images/platforms/podcasting/amazon.svg b/app/Views/_assets/images/platforms/podcasting/amazon.svg new file mode 100644 index 00000000..5d6af71e --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/amazon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/apple-podcasts.svg b/app/Views/_assets/images/platforms/podcasting/apple.svg similarity index 100% rename from app/Views/_assets/images/platforms/apple-podcasts.svg rename to app/Views/_assets/images/platforms/podcasting/apple.svg diff --git a/app/Views/_assets/images/platforms/blubrry.svg b/app/Views/_assets/images/platforms/podcasting/blubrry.svg similarity index 100% rename from app/Views/_assets/images/platforms/blubrry.svg rename to app/Views/_assets/images/platforms/podcasting/blubrry.svg diff --git a/app/Views/_assets/images/platforms/castbox.svg b/app/Views/_assets/images/platforms/podcasting/castbox.svg similarity index 100% rename from app/Views/_assets/images/platforms/castbox.svg rename to app/Views/_assets/images/platforms/podcasting/castbox.svg diff --git a/app/Views/_assets/images/platforms/castro.svg b/app/Views/_assets/images/platforms/podcasting/castro.svg similarity index 100% rename from app/Views/_assets/images/platforms/castro.svg rename to app/Views/_assets/images/platforms/podcasting/castro.svg diff --git a/app/Views/_assets/images/platforms/podcasting/chartable.svg b/app/Views/_assets/images/platforms/podcasting/chartable.svg new file mode 100644 index 00000000..1a09a99b --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/chartable.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/Views/_assets/images/platforms/deezer.svg b/app/Views/_assets/images/platforms/podcasting/deezer.svg similarity index 100% rename from app/Views/_assets/images/platforms/deezer.svg rename to app/Views/_assets/images/platforms/podcasting/deezer.svg diff --git a/app/Views/_assets/images/platforms/podcasting/fyyd.svg b/app/Views/_assets/images/platforms/podcasting/fyyd.svg new file mode 100644 index 00000000..e17b8f6b --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/fyyd.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Views/_assets/images/platforms/podcasting/google.svg b/app/Views/_assets/images/platforms/podcasting/google.svg new file mode 100644 index 00000000..c158a05d --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/google.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/app/Views/_assets/images/platforms/ivoox.svg b/app/Views/_assets/images/platforms/podcasting/ivoox.svg similarity index 100% rename from app/Views/_assets/images/platforms/ivoox.svg rename to app/Views/_assets/images/platforms/podcasting/ivoox.svg diff --git a/app/Views/_assets/images/platforms/listennotes.svg b/app/Views/_assets/images/platforms/podcasting/listennotes.svg similarity index 100% rename from app/Views/_assets/images/platforms/listennotes.svg rename to app/Views/_assets/images/platforms/podcasting/listennotes.svg diff --git a/app/Views/_assets/images/platforms/overcast.svg b/app/Views/_assets/images/platforms/podcasting/overcast.svg similarity index 100% rename from app/Views/_assets/images/platforms/overcast.svg rename to app/Views/_assets/images/platforms/podcasting/overcast.svg diff --git a/app/Views/_assets/images/platforms/playerfm.svg b/app/Views/_assets/images/platforms/podcasting/playerfm.svg similarity index 100% rename from app/Views/_assets/images/platforms/playerfm.svg rename to app/Views/_assets/images/platforms/podcasting/playerfm.svg diff --git a/app/Views/_assets/images/platforms/pocketcasts.svg b/app/Views/_assets/images/platforms/podcasting/pocketcasts.svg similarity index 100% rename from app/Views/_assets/images/platforms/pocketcasts.svg rename to app/Views/_assets/images/platforms/podcasting/pocketcasts.svg diff --git a/app/Views/_assets/images/platforms/podbean.svg b/app/Views/_assets/images/platforms/podcasting/podbean.svg similarity index 100% rename from app/Views/_assets/images/platforms/podbean.svg rename to app/Views/_assets/images/platforms/podcasting/podbean.svg diff --git a/app/Views/_assets/images/platforms/podcast-addict.svg b/app/Views/_assets/images/platforms/podcasting/podcastaddict.svg similarity index 100% rename from app/Views/_assets/images/platforms/podcast-addict.svg rename to app/Views/_assets/images/platforms/podcasting/podcastaddict.svg diff --git a/app/Views/_assets/images/platforms/podcasting/podcastindex.svg b/app/Views/_assets/images/platforms/podcasting/podcastindex.svg new file mode 100644 index 00000000..f55cb778 --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/podcastindex.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/Views/_assets/images/platforms/podchaser.svg b/app/Views/_assets/images/platforms/podcasting/podchaser.svg similarity index 100% rename from app/Views/_assets/images/platforms/podchaser.svg rename to app/Views/_assets/images/platforms/podcasting/podchaser.svg diff --git a/app/Views/_assets/images/platforms/podcasting/podcloud.svg b/app/Views/_assets/images/platforms/podcasting/podcloud.svg new file mode 100644 index 00000000..8bdfccd9 --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/podcloud.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/Views/_assets/images/platforms/podcasting/podinstall.svg b/app/Views/_assets/images/platforms/podcasting/podinstall.svg new file mode 100644 index 00000000..fb6f3868 --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/podinstall.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/Views/_assets/images/platforms/podtail.svg b/app/Views/_assets/images/platforms/podcasting/podtail.svg similarity index 100% rename from app/Views/_assets/images/platforms/podtail.svg rename to app/Views/_assets/images/platforms/podcasting/podtail.svg diff --git a/app/Views/_assets/images/platforms/podcasting/podverse.svg b/app/Views/_assets/images/platforms/podcasting/podverse.svg new file mode 100644 index 00000000..1cb12e6a --- /dev/null +++ b/app/Views/_assets/images/platforms/podcasting/podverse.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/Views/_assets/images/platforms/radiopublic.svg b/app/Views/_assets/images/platforms/podcasting/radiopublic.svg similarity index 100% rename from app/Views/_assets/images/platforms/radiopublic.svg rename to app/Views/_assets/images/platforms/podcasting/radiopublic.svg diff --git a/app/Views/_assets/images/platforms/spotify.svg b/app/Views/_assets/images/platforms/podcasting/spotify.svg similarity index 100% rename from app/Views/_assets/images/platforms/spotify.svg rename to app/Views/_assets/images/platforms/podcasting/spotify.svg diff --git a/app/Views/_assets/images/platforms/spreaker.svg b/app/Views/_assets/images/platforms/podcasting/spreaker.svg similarity index 100% rename from app/Views/_assets/images/platforms/spreaker.svg rename to app/Views/_assets/images/platforms/podcasting/spreaker.svg diff --git a/app/Views/_assets/images/platforms/stitcher.svg b/app/Views/_assets/images/platforms/podcasting/stitcher.svg similarity index 100% rename from app/Views/_assets/images/platforms/stitcher.svg rename to app/Views/_assets/images/platforms/podcasting/stitcher.svg diff --git a/app/Views/_assets/images/platforms/tunein.svg b/app/Views/_assets/images/platforms/podcasting/tunein.svg similarity index 100% rename from app/Views/_assets/images/platforms/tunein.svg rename to app/Views/_assets/images/platforms/podcasting/tunein.svg diff --git a/app/Views/_assets/images/platforms/social/discord.svg b/app/Views/_assets/images/platforms/social/discord.svg new file mode 100644 index 00000000..f74b86b4 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/discord.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/facebook.svg b/app/Views/_assets/images/platforms/social/facebook.svg new file mode 100644 index 00000000..41080c48 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/facebook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/instagram.svg b/app/Views/_assets/images/platforms/social/instagram.svg new file mode 100644 index 00000000..1f5d89c5 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/instagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/linkedin.svg b/app/Views/_assets/images/platforms/social/linkedin.svg new file mode 100644 index 00000000..d4692808 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/mastodon.svg b/app/Views/_assets/images/platforms/social/mastodon.svg new file mode 100644 index 00000000..bb1e3746 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/mastodon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/pixelfed.svg b/app/Views/_assets/images/platforms/social/pixelfed.svg new file mode 100644 index 00000000..d3174c34 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/pixelfed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/slack.svg b/app/Views/_assets/images/platforms/social/slack.svg new file mode 100644 index 00000000..462a58c6 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/slack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/twitch.svg b/app/Views/_assets/images/platforms/social/twitch.svg new file mode 100644 index 00000000..5ff88372 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/twitch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/twitter.svg b/app/Views/_assets/images/platforms/social/twitter.svg new file mode 100644 index 00000000..a385fdc1 --- /dev/null +++ b/app/Views/_assets/images/platforms/social/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/_assets/images/platforms/social/youtube.svg b/app/Views/_assets/images/platforms/social/youtube.svg new file mode 100644 index 00000000..a3aff57a --- /dev/null +++ b/app/Views/_assets/images/platforms/social/youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Views/admin/podcast/_sidebar.php b/app/Views/admin/podcast/_sidebar.php index 704a7444..7d525a25 100644 --- a/app/Views/admin/podcast/_sidebar.php +++ b/app/Views/admin/podcast/_sidebar.php @@ -24,9 +24,13 @@ $podcastNavigation = [ 'icon' => 'group', 'items' => ['contributor-list', 'contributor-add'], ], - 'settings' => [ - 'icon' => 'settings', - 'items' => ['platforms'], + 'platforms' => [ + 'icon' => 'links', + 'items' => [ + 'platforms-podcasting', + 'platforms-social', + 'platforms-funding', + ], ], ]; ?> diff --git a/app/Views/admin/podcast/settings/platforms.php b/app/Views/admin/podcast/platforms.php similarity index 67% rename from app/Views/admin/podcast/settings/platforms.php rename to app/Views/admin/podcast/platforms.php index 7daf991a..d2009812 100644 --- a/app/Views/admin/podcast/settings/platforms.php +++ b/app/Views/admin/podcast/platforms.php @@ -10,7 +10,7 @@ section('content') ?> -id), [ +id, $platformType), [ 'class' => 'flex flex-col max-w-md', ]) ?> @@ -19,7 +19,11 @@
- name, 'w-full mb-1') ?> + type, + $platform->slug, + 'w-full mb-1 text-gray-800' + ) ?>
home_url, icon('external-link', 'mx-auto'), [ 'class' => 'flex-1 text-gray-600 hover:text-gray-900', @@ -32,7 +36,7 @@ ]), ]) ?> submit_url - ? anchor($platform->submit_url, icon('upload', 'mx-auto'), [ + ? anchor($platform->submit_url, icon('add-box', 'mx-auto'), [ 'class' => 'flex-1 text-gray-600 hover:text-gray-900', 'target' => '_blank', 'rel' => 'noopener noreferrer', @@ -48,7 +52,11 @@
link_url ? anchor( - route_to('platforms-remove', $podcast->id, $platform->id), + route_to( + 'podcast-platform-remove', + $podcast->id, + $platform->slug + ), icon('delete-bin', 'mx-auto'), [ 'class' => @@ -61,26 +69,37 @@ ] ) : '' ?> - label, $platform->name, [ + label, $platform->slug, [ 'class' => 'font-semibold mb-2', ]) ?> $platform->name, - 'name' => 'platforms[' . $platform->name . '][url]', + 'id' => $platform->slug . '_link_url', + 'name' => 'platforms[' . $platform->slug . '][url]', 'class' => 'form-input mb-1 w-full', - 'value' => old($platform->name, $platform->link_url), + 'value' => old($platform->slug . '_link_url', $platform->link_url), 'type' => 'url', 'placeholder' => 'https://...', ]) ?> + $platform->slug . '_link_content', + 'name' => 'platforms[' . $platform->slug . '][content]', + 'class' => 'form-input mb-1 w-full', + 'value' => old( + $platform->slug . '_link_content', + $platform->link_content + ), + 'type' => 'text', + 'placeholder' => lang("Platforms.description.{$platform->type}"), + ]) ?> $platform->name . '_visible', - 'name' => 'platforms[' . $platform->name . '][visible]', + 'id' => $platform->slug . '_visible', + 'name' => 'platforms[' . $platform->slug . '][visible]', ], 'yes', old( - $platform->name . '_visible', + $platform->slug . '_visible', $platform->is_visible ? $platform->is_visible : false ), 'text-sm' diff --git a/app/Views/podcast.php b/app/Views/podcast.php index 6a3e5d56..e8f5d659 100644 --- a/app/Views/podcast.php +++ b/app/Views/podcast.php @@ -32,7 +32,7 @@
<?= $podcast->title ?> -
+

title ?> @name ?>

@@ -46,23 +46,65 @@ '' : '' ?>
-
+
name), icon('rss', 'mr-2') . lang('Podcast.feed'), [ 'class' => - 'text-white bg-gradient-to-r from-orange-400 to-red-500 hover:to-orange-500 hover:bg-orange-500 inline-flex items-center px-2 py-1 mb-2 font-semibold rounded-lg shadow-md hover:bg-orange-600', + 'text-white bg-gradient-to-r from-orange-400 to-red-500 hover:to-orange-500 hover:bg-orange-500 inline-flex items-center px-2 py-1 font-semibold rounded-lg shadow-md hover:bg-orange-600', ] ) ?> - platforms as $platform): ?> - is_visible): ?> - - name, 'h-8') ?> + podcastingPlatforms + as $podcastingPlatform + ): ?> + is_visible): ?> + + type, + $podcastingPlatform->slug, + 'h-8' + ) ?>
+ +
+ socialPlatforms + as $socialPlatform + ): ?> + is_visible): ?> + + type, + $socialPlatform->slug, + 'h-8 text-black md:text-white' + ) ?> + + + +
+ +
+ fundingPlatforms + as $fundingPlatform + ): ?> + is_visible): ?> + + type, + $fundingPlatform->slug, + 'h-8' + ) ?> + + + +
+
description_html ?>