fix(premium-podcasts): return different cached page when podcast is unlocked

- clear podcast cache when setting subscription link
- update and add missing translation keys
This commit is contained in:
Yassine Doghri 2022-09-29 10:51:12 +00:00
parent 65173e5180
commit b1303c5255
11 changed files with 59 additions and 54 deletions

View File

@ -70,11 +70,18 @@ class EpisodeController extends BaseController
$this->registerPodcastWebpageHit($this->episode->podcast_id); $this->registerPodcastWebpageHit($this->episode->podcast_id);
} }
$locale = service('request') $cacheName = implode(
->getLocale(); '_',
$cacheName = array_filter([
"page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_{$locale}" . 'page',
(can_user_interact() ? '_authenticated' : ''); "podcast#{$this->podcast->id}",
"episode#{$this->episode->id}",
service('request')
->getLocale(),
is_unlocked($this->podcast->handle) ? 'unlocked' : null,
can_user_interact() ? 'authenticated' : null,
]),
);
if (! ($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$data = [ $data = [
@ -112,11 +119,19 @@ class EpisodeController extends BaseController
$this->registerPodcastWebpageHit($this->episode->podcast_id); $this->registerPodcastWebpageHit($this->episode->podcast_id);
} }
$locale = service('request') $cacheName = implode(
->getLocale(); '_',
$cacheName = array_filter([
"page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_activity_{$locale}" . 'page',
(can_user_interact() ? '_authenticated' : ''); "podcast#{$this->podcast->id}",
"episode#{$this->episode->id}",
'activity',
service('request')
->getLocale(),
is_unlocked($this->podcast->handle) ? 'unlocked' : null,
can_user_interact() ? 'authenticated' : null,
]),
);
if (! ($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$data = [ $data = [

View File

@ -74,6 +74,7 @@ class PodcastController extends BaseController
'activity', 'activity',
service('request') service('request')
->getLocale(), ->getLocale(),
is_unlocked($this->podcast->handle) ? 'unlocked' : null,
can_user_interact() ? 'authenticated' : null, can_user_interact() ? 'authenticated' : null,
]), ]),
); );
@ -122,6 +123,7 @@ class PodcastController extends BaseController
'about', 'about',
service('request') service('request')
->getLocale(), ->getLocale(),
is_unlocked($this->podcast->handle) ? 'unlocked' : null,
can_user_interact() ? 'authenticated' : null, can_user_interact() ? 'authenticated' : null,
]), ]),
); );
@ -188,6 +190,7 @@ class PodcastController extends BaseController
$seasonQuery ? 'season' . $seasonQuery : null, $seasonQuery ? 'season' . $seasonQuery : null,
service('request') service('request')
->getLocale(), ->getLocale(),
is_unlocked($this->podcast->handle) ? 'unlocked' : null,
can_user_interact() ? 'authenticated' : null, can_user_interact() ? 'authenticated' : null,
]), ]),
); );

View File

@ -47,4 +47,5 @@ return [
'video-clips' => 'video clips', 'video-clips' => 'video clips',
'embed' => 'embeddable player', 'embed' => 'embeddable player',
'notifications' => 'notifications', 'notifications' => 'notifications',
'suspend' => 'suspend',
]; ];

View File

