From 9cec8a81ccbb7239402fe6633dbc31979272302a Mon Sep 17 00:00:00 2001 From: Yassine Doghri <yassine@doghri.fr> Date: Tue, 20 Oct 2020 10:31:40 +0000 Subject: [PATCH] fix(cache): add locale for podcast and episode pages + clear some persisting cache in models fixes #42, #61 --- app/Controllers/Episode.php | 11 +-- app/Controllers/Podcast.php | 6 +- app/Models/EpisodeModel.php | 181 +++++++++++++++++++---------------- app/Models/PageModel.php | 37 ++++++- app/Models/PlatformModel.php | 34 ++++++- app/Models/PodcastModel.php | 46 +++++++-- 6 files changed, 209 insertions(+), 106 deletions(-) diff --git a/app/Controllers/Episode.php b/app/Controllers/Episode.php index 8b3409014e..38c83da97d 100644 --- a/app/Controllers/Episode.php +++ b/app/Controllers/Episode.php @@ -44,11 +44,10 @@ class Episode extends BaseController { self::triggerWebpageHit($this->episode->podcast_id); - if ( - !($cachedView = cache( - "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}" - )) - ) { + $locale = service('request')->getLocale(); + $cacheName = "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}_{$locale}"; + + if (!($cachedView = cache($cacheName))) { $previousNextEpisodes = (new EpisodeModel())->getPreviousNextEpisodes( $this->episode, $this->podcast->type @@ -64,7 +63,7 @@ class Episode extends BaseController // The page cache is set to a decade so it is deleted manually upon podcast update return view('episode', $data, [ 'cache' => DECADE, - 'cache_name' => "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}", + 'cache_name' => $cacheName, ]); } diff --git a/app/Controllers/Podcast.php b/app/Controllers/Podcast.php index 27892cdb61..5d555f293e 100644 --- a/app/Controllers/Podcast.php +++ b/app/Controllers/Podcast.php @@ -58,15 +58,13 @@ class Podcast extends BaseController "podcast{$this->podcast->id}", $yearQuery, $seasonQuery ? 'season' . $seasonQuery : null, + service('request')->getLocale(), ]) ); if (!($found = cache($cacheName))) { - // The page cache is set to a decade so it is deleted manually upon podcast update - // $this->cachePage(DECADE); - $episodeModel = new EpisodeModel(); - // Build navigation array + $episodeModel = new EpisodeModel(); $years = $episodeModel->getYears($this->podcast->id); $seasons = $episodeModel->getSeasons($this->podcast->id); diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index 1bd2440b23..eb1e1f990d 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -76,54 +76,6 @@ class EpisodeModel extends Model return $data; } - protected function clearCache(array $data) - { - $episodeModel = new EpisodeModel(); - - $episode = $episodeModel->find( - is_array($data['id']) ? $data['id'][0] : $data['id'] - ); - - // delete cache for rss feed, podcast and episode pages - cache()->delete(md5($episode->podcast->feed_url)); - cache()->delete(md5($episode->podcast->link)); - cache()->delete(md5($episode->link)); - - // delete model requests cache - cache()->delete("podcast{$episode->podcast_id}_episodes"); - - // delete episode lists cache per year / season - $years = $episodeModel->getYears($episode->podcast_id); - $seasons = $episodeModel->getSeasons($episode->podcast_id); - - foreach ($years as $year) { - cache()->delete( - "podcast{$episode->podcast_id}_{$year['year']}_episodes" - ); - cache()->delete( - "page_podcast{$episode->podcast_id}_{$year['year']}" - ); - } - foreach ($seasons as $season) { - cache()->delete( - "podcast{$episode->podcast_id}_season{$season['season_number']}_episodes" - ); - cache()->delete( - "page_podcast{$episode->podcast_id}_season{$season['season_number']}" - ); - } - - cache()->delete("podcast{$episode->podcast_id}_defaultQuery"); - cache()->delete("podcast{$episode->podcast_id}_years"); - cache()->delete("podcast{$episode->podcast_id}_seasons"); - - cache()->delete( - "podcast{$episode->podcast_id}_episode@{$episode->slug}" - ); - - return $data; - } - public function getEpisodeBySlug($podcastId, $episodeSlug) { if (!($found = cache("podcast{$podcastId}_episode@{$episodeSlug}"))) { @@ -142,6 +94,47 @@ class EpisodeModel extends Model return $found; } + /** + * Returns the previous episode based on episode ordering + */ + public function getPreviousNextEpisodes($episode, $podcastType) + { + $sortNumberField = + $podcastType == 'serial' + ? 'if(isnull(season_number),0,season_number)*1000+number' + : 'if(isnull(season_number),0,season_number)*100000000000000+published_at'; + $sortNumberValue = + $podcastType == 'serial' + ? (empty($episode->season_number) + ? 0 + : $episode->season_number) * + 1000 + + $episode->number + : (empty($episode->season_number) + ? '' + : $episode->season_number) . + date('YmdHis', strtotime($episode->published_at)); + + $previousData = $this->orderBy('(' . $sortNumberField . ') DESC') + ->where([ + 'podcast_id' => $episode->podcast_id, + $sortNumberField . ' <' => $sortNumberValue, + ]) + ->first(); + + $nextData = $this->orderBy('(' . $sortNumberField . ') ASC') + ->where([ + 'podcast_id' => $episode->podcast_id, + $sortNumberField . ' >' => $sortNumberValue, + ]) + ->first(); + + return [ + 'previous' => $previousData, + 'next' => $nextData, + ]; + } + /** * Gets all episodes for a podcast ordered according to podcast type * Filtered depending on year or season @@ -239,6 +232,10 @@ class EpisodeModel extends Model /** * Returns the default query for displaying the episode list on the podcast page + * + * @param int $podcastId + * + * @return array */ public function getDefaultQuery(int $podcastId) { @@ -267,44 +264,62 @@ class EpisodeModel extends Model return $defaultQuery; } - /** - * Returns the previous episode based on episode ordering - */ - public function getPreviousNextEpisodes($episode, $podcastType) + protected function clearCache(array $data) { - $sortNumberField = - $podcastType == 'serial' - ? 'if(isnull(season_number),0,season_number)*1000+number' - : 'if(isnull(season_number),0,season_number)*100000000000000+published_at'; - $sortNumberValue = - $podcastType == 'serial' - ? (empty($episode->season_number) - ? 0 - : $episode->season_number) * - 1000 + - $episode->number - : (empty($episode->season_number) - ? '' - : $episode->season_number) . - date('YmdHis', strtotime($episode->published_at)); + $episodeModel = new EpisodeModel(); + $episode = (new EpisodeModel())->find( + is_array($data['id']) ? $data['id'][0] : $data['id'] + ); - $previousData = $this->orderBy('(' . $sortNumberField . ') DESC') - ->where([ - 'podcast_id' => $episode->podcast_id, - $sortNumberField . ' <' => $sortNumberValue, - ]) - ->first(); + // delete cache for rss feed + cache()->delete(md5($episode->podcast->feed_url)); - $nextData = $this->orderBy('(' . $sortNumberField . ') ASC') - ->where([ - 'podcast_id' => $episode->podcast_id, - $sortNumberField . ' >' => $sortNumberValue, - ]) - ->first(); + // delete model requests cache + cache()->delete("podcast{$episode->podcast_id}_episodes"); - return [ - 'previous' => $previousData, - 'next' => $nextData, - ]; + cache()->delete( + "podcast{$episode->podcast_id}_episode@{$episode->slug}" + ); + + // delete episode lists cache per year / season for a podcast + // and localized pages + $years = $episodeModel->getYears($episode->podcast_id); + $seasons = $episodeModel->getSeasons($episode->podcast_id); + $supportedLocales = config('App')->supportedLocales; + + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$episode->podcast->id}_episode{$episode->id}_{$locale}" + ); + } + + foreach ($years as $year) { + cache()->delete( + "podcast{$episode->podcast_id}_{$year['year']}_episodes" + ); + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$episode->podcast_id}_{$year['year']}_{$locale}" + ); + } + } + + foreach ($seasons as $season) { + cache()->delete( + "podcast{$episode->podcast_id}_season{$season['season_number']}_episodes" + ); + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$episode->podcast_id}_season{$season['season_number']}_{$locale}" + ); + } + } + + // delete query cache + cache()->delete("podcast{$episode->podcast_id}_defaultQuery"); + cache()->delete("podcast{$episode->podcast_id}_years"); + cache()->delete("podcast{$episode->podcast_id}_seasons"); + + return $data; } } diff --git a/app/Models/PageModel.php b/app/Models/PageModel.php index 8208ebe28b..c6a5e20784 100644 --- a/app/Models/PageModel.php +++ b/app/Models/PageModel.php @@ -30,7 +30,8 @@ class PageModel extends Model ]; protected $validationMessages = []; - // Before update because slug might change + // Before update because slug or title might change + protected $afterInsert = ['clearCache']; protected $beforeUpdate = ['clearCache']; protected $beforeDelete = ['clearCache']; @@ -44,8 +45,38 @@ class PageModel extends Model cache()->delete(md5($page->link)); // Clear the cache of all podcast and episode pages - // TODO: change the logic of page caching to prevent clearing all cache every time - // cache()->clean(); + $allPodcasts = (new PodcastModel())->findAll(); + + foreach ($allPodcasts as $podcast) { + // delete localized podcast and episode page cache + $episodeModel = new EpisodeModel(); + $years = $episodeModel->getYears($podcast->id); + $seasons = $episodeModel->getSeasons($podcast->id); + $supportedLocales = config('App')->supportedLocales; + + foreach ($years as $year) { + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcast->id}_{$year['year']}_{$locale}" + ); + } + } + foreach ($seasons as $season) { + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcast->id}_season{$season['season_number']}_{$locale}" + ); + } + } + + foreach ($podcast->episodes as $episode) { + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcast->id}_episode{$episode->id}_{$locale}" + ); + } + } + } return $data; } diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php index cb24ad1a1e..abba0a525f 100644 --- a/app/Models/PlatformModel.php +++ b/app/Models/PlatformModel.php @@ -76,8 +76,7 @@ class PlatformModel extends Model public function savePlatformLinks($podcastId, $platformLinksData) { - cache()->delete("podcast{$podcastId}_platforms"); - cache()->delete("podcast{$podcastId}_platformLinks"); + $this->clearCache($podcastId); // Remove already previously set platforms to overwrite them $this->db @@ -109,12 +108,39 @@ class PlatformModel extends Model public function removePlatformLink($podcastId, $platformId) { - cache()->delete("podcast{$podcastId}_platforms"); - cache()->delete("podcast{$podcastId}_platformLinks"); + $this->clearCache($podcastId); return $this->db->table('platform_links')->delete([ 'podcast_id' => $podcastId, 'platform_id' => $platformId, ]); } + + public function clearCache($podcastId) + { + cache()->delete("podcast{$podcastId}_platforms"); + cache()->delete("podcast{$podcastId}_platformLinks"); + + // delete localized podcast page cache + $episodeModel = new EpisodeModel(); + $years = $episodeModel->getYears($podcastId); + $seasons = $episodeModel->getSeasons($podcastId); + $supportedLocales = config('App')->supportedLocales; + + foreach ($years as $year) { + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcastId}_{$year['year']}_{$locale}" + ); + } + } + + foreach ($seasons as $season) { + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcastId}_season{$season['season_number']}_{$locale}" + ); + } + } + } } diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index 84b26e6ba7..bb92d0e926 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -170,20 +170,54 @@ class PodcastModel extends Model $podcast = (new PodcastModel())->getPodcastById( is_array($data['id']) ? $data['id'][0] : $data['id'] ); + $supportedLocales = config('App')->supportedLocales; // delete cache for rss feed and podcast pages cache()->delete(md5($podcast->feed_url)); - cache()->delete(md5($podcast->link)); - - // clear cache for every podcast's episode page? - foreach ($podcast->episodes as $episode) { - cache()->delete(md5($episode->link)); - } // delete model requests cache cache()->delete("podcast{$podcast->id}"); cache()->delete("podcast@{$podcast->name}"); + // clear cache for every localized podcast episode page + foreach ($podcast->episodes as $episode) { + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcast->id}_episode{$episode->id}_{$locale}" + ); + } + } + + // delete episode lists cache per year / season + // and localized pages + $episodeModel = new EpisodeModel(); + $years = $episodeModel->getYears($podcast->id); + $seasons = $episodeModel->getSeasons($podcast->id); + + foreach ($years as $year) { + cache()->delete("podcast{$podcast->id}_{$year['year']}_episodes"); + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcast->id}_{$year['year']}_{$locale}" + ); + } + } + foreach ($seasons as $season) { + cache()->delete( + "podcast{$podcast->id}_season{$season['season_number']}_episodes" + ); + foreach ($supportedLocales as $locale) { + cache()->delete( + "page_podcast{$podcast->id}_season{$season['season_number']}_{$locale}" + ); + } + } + + // delete query cache + cache()->delete("podcast{$podcast->id}_defaultQuery"); + cache()->delete("podcast{$podcast->id}_years"); + cache()->delete("podcast{$podcast->id}_seasons"); + return $data; } } -- GitLab