From 3a7d26fdf9bfeffb9247f8efe06d9040ae2fe5ff Mon Sep 17 00:00:00 2001
From: Yassine Doghri <yassine@doghri.fr>
Date: Thu, 24 Oct 2024 12:23:59 +0000
Subject: [PATCH] feat(rss): add option for 301 redirect to new feed url

---
 app/Controllers/FeedController.php              | 15 +++++++++++++--
 modules/Admin/Controllers/PodcastController.php |  8 ++++++++
 modules/Admin/Language/en/Podcast.php           |  2 ++
 themes/cp_admin/podcast/edit.php                |  4 ++++
 4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/app/Controllers/FeedController.php b/app/Controllers/FeedController.php
index 4d646bd454..11b54ddd62 100644
--- a/app/Controllers/FeedController.php
+++ b/app/Controllers/FeedController.php
@@ -33,14 +33,25 @@ class FeedController extends Controller
 
     public function index(string $podcastHandle): ResponseInterface
     {
-        helper(['rss', 'premium_podcasts', 'misc']);
-
         $podcast = (new PodcastModel())->where('handle', $podcastHandle)
             ->first();
         if (! $podcast instanceof Podcast) {
             throw PageNotFoundException::forPageNotFound();
         }
 
+        // 301 redirect to new feed?
+        $redirectToNewFeed = service('settings')
+            ->get('Podcast.redirect_to_new_feed', 'podcast:' . $podcast->id);
+
+        if ($redirectToNewFeed && $podcast->new_feed_url !== null && filter_var(
+            $podcast->new_feed_url,
+            FILTER_VALIDATE_URL
+        ) && $podcast->new_feed_url !== current_url()) {
+            return redirect()->to($podcast->new_feed_url, 301);
+        }
+
+        helper(['rss', 'premium_podcasts', 'misc']);
+
         $service = null;
         try {
             $service = UserAgentsRSS::find(service('superglobals')->server('HTTP_USER_AGENT'));
diff --git a/modules/Admin/Controllers/PodcastController.php b/modules/Admin/Controllers/PodcastController.php
index aa8c726f9d..67c1596ddc 100644
--- a/modules/Admin/Controllers/PodcastController.php
+++ b/modules/Admin/Controllers/PodcastController.php
@@ -367,6 +367,14 @@ class PodcastController extends BaseController
                 'podcast:' . $this->podcast->id
             );
 
+        // New feed url redirect
+        service('settings')
+            ->set(
+                'Podcast.redirect_to_new_feed',
+                $this->request->getPost('redirect_to_new_feed') === 'yes',
+                'podcast:' . $this->podcast->id
+            );
+
         $db->transComplete();
 
         return redirect()->route('podcast-edit', [$this->podcast->id])->with(
diff --git a/modules/Admin/Language/en/Podcast.php b/modules/Admin/Language/en/Podcast.php
index ff0daebc78..ac1aae77e5 100644
--- a/modules/Admin/Language/en/Podcast.php
+++ b/modules/Admin/Language/en/Podcast.php
@@ -143,6 +143,8 @@ return [
         'verify_txt_helper' => 'This text is injected into a <podcast:txt purpose="verify"> tag.',
         'new_feed_url' => 'New feed URL',
         'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.',
+        'redirect_to_new_feed' => 'Automatically redirect to new feed (301 redirect)',
+        'redirect_to_new_feed_hint' => 'Check this when migrating your Castopod RSS feed to the new feed url set above. To ensure followers receive your most recent episodes from the new feed URL, maintain this redirect and the <itunes:new-feed-url> tag in your new feed for at least four weeks.',
         'old_feed_url' => 'Old feed URL',
         'partnership' => 'Partnership',
         'partner_id' => 'ID',
diff --git a/themes/cp_admin/podcast/edit.php b/themes/cp_admin/podcast/edit.php
index d38bc5a8de..85c94fae11 100644
--- a/themes/cp_admin/podcast/edit.php
+++ b/themes/cp_admin/podcast/edit.php
@@ -262,6 +262,10 @@ label="<?= esc(lang('Podcast.form.new_feed_url')) ?>"
 hint="<?= esc(lang('Podcast.form.new_feed_url_hint')) ?>"
 value="<?= esc($podcast->new_feed_url) ?>"
 />
+<Forms.Toggler name="redirect_to_new_feed" value="yes" checked="<?= service('settings')
+            ->get('Podcast.redirect_to_new_feed', 'podcast:' . $podcast->id) ? 'true' : 'false' ?>" hint="<?= esc(lang('Podcast.form.redirect_to_new_feed_hint')) ?>"><?= lang('Podcast.form.redirect_to_new_feed') ?></Forms.Toggler>
+
+<hr class="border-subtle">
 
 <Forms.Toggler class="mb-2" name="lock" value="yes" checked="<?= $podcast->is_locked ? 'true' : 'false' ?>" hint="<?= esc(lang('Podcast.form.lock_hint')) ?>">
     <?= lang('Podcast.form.lock') ?>
-- 
GitLab