@ -110,7 +110,7 @@ return [
'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show',
], ],
'premium_title' => 'Premium', 'premium_title' => 'Premium',
'premium' => 'Episode must only be accessible to premium subscribers', 'premium' => 'Episode must be accessible to premium subscribers only',
'parental_advisory' => [ 'parental_advisory' => [
'label' => 'Parental advisory', 'label' => 'Parental advisory',
'hint' => 'Does the episode contain explicit content?', 'hint' => 'Does the episode contain explicit content?',

View File

@ -99,17 +99,17 @@ $routes->group(
], ],
); );
$routes->get( $routes->get(
'remove', 'delete',
'SubscriptionController::remove/$1/$2', 'SubscriptionController::delete/$1/$2',
[ [
'as' => 'subscription-remove', 'as' => 'subscription-delete',
'filter' => 'filter' =>
'permission:podcast-manage_subscriptions', 'permission:podcast-manage_subscriptions',
], ],
); );
$routes->post( $routes->post(
'remove', 'delete',
'SubscriptionController::attemptRemove/$1/$2', 'SubscriptionController::attemptDelete/$1/$2',
[ [
'filter' => 'filter' =>
'permission:podcast-manage_subscriptions', 'permission:podcast-manage_subscriptions',

View File

@ -45,33 +45,15 @@ class LockController extends BaseController
public function index(): string public function index(): string
{ {
$locale = service('request') $data = [
->getLocale(); // TODO: metatags for locked premium podcasts
$cacheName = 'metatags' => '',
"page_podcast#{$this->podcast->id}_{$locale}_unlock" . 'podcast' => $this->podcast,
(can_user_interact() ? '_authenticated' : ''); ];
if (! ($cachedView = cache($cacheName))) { helper('form');
$data = [
// TODO: metatags for locked premium podcasts
'metatags' => '',
'podcast' => $this->podcast,
];
helper('form'); return view('podcast/unlock', $data);
if (can_user_interact()) {
return view('podcast/unlock', $data);
}
// The page cache is set to a decade so it is deleted manually upon podcast update
return view('podcast/unlock', $data, [
'cache' => DECADE,
'cache_name' => $cacheName,
]);
}
return $cachedView;
} }
public function attemptUnlock(): RedirectResponse public function attemptUnlock(): RedirectResponse

View File

@ -88,6 +88,10 @@ class SubscriptionController extends BaseController
service('settings') service('settings')
->set('Subscription.link', $subscriptionLink, 'podcast:' . $this->podcast->id); ->set('Subscription.link', $subscriptionLink, 'podcast:' . $this->podcast->id);
// clear cached podcast pages to render Call To Action
cache()
->deleteMatching("page_podcast#{$this->podcast->id}*");
return redirect()->route('subscription-list', [$this->podcast->id])->with( return redirect()->route('subscription-list', [$this->podcast->id])->with(
'message', 'message',
lang('Subscription.messages.linkSaveSuccess') lang('Subscription.messages.linkSaveSuccess')
@ -396,7 +400,7 @@ class SubscriptionController extends BaseController
); );
} }
public function remove(): string public function delete(): string
{ {
helper('form'); helper('form');
@ -412,7 +416,7 @@ class SubscriptionController extends BaseController
return view('subscription/delete', $data); return view('subscription/delete', $data);
} }
public function attemptRemove(): RedirectResponse public function attemptDelete(): RedirectResponse
{ {
$db = db_connect(); $db = db_connect();
$db->transStart(); $db->transStart();
@ -423,15 +427,15 @@ class SubscriptionController extends BaseController
$email = service('email'); $email = service('email');
if (! $email->setTo($this->subscription->email) if (! $email->setTo($this->subscription->email)
->setSubject(lang('Subscription.emails.removed_subject', [], $this->podcast->language_code)) ->setSubject(lang('Subscription.emails.deleted_subject', [], $this->podcast->language_code))
->setMessage(view('subscription/email/removed', [ ->setMessage(view('subscription/email/deleted', [
'subscription' => $this->subscription, 'subscription' => $this->subscription,
]))->setMailType('html') ]))->setMailType('html')
->send()) { ->send()) {
$db->transRollback(); $db->transRollback();
return redirect()->route('subscription-list', [$this->podcast->id])->with( return redirect()->route('subscription-list', [$this->podcast->id])->with(
'errors', 'errors',
[lang('Subscription.messages.removeError'), $email->printDebugger([])] [lang('Subscription.messages.deleteError'), $email->printDebugger([])]
); );
} }
@ -439,7 +443,7 @@ class SubscriptionController extends BaseController
return redirect()->route('subscription-list', [$this->podcast->id])->with( return redirect()->route('subscription-list', [$this->podcast->id])->with(
'messages', 'messages',
lang('Subscription.messages.removeSuccess', [ lang('Subscription.messages.deleteSuccess', [
'subscriber' => $this->subscription->email, 'subscriber' => $this->subscription->email,
]) ])
); );

View File

@ -60,8 +60,8 @@ return [
'editError' => 'Subscription could not be edited.', 'editError' => 'Subscription could not be edited.',
'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.',
'regenerateTokenError' => 'Token could not be regenerated.', 'regenerateTokenError' => 'Token could not be regenerated.',
'removeSuccess' => 'Subscription was canceled! An email was sent to {subscriber} to tell him.', 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.',
'removeError' => 'Subscription could not be canceled.', 'deleteError' => 'Subscription could not be removed.',
'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.',
'suspendError' => 'Subscription could not be suspended.', 'suspendError' => 'Subscription could not be suspended.',
'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.',
@ -93,8 +93,8 @@ return [
'suspended_reason' => 'That is for the following reason: {0}', 'suspended_reason' => 'That is for the following reason: {0}',
'resumed_subject' => 'Your subscription has been resumed!', 'resumed_subject' => 'Your subscription has been resumed!',
'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.',
'removed_subject' => 'Your subscription has been removed!', 'deleted_subject' => 'Your subscription has been removed!',
'removed' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.',
'footer' => '{castopod} hosted on {host}', 'footer' => '{castopod} hosted on {host}',
], ],
]; ];

View File

@ -1,6 +1,6 @@
<?= lang('Subscription.emails.greeting', [], $subscription->podcast->language_code) ?><br/><br/> <?= lang('Subscription.emails.greeting', [], $subscription->podcast->language_code) ?><br/><br/>
<?= lang('Subscription.emails.removed', [ <?= lang('Subscription.emails.deleted', [
'podcastTitle' => '<strong>' . $subscription->podcast->title . '</strong>', 'podcastTitle' => '<strong>' . $subscription->podcast->title . '</strong>',
], $subscription->podcast->language_code, false) ?> ], $subscription->podcast->language_code, false) ?>

View File

@ -94,7 +94,7 @@
[ [
'type' => 'link', 'type' => 'link',
'title' => lang('Subscription.delete'), 'title' => lang('Subscription.delete'),
'uri' => route_to('subscription-remove', $podcast->id, $subscription->id), 'uri' => route_to('subscription-delete', $podcast->id, $subscription->id),
'class' => 'font-semibold text-red-600', 'class' => 'font-semibold text-red-600',
], ],
]; ];

