From 54b84f96843af13f579fea49102c8c2ef81b0a54 Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Tue, 20 Apr 2021 13:43:38 +0000 Subject: [PATCH] perf(cache): update CI4 to use cache's deleteMatching method add missing locale to category_options cache name --- .devcontainer/devcontainer.json | 27 ++-- INSTALL.md | 9 +- app/Authorization/PermissionModel.php | 7 +- app/Config/App.php | 29 +++- app/Config/Cookie.php | 119 ++++++++++++++ app/Config/Routes.php | 2 +- app/Controllers/Admin/EpisodePerson.php | 10 +- app/Controllers/Admin/PodcastPerson.php | 10 +- app/Controllers/Episode.php | 4 +- app/Controllers/Feed.php | 8 +- app/Controllers/Page.php | 31 ++-- app/Controllers/Podcast.php | 21 +-- app/Entities/Episode.php | 2 +- app/Entities/Podcast.php | 2 +- app/Language/en/Install.php | 2 +- app/Language/en/Validation.php | 2 - app/Language/fr/Install.php | 2 +- app/Language/fr/Validation.php | 2 - app/Models/CategoryModel.php | 26 ++-- app/Models/EpisodeModel.php | 196 ++++-------------------- app/Models/EpisodePersonModel.php | 44 ++---- app/Models/PageModel.php | 44 +----- app/Models/PersonModel.php | 23 ++- app/Models/PlatformModel.php | 76 ++------- app/Models/PodcastModel.php | 184 ++++++++++++++-------- app/Models/PodcastPersonModel.php | 23 ++- app/Models/SoundbiteModel.php | 26 ++-- app/Models/UserModel.php | 5 +- app/Validation/Rules.php | 20 --- app/Views/install/cache_config.php | 2 +- composer.lock | 88 +++++------ 31 files changed, 486 insertions(+), 560 deletions(-) create mode 100644 app/Config/Cookie.php diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4422b82f..45fcd1c0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,17 +13,18 @@ "color-highlight.markerType": "dot-before" }, "extensions": [ - "mikestead.dotenv", - "bmewburn.vscode-intelephense-client", - "streetsidesoftware.code-spell-checker", - "naumovs.color-highlight", - "heybourn.headwind", - "wayou.vscode-todo-highlight", - "esbenp.prettier-vscode", - "bradlc.vscode-tailwindcss", - "jamesbirtles.svelte-vscode", - "dbaeumer.vscode-eslint", - "stylelint.vscode-stylelint", - "wongjn.php-sniffer" - ] + "mikestead.dotenv", + "bmewburn.vscode-intelephense-client", + "streetsidesoftware.code-spell-checker", + "naumovs.color-highlight", + "heybourn.headwind", + "wayou.vscode-todo-highlight", + "esbenp.prettier-vscode", + "bradlc.vscode-tailwindcss", + "jamesbirtles.svelte-vscode", + "dbaeumer.vscode-eslint", + "stylelint.vscode-stylelint", + "wongjn.php-sniffer", + "eamodio.gitlens" +] } diff --git a/INSTALL.md b/INSTALL.md index efc5f995..74651395 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -50,15 +50,16 @@ Before uploading Castopod files to your web server: PHP version 7.3 or higher is required, with the following extensions installed: -- [intl](http://php.net/manual/en/intl.requirements.php) -- [libcurl](http://php.net/manual/en/curl.requirements.php) -- [mbstring](http://php.net/manual/en/mbstring.installation.php) +- [intl](https://php.net/manual/en/intl.requirements.php) +- [libcurl](https://php.net/manual/en/curl.requirements.php) +- [mbstring](https://php.net/manual/en/mbstring.installation.php) +- [gd](https://www.php.net/manual/en/image.installation.php) Additionally, make sure that the following extensions are enabled in your PHP: - json (enabled by default - don't turn it off) - xml (enabled by default - don't turn it off) -- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php) +- [mysqlnd](https://php.net/manual/en/mysqlnd.install.php) ### MySQL compatible database diff --git a/app/Authorization/PermissionModel.php b/app/Authorization/PermissionModel.php index f60fe7d6..c15f4412 100644 --- a/app/Authorization/PermissionModel.php +++ b/app/Authorization/PermissionModel.php @@ -39,14 +39,15 @@ class PermissionModel extends \Myth\Auth\Authorization\PermissionModel */ public function getPermissionsForGroup(int $groupId): array { - if (!($found = cache("group{$groupId}_permissions"))) { + $cacheName = "group{$groupId}_permissions"; + if (!($found = cache($cacheName))) { $groupPermissions = $this->db ->table('auth_groups_permissions') ->select('id, auth_permissions.name') ->join( 'auth_permissions', 'auth_permissions.id = permission_id', - 'inner' + 'inner', ) ->where('group_id', $groupId) ->get() @@ -57,7 +58,7 @@ class PermissionModel extends \Myth\Auth\Authorization\PermissionModel $found[$row->id] = strtolower($row->name); } - cache()->save("group{$groupId}_permissions", $found, 300); + cache()->save($cacheName, $found, 300); } return $found; diff --git a/app/Config/App.php b/app/Config/App.php index 5e9e88b8..75b98699 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -253,6 +253,8 @@ class App extends BaseConfig * Set a cookie name prefix if you need to avoid collisions. * * @var string + * + * @deprecated use Config\Cookie::$prefix property instead. */ public $cookiePrefix = ''; @@ -264,6 +266,8 @@ class App extends BaseConfig * Set to `.your-domain.com` for site-wide cookies. * * @var string + * + * @deprecated use Config\Cookie::$domain property instead. */ public $cookieDomain = ''; @@ -275,6 +279,8 @@ class App extends BaseConfig * Typically will be a forward slash. * * @var string + * + * @deprecated use Config\Cookie::$path property instead. */ public $cookiePath = '/'; @@ -286,19 +292,23 @@ class App extends BaseConfig * Cookie will only be set if a secure HTTPS connection exists. * * @var boolean + * + * @deprecated use Config\Cookie::$secure property instead. */ public $cookieSecure = false; /** * -------------------------------------------------------------------------- - * Cookie HTTP Only + * Cookie HttpOnly * -------------------------------------------------------------------------- * * Cookie will only be accessible via HTTP(S) (no JavaScript). * * @var boolean + * + * @deprecated use Config\Cookie::$httponly property instead. */ - public $cookieHTTPOnly = false; + public $cookieHTTPOnly = true; /** * -------------------------------------------------------------------------- @@ -311,11 +321,18 @@ class App extends BaseConfig * - Strict * - '' * - * Defaults to `Lax` for compatibility with modern browsers. Setting `''` - * (empty string) means no SameSite attribute will be set on cookies. If - * set to `None`, `$cookieSecure` must also be set. + * Alternatively, you can use the constant names: + * - `Cookie::SAMESITE_NONE` + * - `Cookie::SAMESITE_LAX` + * - `Cookie::SAMESITE_STRICT` * - * @var string 'Lax'|'None'|'Strict' + * Defaults to `Lax` for compatibility with modern browsers. Setting `''` + * (empty string) means default SameSite attribute set by browsers (`Lax`) + * will be set on cookies. If set to `None`, `$cookieSecure` must also be set. + * + * @var string + * + * @deprecated use Config\Cookie::$samesite property instead. */ public $cookieSameSite = 'Lax'; diff --git a/app/Config/Cookie.php b/app/Config/Cookie.php new file mode 100644 index 00000000..68c403e5 --- /dev/null +++ b/app/Config/Cookie.php @@ -0,0 +1,119 @@ +group('@(:podcastName)', function ($routes) { // Other pages $routes->get('/credits', 'Page::credits', ['as' => 'credits']); -$routes->get('/(:slug)', 'Page/$1', ['as' => 'page']); +$routes->get('/pages/(:slug)', 'Page/$1', ['as' => 'page']); // interacting as an actor $routes->post('interact-as-actor', 'Auth::attemptInteractAsActor', [ diff --git a/app/Controllers/Admin/EpisodePerson.php b/app/Controllers/Admin/EpisodePerson.php index 9d35dd9c..e6ccca64 100644 --- a/app/Controllers/Admin/EpisodePerson.php +++ b/app/Controllers/Admin/EpisodePerson.php @@ -30,7 +30,7 @@ class EpisodePerson extends BaseController if (count($params) > 1) { if ( !($this->podcast = (new PodcastModel())->getPodcastById( - $params[0] + $params[0], )) ) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); @@ -61,9 +61,9 @@ class EpisodePerson extends BaseController $data = [ 'episode' => $this->episode, 'podcast' => $this->podcast, - 'episodePersons' => (new EpisodePersonModel())->getPersonsByEpisodeId( + 'episodePersons' => (new EpisodePersonModel())->getEpisodePersons( $this->podcast->id, - $this->episode->id + $this->episode->id, ), 'personOptions' => (new PersonModel())->getPersonOptions(), 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), @@ -92,7 +92,7 @@ class EpisodePerson extends BaseController $this->podcast->id, $this->episode->id, $this->request->getPost('person'), - $this->request->getPost('person_group_role') + $this->request->getPost('person_group_role'), ); return redirect()->back(); @@ -103,7 +103,7 @@ class EpisodePerson extends BaseController (new EpisodePersonModel())->removeEpisodePersons( $this->podcast->id, $this->episode->id, - $episodePersonId + $episodePersonId, ); return redirect()->back(); diff --git a/app/Controllers/Admin/PodcastPerson.php b/app/Controllers/Admin/PodcastPerson.php index 67603700..4da46dbd 100644 --- a/app/Controllers/Admin/PodcastPerson.php +++ b/app/Controllers/Admin/PodcastPerson.php @@ -24,7 +24,7 @@ class PodcastPerson extends BaseController if (count($params) > 0) { if ( !($this->podcast = (new PodcastModel())->getPodcastById( - $params[0] + $params[0], )) ) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); @@ -43,8 +43,8 @@ class PodcastPerson extends BaseController $data = [ 'podcast' => $this->podcast, - 'podcastPersons' => (new PodcastPersonModel())->getPersonsByPodcastId( - $this->podcast->id + 'podcastPersons' => (new PodcastPersonModel())->getPodcastPersons( + $this->podcast->id, ), 'personOptions' => (new PersonModel())->getPersonOptions(), 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), @@ -71,7 +71,7 @@ class PodcastPerson extends BaseController (new PodcastPersonModel())->addPodcastPersons( $this->podcast->id, $this->request->getPost('person'), - $this->request->getPost('person_group_role') + $this->request->getPost('person_group_role'), ); return redirect()->back(); @@ -81,7 +81,7 @@ class PodcastPerson extends BaseController { (new PodcastPersonModel())->removePodcastPersons( $this->podcast->id, - $podcastPersonId + $podcastPersonId, ); return redirect()->back(); diff --git a/app/Controllers/Episode.php b/app/Controllers/Episode.php index b791a6b0..8448e756 100644 --- a/app/Controllers/Episode.php +++ b/app/Controllers/Episode.php @@ -47,7 +47,7 @@ class Episode extends BaseController self::triggerWebpageHit($this->podcast->id); $locale = service('request')->getLocale(); - $cacheName = "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}_{$locale}"; + $cacheName = "page_podcast#{$this->podcast->id}_episode{$this->episode->id}_{$locale}"; if (!($cachedView = cache($cacheName))) { helper('persons'); @@ -107,7 +107,7 @@ class Episode extends BaseController $locale = service('request')->getLocale(); - $cacheName = "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}_embeddable_player_{$theme}_{$locale}"; + $cacheName = "page_podcast#{$this->podcast->id}_episode{$this->episode->id}_embeddable_player_{$theme}_{$locale}"; if (!($cachedView = cache($cacheName))) { $theme = EpisodeModel::$themes[$theme]; diff --git a/app/Controllers/Feed.php b/app/Controllers/Feed.php index 77bfcbfe..3225e5f2 100644 --- a/app/Controllers/Feed.php +++ b/app/Controllers/Feed.php @@ -26,7 +26,7 @@ class Feed extends Controller $serviceSlug = ''; try { $service = \Opawg\UserAgentsPhp\UserAgentsRSS::find( - $_SERVER['HTTP_USER_AGENT'] + $_SERVER['HTTP_USER_AGENT'], ); if ($service) { $serviceSlug = $service['slug']; @@ -37,14 +37,14 @@ class Feed extends Controller } $cacheName = - "podcast{$podcast->id}_feed" . ($service ? "_{$serviceSlug}" : ''); + "podcast#{$podcast->id}_feed" . ($service ? "_{$serviceSlug}" : ''); if (!($found = cache($cacheName))) { $found = get_rss_feed($podcast, $serviceSlug); // The page cache is set to expire after next episode publication or a decade by default so it is deleted manually upon podcast update $secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode( - $podcast->id + $podcast->id, ); cache()->save( @@ -52,7 +52,7 @@ class Feed extends Controller $found, $secondsToNextUnpublishedEpisode ? $secondsToNextUnpublishedEpisode - : DECADE + : DECADE, ); } return $this->response->setXML($found); diff --git a/app/Controllers/Page.php b/app/Controllers/Page.php index 46d28d22..8f97b5de 100644 --- a/app/Controllers/Page.php +++ b/app/Controllers/Page.php @@ -36,37 +36,42 @@ class Page extends BaseController public function index() { - // The page cache is set to a decade so it is deleted manually upon page update - $this->cachePage(DECADE); + $cacheName = "page@{$this->page->slug}"; + if (!($found = cache($cacheName))) { + $data = [ + 'page' => $this->page, + ]; - $data = [ - 'page' => $this->page, - ]; - return view('page', $data); + $found = view('page', $data); + + // The page cache is set to a decade so it is deleted manually upon page update + cache()->save($cacheName, $found, DECADE); + } + + return $found; } public function credits() { $locale = service('request')->getLocale(); - $model = new PodcastModel(); - $allPodcasts = $model->findAll(); + $allPodcasts = (new PodcastModel())->findAll(); - if (!($found = cache("credits_{$locale}"))) { + $cacheName = "paĝe_credits_{$locale}"; + if (!($found = cache($cacheName))) { $page = new \App\Entities\Page([ 'title' => lang('Person.credits', [], $locale), 'slug' => 'credits', 'content' => '', ]); - $creditModel = (new CreditModel())->findAll(); + $allCredits = (new CreditModel())->findAll(); // Unlike the carpenter, we make a tree from a table: - $person_group = null; $person_id = null; $person_role = null; $credits = []; - foreach ($creditModel as $credit) { + foreach ($allCredits as $credit) { if ($person_group !== $credit->person_group) { $person_group = $credit->person_group; $person_id = $credit->person_id; @@ -200,7 +205,7 @@ class Page extends BaseController $found = view('credits', $data); - cache()->save("credits_{$locale}", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; diff --git a/app/Controllers/Podcast.php b/app/Controllers/Podcast.php index ef11e954..2b351e73 100644 --- a/app/Controllers/Podcast.php +++ b/app/Controllers/Podcast.php @@ -68,7 +68,7 @@ class Podcast extends BaseController $seasonQuery = $this->request->getGet('season'); if (!$yearQuery and !$seasonQuery) { - $defaultQuery = (new EpisodeModel())->getDefaultQuery( + $defaultQuery = (new PodcastModel())->getDefaultQuery( $this->podcast->id, ); if ($defaultQuery) { @@ -84,18 +84,19 @@ class Podcast extends BaseController '_', array_filter([ 'page', - "podcast{$this->podcast->id}", + "podcast#{$this->podcast->id}", $yearQuery ? 'year' . $yearQuery : null, $seasonQuery ? 'season' . $seasonQuery : null, service('request')->getLocale(), + can_user_interact() ? '_interact' : '', ]), ); if (!($found = cache($cacheName))) { // Build navigation array - $episodeModel = new EpisodeModel(); - $years = $episodeModel->getYears($this->podcast->id); - $seasons = $episodeModel->getSeasons($this->podcast->id); + $podcastModel = new PodcastModel(); + $years = $podcastModel->getYears($this->podcast->id); + $seasons = $podcastModel->getSeasons($this->podcast->id); $episodesNavigation = []; $activeQuery = null; @@ -155,7 +156,7 @@ class Podcast extends BaseController 'podcast' => $this->podcast, 'episodesNav' => $episodesNavigation, 'activeQuery' => $activeQuery, - 'episodes' => $episodeModel->getPodcastEpisodes( + 'episodes' => (new EpisodeModel())->getPodcastEpisodes( $this->podcast->id, $this->podcast->type, $yearQuery, @@ -164,20 +165,20 @@ class Podcast extends BaseController 'persons' => $persons, ]; - $secondsToNextUnpublishedEpisode = $episodeModel->getSecondsToNextUnpublishedEpisode( + $secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode( $this->podcast->id, ); // if user is logged in then send to the authenticated episodes view if (can_user_interact()) { - return view('podcast/episodes_authenticated', $data, [ + $found = view('podcast/episodes_authenticated', $data, [ 'cache' => $secondsToNextUnpublishedEpisode ? $secondsToNextUnpublishedEpisode : DECADE, - 'cache_name' => $cacheName . '_authenticated', + 'cache_name' => $cacheName, ]); } else { - return view('podcast/episodes', $data, [ + $found = view('podcast/episodes', $data, [ 'cache' => $secondsToNextUnpublishedEpisode ? $secondsToNextUnpublishedEpisode : DECADE, diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php index e7fdac99..d0cdf642 100644 --- a/app/Entities/Episode.php +++ b/app/Entities/Episode.php @@ -385,7 +385,7 @@ class Episode extends Entity } if (empty($this->persons)) { - $this->persons = (new EpisodePersonModel())->getPersonsByEpisodeId( + $this->persons = (new EpisodePersonModel())->getEpisodePersons( $this->podcast_id, $this->id, ); diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index 82922b2d..8bce314e 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -232,7 +232,7 @@ class Podcast extends Entity } if (empty($this->persons)) { - $this->persons = (new PodcastPersonModel())->getPersonsByPodcastId( + $this->persons = (new PodcastPersonModel())->getPodcastPersons( $this->id, ); } diff --git a/app/Language/en/Install.php b/app/Language/en/Install.php index 5a5af49e..b4428f8d 100644 --- a/app/Language/en/Install.php +++ b/app/Language/en/Install.php @@ -39,7 +39,7 @@ return [ 'cacheHandlerOptions' => [ 'file' => 'File', 'redis' => 'Redis', - 'memcached' => 'Memcached', + 'predis' => 'Predis', ], 'next' => 'Next', 'submit' => 'Finish install', diff --git a/app/Language/en/Validation.php b/app/Language/en/Validation.php index 4fb15636..fb27793e 100644 --- a/app/Language/en/Validation.php +++ b/app/Language/en/Validation.php @@ -7,8 +7,6 @@ */ return [ - 'not_in_protected_slugs' => - 'The {field} field conflicts with one of the gateway routes (admin, auth or install).', 'min_dims' => '{field} is either not an image, or it is not wide or tall enough.', 'is_image_squared' => diff --git a/app/Language/fr/Install.php b/app/Language/fr/Install.php index e721ebb4..92640320 100644 --- a/app/Language/fr/Install.php +++ b/app/Language/fr/Install.php @@ -39,7 +39,7 @@ return [ 'cacheHandlerOptions' => [ 'file' => 'Fichiers', 'redis' => 'Redis', - 'memcached' => 'Memcached', + 'predis' => 'Predis', ], 'next' => 'Suivant', 'submit' => 'Terminer l’installation', diff --git a/app/Language/fr/Validation.php b/app/Language/fr/Validation.php index d9ae5dc5..519fbe9a 100644 --- a/app/Language/fr/Validation.php +++ b/app/Language/fr/Validation.php @@ -7,8 +7,6 @@ */ return [ - 'not_in_protected_slugs' => - 'Le champ {field} est en conflit avec une des routes (admin, auth ou install).', 'min_dims' => '{field} n’est pas une image ou n’a pas la taille minimale requise.', 'is_image_squared' => diff --git a/app/Models/CategoryModel.php b/app/Models/CategoryModel.php index 6764f6ed..6fc150c4 100644 --- a/app/Models/CategoryModel.php +++ b/app/Models/CategoryModel.php @@ -34,21 +34,24 @@ class CategoryModel extends Model public function getCategoryOptions() { - if (!($options = cache('category_options'))) { + $locale = service('request')->getLocale(); + $cacheName = "category_options_{$locale}"; + + if (!($options = cache($cacheName))) { $categories = $this->findAll(); $options = array_reduce( $categories, function ($result, $category) { $result[$category->id] = lang( - 'Podcast.category_options.' . $category->code + 'Podcast.category_options.' . $category->code, ); return $result; }, - [] + [], ); - cache()->save('category_options', $options, DECADE); + cache()->save($cacheName, $options, DECADE); } return $options; @@ -64,7 +67,7 @@ class CategoryModel extends Model */ public function setPodcastCategories($podcastId, $categories) { - cache()->delete("podcasts{$podcastId}_categories"); + cache()->delete("podcast#{$podcastId}_categories"); // Remove already previously set categories to overwrite them $this->db @@ -83,7 +86,7 @@ class CategoryModel extends Model return $result; }, - [] + [], ); // Set podcast categories @@ -103,20 +106,17 @@ class CategoryModel extends Model */ public function getPodcastCategories($podcastId) { - if (!($categories = cache("podcasts{$podcastId}_categories"))) { + $cacheName = "podcast#{$podcastId}_categories"; + if (!($categories = cache($cacheName))) { $categories = $this->select('categories.*') ->join( 'podcasts_categories', - 'podcasts_categories.category_id = categories.id' + 'podcasts_categories.category_id = categories.id', ) ->where('podcasts_categories.podcast_id', $podcastId) ->findAll(); - cache()->save( - "podcasts{$podcastId}_categories", - $categories, - DECADE - ); + cache()->save($cacheName, $categories, DECADE); } return $categories; diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index 7fd8c5b2..93603482 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -113,7 +113,8 @@ class EpisodeModel extends Model */ public function getEpisodeBySlug($podcastId, $episodeSlug) { - if (!($found = cache("podcast@{$podcastId}_episode@{$episodeSlug}"))) { + $cacheName = "podcast#{$podcastId}_episode@{$episodeSlug}"; + if (!($found = cache($cacheName))) { $builder = $this->select('episodes.*') ->where('slug', $episodeSlug) ->where('`published_at` <= NOW()', null, false); @@ -130,11 +131,7 @@ class EpisodeModel extends Model $found = $builder->first(); - cache()->save( - "podcast{$podcastId}_episode@{$episodeSlug}", - $found, - DECADE, - ); + cache()->save($cacheName, $found, DECADE); } return $found; @@ -142,14 +139,15 @@ class EpisodeModel extends Model public function getEpisodeById($episodeId) { - if (!($found = cache("podcast_episode{$episodeId}"))) { + $cacheName = "podcast_episode#{$episodeId}"; + if (!($found = cache($cacheName))) { $builder = $this->where([ 'id' => $episodeId, ]); $found = $builder->first(); - cache()->save("podcast_episode{$episodeId}", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; @@ -157,7 +155,8 @@ class EpisodeModel extends Model public function getPublishedEpisodeById($episodeId, $podcastId = null) { - if (!($found = cache("podcast{$podcastId}_episode{$episodeId}"))) { + $cacheName = "podcast_episode#{$episodeId}_published"; + if (!($found = cache($cacheName))) { $builder = $this->where([ 'id' => $episodeId, ])->where('`published_at` <= NOW()', null, false); @@ -168,11 +167,7 @@ class EpisodeModel extends Model $found = $builder->first(); - cache()->save( - "podcast{$podcastId}_episode{$episodeId}", - $found, - DECADE, - ); + cache()->save($cacheName, $found, DECADE); } return $found; @@ -195,7 +190,7 @@ class EpisodeModel extends Model $cacheName = implode( '_', array_filter([ - "podcast{$podcastId}", + "podcast#{$podcastId}", $year, $season ? 'season' . $season : null, 'episodes', @@ -243,106 +238,6 @@ class EpisodeModel extends Model return $found; } - public function getYears(int $podcastId): array - { - if (!($found = cache("podcast{$podcastId}_years"))) { - $found = $this->select( - 'YEAR(published_at) as year, count(*) as number_of_episodes', - ) - ->where([ - 'podcast_id' => $podcastId, - 'season_number' => null, - $this->deletedField => null, - ]) - ->where('`published_at` <= NOW()', null, false) - ->groupBy('year') - ->orderBy('year', 'DESC') - ->get() - ->getResultArray(); - - $secondsToNextUnpublishedEpisode = $this->getSecondsToNextUnpublishedEpisode( - $podcastId, - ); - - cache()->save( - "podcast{$podcastId}_years", - $found, - $secondsToNextUnpublishedEpisode - ? $secondsToNextUnpublishedEpisode - : DECADE, - ); - } - - return $found; - } - - public function getSeasons(int $podcastId): array - { - if (!($found = cache("podcast{$podcastId}_seasons"))) { - $found = $this->select( - 'season_number, count(*) as number_of_episodes', - ) - ->where([ - 'podcast_id' => $podcastId, - 'season_number is not' => null, - $this->deletedField => null, - ]) - ->where('`published_at` <= NOW()', null, false) - ->groupBy('season_number') - ->orderBy('season_number', 'ASC') - ->get() - ->getResultArray(); - - $secondsToNextUnpublishedEpisode = $this->getSecondsToNextUnpublishedEpisode( - $podcastId, - ); - - cache()->save( - "podcast{$podcastId}_seasons", - $found, - $secondsToNextUnpublishedEpisode - ? $secondsToNextUnpublishedEpisode - : DECADE, - ); - } - - return $found; - } - - /** - * Returns the default query for displaying the episode list on the podcast page - * - * @param int $podcastId - * - * @return array|null - */ - public function getDefaultQuery(int $podcastId) - { - if (!($defaultQuery = cache("podcast{$podcastId}_defaultQuery"))) { - $seasons = $this->getSeasons($podcastId); - - if (!empty($seasons)) { - // get latest season - $defaultQuery = ['type' => 'season', 'data' => end($seasons)]; - } else { - $years = $this->getYears($podcastId); - if (!empty($years)) { - // get most recent year - $defaultQuery = ['type' => 'year', 'data' => $years[0]]; - } else { - $defaultQuery = null; - } - } - - cache()->save( - "podcast{$podcastId}_defaultQuery", - $defaultQuery, - DECADE, - ); - } - return $defaultQuery; - } - /** * Returns the timestamp difference in seconds between the next episode to publish and the current timestamp * Returns false if there's no episode to publish @@ -387,70 +282,37 @@ class EpisodeModel extends Model ); // delete cache for rss feed - cache()->delete("podcast{$episode->podcast_id}_feed"); - foreach (\Opawg\UserAgentsPhp\UserAgentsRSS::$db as $service) { - cache()->delete( - "podcast{$episode->podcast_id}_feed_{$service['slug']}", - ); - } + cache()->deleteMatching("podcast#{$episode->podcast_id}_feed*"); // delete model requests cache - cache()->delete("podcast{$episode->podcast_id}_episodes"); + cache()->delete("podcast#{$episode->podcast_id}_episodes"); + cache()->deleteMatching("podcast_episode#{$episode->id}*"); cache()->delete( - "podcast{$episode->podcast_id}_episode@{$episode->slug}", + "podcast#{$episode->podcast_id}_episode@{$episode->slug}", ); - cache()->delete("podcast_episode{$episode->id}"); + cache()->deleteMatching( + "page_podcast#{$episode->podcast_id}_episode#{$episode->id}_*", + ); + cache()->deleteMatching('page_credits_*'); - // delete episode lists cache per year / season for a podcast - // and localized pages - $episodeModel = new EpisodeModel(); - $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}", + if ($episode->season_number) { + cache()->deleteMatching("podcast#{$episode->podcast_id}_season*"); + cache()->deleteMatching( + "page_podcast#{$episode->podcast_id}_season*", ); - cache()->delete("credits_{$locale}"); - } - - foreach ($years as $year) { - cache()->delete( - "podcast{$episode->podcast_id}_year{$year['year']}_episodes", + } else { + cache()->deleteMatching("podcast#{$episode->podcast_id}_year*"); + cache()->deleteMatching( + "page_podcast#{$episode->podcast_id}_year*", ); - foreach ($supportedLocales as $locale) { - cache()->delete( - "page_podcast{$episode->podcast_id}_year{$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}", - ); - } - } - - foreach (array_keys(self::$themes) as $themeKey) { - foreach ($supportedLocales as $locale) { - cache()->delete( - "page_podcast{$episode->podcast_id}_episode{$episode->id}_embeddable_player_{$themeKey}_{$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"); + 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/EpisodePersonModel.php b/app/Models/EpisodePersonModel.php index 1ed80d1e..8df81e10 100644 --- a/app/Models/EpisodePersonModel.php +++ b/app/Models/EpisodePersonModel.php @@ -38,27 +38,17 @@ class EpisodePersonModel extends Model protected $afterInsert = ['clearCache']; protected $beforeDelete = ['clearCache']; - public function getPersonsByEpisodeId($podcastId, $episodeId) + public function getEpisodePersons($episodeId) { - if ( - !($found = cache( - "podcast{$podcastId}_episodes{$episodeId}_persons" - )) - ) { + $cacheName = "podcast_episode#{$episodeId}_persons"; + if (!($found = cache($cacheName))) { $found = $this->select('episodes_persons.*') ->where('episode_id', $episodeId) - ->join( - 'persons', - 'person_id=persons.id' - ) + ->join('persons', 'person_id=persons.id') ->orderby('full_name') ->findAll(); - cache()->save( - "podcast{$podcastId}_episodes{$episodeId}_persons", - $found, - DECADE - ); + cache()->save($cacheName, $found, DECADE); } return $found; } @@ -81,11 +71,9 @@ class EpisodePersonModel extends Model ) { if (!empty($persons)) { $this->clearCache([ - 'id' => [ - 'podcast_id' => $podcastId, - 'episode_id' => $episodeId, - ], + 'episode_id' => $episodeId, ]); + $data = []; foreach ($persons as $person) { if ($groups_roles) { @@ -126,23 +114,17 @@ class EpisodePersonModel extends Model protected function clearCache(array $data) { - $podcastId = null; $episodeId = null; - if ( - isset($data['id']['podcast_id']) && - isset($data['id']['episode_id']) - ) { - $podcastId = $data['id']['podcast_id']; - $episodeId = $data['id']['episode_id']; + if (isset($data['episode_id'])) { + $episodeId = $data['episode_id']; } else { - $episodePerson = (new EpisodePersonModel())->find( - is_array($data['id']) ? $data['id']['id'] : $data['id'] + $person = (new EpisodePersonModel())->find( + is_array($data['id']) ? $data['id']['id'] : $data['id'], ); - $podcastId = $episodePerson->podcast_id; - $episodeId = $episodePerson->episode_id; + $episodeId = $person->episode_id; } - cache()->delete("podcast{$podcastId}_episodes{$episodeId}_persons"); + cache()->delete("podcast_episode#{$episodeId}_persons"); (new EpisodeModel())->clearCache(['id' => $episodeId]); return $data; diff --git a/app/Models/PageModel.php b/app/Models/PageModel.php index d3740ead..c045ca0c 100644 --- a/app/Models/PageModel.php +++ b/app/Models/PageModel.php @@ -25,7 +25,7 @@ class PageModel extends Model protected $validationRules = [ 'title' => 'required', 'slug' => - 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]|is_unique[pages.slug,id,{id}]|not_in_protected_slugs', + 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]|is_unique[pages.slug,id,{id}]', 'content' => 'required', ]; protected $validationMessages = []; @@ -37,46 +37,8 @@ class PageModel extends Model protected function clearCache(array $data) { - $page = (new PageModel())->find( - is_array($data['id']) ? $data['id'][0] : $data['id'], - ); - - // delete page cache - cache()->delete(md5($page->link)); - - // Clear the cache of all podcast and episode pages - $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['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}", - ); - } - } - } + // Clear the cache of all pages + cache()->deleteMatching('page*'); return $data; } diff --git a/app/Models/PersonModel.php b/app/Models/PersonModel.php index e1812cf4..fc19b398 100644 --- a/app/Models/PersonModel.php +++ b/app/Models/PersonModel.php @@ -48,9 +48,11 @@ class PersonModel extends Model public function getPersonById($personId) { - if (!($found = cache("person{$personId}"))) { + $cacheName = "person#{$personId}"; + if (!($found = cache($cacheName))) { $found = $this->find($personId); - cache()->save("person{$personId}", $found, DECADE); + + cache()->save($cacheName, $found, DECADE); } return $found; @@ -99,7 +101,8 @@ class PersonModel extends Model { $options = []; $locale = service('request')->getLocale(); - if (!($options = cache("taxonomy_options_{$locale}"))) { + $cacheName = "taxonomy_options_{$locale}"; + if (!($options = cache($cacheName))) { foreach (lang('PersonsTaxonomy.persons') as $group_key => $group) { foreach ($group['roles'] as $role_key => $role) { $options[ @@ -108,7 +111,7 @@ class PersonModel extends Model } } - cache()->save("taxonomy_options_{$locale}", $options, DECADE); + cache()->save($cacheName, $options, DECADE); } return $options; @@ -116,19 +119,15 @@ class PersonModel extends Model protected function clearCache(array $data) { - $person = (new PersonModel())->getPersonById( + $person = (new PersonModel())->find( is_array($data['id']) ? $data['id'][0] : $data['id'], ); cache()->delete('person_options'); - cache()->delete("person{$person->id}"); - cache()->delete("user{$person->created_by}_persons"); + cache()->delete("person#{$person->id}"); - $supportedLocales = config('App')->supportedLocales; - // clear cache for every credit page - foreach ($supportedLocales as $locale) { - cache()->delete("credit_{$locale}"); - } + // clear cache for every credits page + cache()->deleteMatching('page_credits_*'); return $data; } diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php index a5666e0c..45d84bb9 100644 --- a/app/Models/PlatformModel.php +++ b/app/Models/PlatformModel.php @@ -45,9 +45,10 @@ class PlatformModel extends Model public function getPlatform($slug) { - if (!($found = cache("platform_$slug"))) { + $cacheName = "platform@{$slug}"; + if (!($found = cache($cacheName))) { $found = $this->where('slug', $slug)->first(); - cache()->save("platform_$slug", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; } @@ -72,7 +73,9 @@ class PlatformModel extends Model public function getPlatformsWithLinks($podcastId, $platformType) { if ( - !($found = cache("podcast{$podcastId}_platforms_{$platformType}")) + !($found = cache( + "podcast#{$podcastId}_platforms_{$platformType}_withLinks", + )) ) { $found = $this->select( 'platforms.*, podcasts_platforms.link_url, podcasts_platforms.link_content, podcasts_platforms.is_visible, podcasts_platforms.is_on_embeddable_player', @@ -86,7 +89,7 @@ class PlatformModel extends Model ->findAll(); cache()->save( - "podcast{$podcastId}_platforms_{$platformType}", + "podcast#{$podcastId}_platforms_{$platformType}_withLinks", $found, DECADE, ); @@ -97,11 +100,8 @@ class PlatformModel extends Model public function getPodcastPlatforms($podcastId, $platformType) { - if ( - !($found = cache( - "podcast{$podcastId}_podcastPlatforms_{$platformType}", - )) - ) { + $cacheName = "podcast#{$podcastId}_platforms_{$platformType}"; + if (!($found = cache($cacheName))) { $found = $this->select( 'platforms.*, podcasts_platforms.link_url, podcasts_platforms.link_content, podcasts_platforms.is_visible, podcasts_platforms.is_on_embeddable_player', ) @@ -113,11 +113,7 @@ class PlatformModel extends Model ->where('platforms.type', $platformType) ->findAll(); - cache()->save( - "podcast{$podcastId}_podcastPlatforms_{$platformType}", - $found, - DECADE, - ); + cache()->save($cacheName, $found, DECADE); } return $found; @@ -132,12 +128,14 @@ class PlatformModel extends Model $podcastsPlatformsTable = $this->db->prefixTable('podcasts_platforms'); $platformsTable = $this->db->prefixTable('platforms'); - $deleteJoinQuery = <<db->query($deleteJoinQuery, [$podcastId, $platformType]); // Set podcastPlatforms @@ -168,51 +166,9 @@ class PlatformModel extends Model public function clearCache($podcastId) { - $podcast = (new PodcastModel())->getPodcastById($podcastId); + cache()->deleteMatching("podcast#{$podcastId}_platforms_*"); - 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); - $seasons = $episodeModel->getSeasons($podcastId); - $supportedLocales = config('App')->supportedLocales; - - foreach ($years as $year) { - foreach ($supportedLocales as $locale) { - cache()->delete( - "page_podcast{$podcastId}_year{$year['year']}_{$locale}", - ); - } - } - - foreach ($seasons as $season) { - foreach ($supportedLocales as $locale) { - cache()->delete( - "page_podcast{$podcastId}_season{$season['season_number']}_{$locale}", - ); - } - } - - // 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}", - ); - foreach ( - array_keys(\App\Models\EpisodeModel::$themes) - as $themeKey - ) { - cache()->delete( - "page_podcast{$podcast->id}_episode{$episode->id}_embeddable_player_{$themeKey}_{$locale}", - ); - } - } - } + cache()->deleteMatching("page_podcast#{$podcastId}*"); } } diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index e533bbb7..4724385f 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -83,7 +83,8 @@ class PodcastModel extends Model public function getPodcastByName($podcastName) { - if (!($found = cache("podcast@{$podcastName}"))) { + $cacheName = "podcast@{$podcastName}"; + if (!($found = cache($cacheName))) { $found = $this->where('name', $podcastName)->first(); cache()->save("podcast@{$podcastName}", $found, DECADE); } @@ -93,10 +94,11 @@ class PodcastModel extends Model public function getPodcastById($podcastId) { - if (!($found = cache("podcast{$podcastId}"))) { + $cacheName = "podcast#{$podcastId}"; + if (!($found = cache($cacheName))) { $found = $this->find($podcastId); - cache()->save("podcast{$podcastId}", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; @@ -111,7 +113,8 @@ class PodcastModel extends Model */ public function getUserPodcasts($userId) { - if (!($found = cache("user{$userId}_podcasts"))) { + $cacheName = "user{$userId}_podcasts"; + if (!($found = cache($cacheName))) { $found = $this->select('podcasts.*') ->join( 'podcasts_users', @@ -120,7 +123,7 @@ class PodcastModel extends Model ->where('podcasts_users.user_id', $userId) ->findAll(); - cache()->save("user{$userId}_podcasts", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; @@ -128,7 +131,7 @@ class PodcastModel extends Model public function addPodcastContributor($userId, $podcastId, $groupId) { - cache()->delete("podcast{$podcastId}_contributors"); + cache()->delete("podcast#{$podcastId}_contributors"); $data = [ 'user_id' => (int) $userId, @@ -141,7 +144,7 @@ class PodcastModel extends Model public function updatePodcastContributor($userId, $podcastId, $groupId) { - cache()->delete("podcast{$podcastId}_contributors"); + cache()->delete("podcast#{$podcastId}_contributors"); return $this->db ->table('podcasts_users') @@ -154,7 +157,7 @@ class PodcastModel extends Model public function removePodcastContributor($userId, $podcastId) { - cache()->delete("podcast{$podcastId}_contributors"); + cache()->delete("podcast#{$podcastId}_contributors"); return $this->db ->table('podcasts_users') @@ -196,75 +199,122 @@ class PodcastModel extends Model : false; } + public function getYears(int $podcastId): array + { + $cacheName = "podcast#{$podcastId}_years"; + if (!($found = cache($cacheName))) { + $episodeModel = new EpisodeModel(); + $found = $episodeModel + ->select( + 'YEAR(published_at) as year, count(*) as number_of_episodes', + ) + ->where([ + 'podcast_id' => $podcastId, + 'season_number' => null, + $episodeModel->deletedField => null, + ]) + ->where('`published_at` <= NOW()', null, false) + ->groupBy('year') + ->orderBy('year', 'DESC') + ->get() + ->getResultArray(); + + $secondsToNextUnpublishedEpisode = $episodeModel->getSecondsToNextUnpublishedEpisode( + $podcastId, + ); + + cache()->save( + $cacheName, + $found, + $secondsToNextUnpublishedEpisode + ? $secondsToNextUnpublishedEpisode + : DECADE, + ); + } + + return $found; + } + + public function getSeasons(int $podcastId): array + { + $cacheName = "podcast#{$podcastId}_seasons"; + if (!($found = cache($cacheName))) { + $episodeModel = new EpisodeModel(); + $found = $episodeModel + ->select('season_number, count(*) as number_of_episodes') + ->where([ + 'podcast_id' => $podcastId, + 'season_number is not' => null, + $episodeModel->deletedField => null, + ]) + ->where('`published_at` <= NOW()', null, false) + ->groupBy('season_number') + ->orderBy('season_number', 'ASC') + ->get() + ->getResultArray(); + + $secondsToNextUnpublishedEpisode = $episodeModel->getSecondsToNextUnpublishedEpisode( + $podcastId, + ); + + cache()->save( + $cacheName, + $found, + $secondsToNextUnpublishedEpisode + ? $secondsToNextUnpublishedEpisode + : DECADE, + ); + } + + return $found; + } + + /** + * Returns the default query for displaying the episode list on the podcast page + * + * @param int $podcastId + * + * @return array|null + */ + public function getDefaultQuery(int $podcastId) + { + $cacheName = "podcast#{$podcastId}_defaultQuery"; + if (!($defaultQuery = cache($cacheName))) { + $seasons = $this->getSeasons($podcastId); + + if (!empty($seasons)) { + // get latest season + $defaultQuery = ['type' => 'season', 'data' => end($seasons)]; + } else { + $years = $this->getYears($podcastId); + if (!empty($years)) { + // get most recent year + $defaultQuery = ['type' => 'year', 'data' => $years[0]]; + } else { + $defaultQuery = null; + } + } + + cache()->save($cacheName, $defaultQuery, DECADE); + } + return $defaultQuery; + } + public function clearCache(array $data) { $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("podcast{$podcast->id}_feed"); - foreach (\Opawg\UserAgentsPhp\UserAgentsRSS::$db as $service) { - cache()->delete("podcast{$podcast->id}_feed_{$service['slug']}"); - } + // delete cache all podcast pages + cache()->deleteMatching("page_podcast#{$podcast->id}_*"); - // delete model requests cache - cache()->delete("podcast{$podcast->id}"); + // delete model requests cache, includes feed / query / episode lists, etc. + cache()->deleteMatching("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}", - ); - foreach ( - array_keys(\App\Models\EpisodeModel::$themes) - as $themeKey - ) { - cache()->delete( - "page_podcast{$podcast->id}_episode{$episode->id}_embeddable_player_{$themeKey}_{$locale}", - ); - } - } - } // clear cache for every credit page - foreach ($supportedLocales as $locale) { - cache()->delete("credits_{$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['year']}_episodes", - ); - foreach ($supportedLocales as $locale) { - cache()->delete( - "page_podcast{$podcast->id}_year{$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"); + cache()->deleteMatching('page_credits_*'); return $data; } diff --git a/app/Models/PodcastPersonModel.php b/app/Models/PodcastPersonModel.php index 8268cf0e..c111fe98 100644 --- a/app/Models/PodcastPersonModel.php +++ b/app/Models/PodcastPersonModel.php @@ -37,20 +37,19 @@ class PodcastPersonModel extends Model protected $afterInsert = ['clearCache']; protected $beforeDelete = ['clearCache']; - public function getPersonsByPodcastId($podcastId) + public function getPodcastPersons($podcastId) { - if (!($found = cache("podcast{$podcastId}_persons"))) { + $cacheName = "podcast#{$podcastId}_persons"; + if (!($found = cache($cacheName))) { $found = $this->select('podcasts_persons.*') ->where('podcast_id', $podcastId) - ->join( - 'persons', - 'person_id=persons.id' - ) + ->join('persons', 'person_id=persons.id') ->orderby('full_name') ->findAll(); - cache()->save("podcast{$podcastId}_persons", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } + return $found; } @@ -66,7 +65,7 @@ class PodcastPersonModel extends Model public function addPodcastPersons($podcastId, $persons, $groups_roles) { if (!empty($persons)) { - $this->clearCache(['id' => ['podcast_id' => $podcastId]]); + $this->clearCache(['podcast_id' => $podcastId]); $data = []; foreach ($persons as $person) { if ($groups_roles) { @@ -102,16 +101,16 @@ class PodcastPersonModel extends Model protected function clearCache(array $data) { $podcastId = null; - if (isset($data['id']['podcast_id'])) { - $podcastId = $data['id']['podcast_id']; + if (isset($data['podcast_id'])) { + $podcastId = $data['podcast_id']; } else { $person = (new PodcastPersonModel())->find( - is_array($data['id']) ? $data['id']['id'] : $data['id'] + is_array($data['id']) ? $data['id']['id'] : $data['id'], ); $podcastId = $person->podcast_id; } - cache()->delete("podcast{$podcastId}_persons"); + cache()->delete("podcast#{$podcastId}_persons"); (new PodcastModel())->clearCache(['id' => $podcastId]); return $data; diff --git a/app/Models/SoundbiteModel.php b/app/Models/SoundbiteModel.php index fa55d592..102ab7bf 100644 --- a/app/Models/SoundbiteModel.php +++ b/app/Models/SoundbiteModel.php @@ -56,14 +56,15 @@ class SoundbiteModel extends Model */ public function getEpisodeSoundbites(int $podcastId, int $episodeId): array { - if (!($found = cache("episode{$episodeId}_soundbites"))) { + $cacheName = "podcast_episode#{$episodeId}_soundbites"; + if (!($found = cache($cacheName))) { $found = $this->where([ 'episode_id' => $episodeId, 'podcast_id' => $podcastId, ]) ->orderBy('start_time') ->findAll(); - cache()->save("episode{$episodeId}_soundbites", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; } @@ -73,25 +74,18 @@ class SoundbiteModel extends Model $episode = (new EpisodeModel())->find( isset($data['data']) ? $data['data']['episode_id'] - : $data['id']['episode_id'] + : $data['id']['episode_id'], ); - cache()->delete("episode{$episode->id}_soundbites"); + cache()->delete("podcast_episode#{$episode->id}_soundbites"); // delete cache for rss feed - cache()->delete("podcast{$episode->id}_feed"); - foreach (\Opawg\UserAgentsPhp\UserAgentsRSS::$db as $service) { - cache()->delete( - "podcast{$episode->podcast->id}_feed_{$service['slug']}" - ); - } + cache()->deleteMatching("podcast#{$episode->podcast_id}_feed*"); + + cache()->deleteMatching( + "page_podcast#{$episode->podcast_id}_episode#{$episode->id}_*", + ); - $supportedLocales = config('App')->supportedLocales; - foreach ($supportedLocales as $locale) { - cache()->delete( - "page_podcast{$episode->podcast->id}_episode{$episode->id}_{$locale}" - ); - } return $data; } } diff --git a/app/Models/UserModel.php b/app/Models/UserModel.php index 4a034461..e726b132 100644 --- a/app/Models/UserModel.php +++ b/app/Models/UserModel.php @@ -14,7 +14,8 @@ class UserModel extends \Myth\Auth\Models\UserModel public function getPodcastContributors($podcastId) { - if (!($found = cache("podcast{$podcastId}_contributors"))) { + $cacheName = "podcast#{$podcastId}_contributors"; + if (!($found = cache($cacheName))) { $found = $this->select('users.*, auth_groups.name as podcast_role') ->join('podcasts_users', 'podcasts_users.user_id = users.id') ->join( @@ -24,7 +25,7 @@ class UserModel extends \Myth\Auth\Models\UserModel ->where('podcasts_users.podcast_id', $podcastId) ->findAll(); - cache()->save("podcast{$podcastId}_contributors", $found, DECADE); + cache()->save($cacheName, $found, DECADE); } return $found; diff --git a/app/Validation/Rules.php b/app/Validation/Rules.php index 9b8ce5a4..94f11774 100644 --- a/app/Validation/Rules.php +++ b/app/Validation/Rules.php @@ -10,26 +10,6 @@ namespace App\Validation; class Rules { - /** - * Value should not be within the array of protected slugs (adminGateway, authGateway or installGateway) - * - * @param string $value - * - * @return boolean - */ - public function not_in_protected_slugs(string $value = null): bool - { - $appConfig = config('App'); - $protectedSlugs = [ - $appConfig->adminGateway, - $appConfig->authGateway, - $appConfig->installGateway, - ]; - return !in_array($value, $protectedSlugs, true); - } - - //-------------------------------------------------------------------- - /** * Checks a URL to ensure it's formed correctly. * diff --git a/app/Views/install/cache_config.php b/app/Views/install/cache_config.php index 44f01018..0cb1fc80 100644 --- a/app/Views/install/cache_config.php +++ b/app/Views/install/cache_config.php @@ -21,7 +21,7 @@ [ 'file' => lang('Install.form.cacheHandlerOptions.file'), 'redis' => lang('Install.form.cacheHandlerOptions.redis'), - 'memcached' => lang('Install.form.cacheHandlerOptions.memcached'), + 'predis' => lang('Install.form.cacheHandlerOptions.predis'), ], old('cache_handler', 'file'), [ diff --git a/composer.lock b/composer.lock index e79f6d1b..ed5ded54 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0d419d654c43fa6e14f8a96b42258a91", + "content-hash": "b5d726bdc7252c80c0fd5a6f53de1948", "packages": [ { "name": "brick/math", @@ -68,12 +68,12 @@ "source": { "type": "git", "url": "https://github.com/codeigniter4/CodeIgniter4.git", - "reference": "425bca14c840c08b935d730c73da372f3d4bdef8" + "reference": "dfbc85af9ef408a6654cce6a462c8fdde3ee2446" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/425bca14c840c08b935d730c73da372f3d4bdef8", - "reference": "425bca14c840c08b935d730c73da372f3d4bdef8", + "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/dfbc85af9ef408a6654cce6a462c8fdde3ee2446", + "reference": "dfbc85af9ef408a6654cce6a462c8fdde3ee2446", "shasum": "" }, "require": { @@ -83,18 +83,18 @@ "ext-mbstring": "*", "kint-php/kint": "^3.3", "laminas/laminas-escaper": "^2.6", - "php": "^7.3||^8.0", + "php": "^7.3 || ^8.0", "psr/log": "^1.1" }, "require-dev": { "codeigniter4/codeigniter4-standard": "^1.0", "fakerphp/faker": "^1.9", - "johnkary/phpunit-speedtrap": "^3.3", "mikey179/vfsstream": "^1.6", - "phpstan/phpstan": "0.12.82", + "nexusphp/tachycardia": "^1.0", + "phpstan/phpstan": "0.12.84", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "^0.10", + "rector/rector": "0.10.6", "squizlabs/php_codesniffer": "^3.3" }, "suggest": { @@ -139,7 +139,7 @@ "slack": "https://codeigniterchat.slack.com", "issues": "https://github.com/codeigniter4/CodeIgniter4/issues" }, - "time": "2021-03-25T19:47:47+00:00" + "time": "2021-04-20T08:40:30+00:00" }, { "name": "composer/ca-bundle", @@ -823,16 +823,16 @@ }, { "name": "league/commonmark", - "version": "1.5.7", + "version": "1.5.8", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54" + "reference": "08fa59b8e4e34ea8a773d55139ae9ac0e0aecbaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/11df9b36fd4f1d2b727a73bf14931d81373b9a54", - "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/08fa59b8e4e34ea8a773d55139ae9ac0e0aecbaf", + "reference": "08fa59b8e4e34ea8a773d55139ae9ac0e0aecbaf", "shasum": "" }, "require": { @@ -920,7 +920,7 @@ "type": "tidelift" } ], - "time": "2020-10-31T13:49:32+00:00" + "time": "2021-03-28T18:51:39+00:00" }, { "name": "league/html-to-markdown", @@ -1010,23 +1010,23 @@ }, { "name": "maxmind-db/reader", - "version": "v1.10.0", + "version": "v1.10.1", "source": { "type": "git", "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", - "reference": "07f84d969cfc527ce49388558a366ad376f1f35c" + "reference": "569bd44d97d30a4ec12c7793a33004a76d4caf18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/07f84d969cfc527ce49388558a366ad376f1f35c", - "reference": "07f84d969cfc527ce49388558a366ad376f1f35c", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/569bd44d97d30a4ec12c7793a33004a76d4caf18", + "reference": "569bd44d97d30a4ec12c7793a33004a76d4caf18", "shasum": "" }, "require": { "php": ">=7.2" }, "conflict": { - "ext-maxminddb": "<1.10.0,>=2.0.0" + "ext-maxminddb": "<1.10.1,>=2.0.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", @@ -1069,9 +1069,9 @@ ], "support": { "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", - "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.10.0" + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.10.1" }, - "time": "2021-02-09T17:52:47+00:00" + "time": "2021-04-14T17:49:35+00:00" }, { "name": "maxmind/web-service-common", @@ -1125,20 +1125,20 @@ }, { "name": "michalsn/codeigniter4-uuid", - "version": "v1.0.0-beta2", + "version": "v1.0.0-beta3", "source": { "type": "git", "url": "https://github.com/michalsn/codeigniter4-uuid.git", - "reference": "a5f9751570a3b27e81deaa7548eef507499be888" + "reference": "568aba8f315199b6cc87e76b8441cd03a2bba5b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michalsn/codeigniter4-uuid/zipball/a5f9751570a3b27e81deaa7548eef507499be888", - "reference": "a5f9751570a3b27e81deaa7548eef507499be888", + "url": "https://api.github.com/repos/michalsn/codeigniter4-uuid/zipball/568aba8f315199b6cc87e76b8441cd03a2bba5b4", + "reference": "568aba8f315199b6cc87e76b8441cd03a2bba5b4", "shasum": "" }, "require": { - "php": ">=7.2", + "php": ">=7.3", "ramsey/uuid": "^4.0" }, "require-dev": { @@ -1172,9 +1172,9 @@ ], "support": { "issues": "https://github.com/michalsn/codeigniter4-uuid/issues", - "source": "https://github.com/michalsn/codeigniter4-uuid/tree/develop" + "source": "https://github.com/michalsn/codeigniter4-uuid/tree/v1.0.0-beta3" }, - "time": "2020-08-16T07:56:20+00:00" + "time": "2021-04-02T11:08:18+00:00" }, { "name": "myth/auth", @@ -1182,12 +1182,12 @@ "source": { "type": "git", "url": "https://github.com/lonnieezell/myth-auth.git", - "reference": "a11dc6369177c932add936f1be3844c30fe45ed4" + "reference": "eff9805d7f1d27326f14875b53ff4b3d2a6b72ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lonnieezell/myth-auth/zipball/a11dc6369177c932add936f1be3844c30fe45ed4", - "reference": "a11dc6369177c932add936f1be3844c30fe45ed4", + "url": "https://api.github.com/repos/lonnieezell/myth-auth/zipball/eff9805d7f1d27326f14875b53ff4b3d2a6b72ee", + "reference": "eff9805d7f1d27326f14875b53ff4b3d2a6b72ee", "shasum": "" }, "require": { @@ -1248,7 +1248,7 @@ "type": "patreon" } ], - "time": "2021-03-23T03:55:24+00:00" + "time": "2021-04-12T22:34:12+00:00" }, { "name": "opawg/user-agents-php", @@ -1359,16 +1359,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.30", + "version": "2.0.31", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "136b9ca7eebef78be14abf90d65c5e57b6bc5d36" + "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/136b9ca7eebef78be14abf90d65c5e57b6bc5d36", - "reference": "136b9ca7eebef78be14abf90d65c5e57b6bc5d36", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/233a920cb38636a43b18d428f9a8db1f0a1a08f4", + "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4", "shasum": "" }, "require": { @@ -1448,7 +1448,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.30" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.31" }, "funding": [ { @@ -1464,7 +1464,7 @@ "type": "tidelift" } ], - "time": "2020-12-17T05:42:04+00:00" + "time": "2021-04-06T13:56:45+00:00" }, { "name": "podlibre/ipcat", @@ -2761,16 +2761,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.5", + "version": "9.2.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1" + "reference": "f6293e1b30a2354e8428e004689671b83871edde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", + "reference": "f6293e1b30a2354e8428e004689671b83871edde", "shasum": "" }, "require": { @@ -2826,7 +2826,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" }, "funding": [ { @@ -2834,7 +2834,7 @@ "type": "github" } ], - "time": "2020-11-28T06:44:49+00:00" + "time": "2021-03-28T07:26:59+00:00" }, { "name": "phpunit/php-file-iterator",