View File

@ -75,7 +75,7 @@
<header class="relative flex flex-col-reverse justify-between w-full col-start-2 bg-top bg-no-repeat bg-cover sm:flex-row sm:items-end bg-header aspect-[3/1]" style="background-image: url('<?= $podcast->banner->medium_url ?>');"> <header class="relative flex flex-col-reverse justify-between w-full col-start-2 bg-top bg-no-repeat bg-cover sm:flex-row sm:items-end bg-header aspect-[3/1]" style="background-image: url('<?= $podcast->banner->medium_url ?>');">
<div class="absolute bottom-0 left-0 w-full h-full backdrop-gradient mix-blend-multiply"></div> <div class="absolute bottom-0 left-0 w-full h-full backdrop-gradient mix-blend-multiply"></div>
<div class="flex items-center pl-4 -mb-6 md:pl-8 md:-mb-8 gap-x-4"> <div class="flex items-center pl-4 -mb-6 md:pl-8 md:-mb-8 gap-x-4">
<img src="<?= $podcast->cover->thumbnail_url ?>" alt="<?= esc($podcast->title) ?>" class="h-24 rounded-full sm:h-28 md:h-36 ring-3 ring-background-elevated aspect-square" loading="lazy" /> <img src="<?= $podcast->cover->thumbnail_url ?>" alt="<?= esc($podcast->title) ?>" class="z-[45] h-24 rounded-full sm:h-28 md:h-36 ring-3 ring-background-elevated aspect-square" loading="lazy" />
<div class="relative flex flex-col text-white -top-3 sm:top-0 md:top-2"> <div class="relative flex flex-col text-white -top-3 sm:top-0 md:top-2">
<h1 class="text-lg font-bold leading-none line-clamp-2 md:leading-none md:text-2xl font-display"><?= esc($podcast->title) ?><span class="ml-1 font-sans text-base font-normal">@<?= esc($podcast->handle) ?></span></h1> <h1 class="text-lg font-bold leading-none line-clamp-2 md:leading-none md:text-2xl font-display"><?= esc($podcast->title) ?><span class="ml-1 font-sans text-base font-normal">@<?= esc($podcast->handle) ?></span></h1>
<div class=""> <div class="">