diff --git a/app/Controllers/Admin/EpisodeController.php b/app/Controllers/Admin/EpisodeController.php index b7c500420c4e70f044a81dbfe4297654502743bc..385a94dc5eff082c0f0930f4efa0066828fddd44 100644 --- a/app/Controllers/Admin/EpisodeController.php +++ b/app/Controllers/Admin/EpisodeController.php @@ -26,7 +26,7 @@ class EpisodeController extends BaseController { protected Podcast $podcast; - protected ?Episode $episode; + protected Episode $episode; public function _remap(string $method, string ...$params): mixed { @@ -253,7 +253,7 @@ class EpisodeController extends BaseController $this->episode->is_blocked = $this->request->getPost('block') === 'yes'; $this->episode->custom_rss_string = $this->request->getPost('custom_rss',); - $this->episode->updated_by = user_id(); + $this->episode->updated_by = (int) user_id(); $audioFile = $this->request->getFile('audio_file'); if ($audioFile !== null && $audioFile->isValid()) { @@ -268,7 +268,7 @@ class EpisodeController extends BaseController $transcriptChoice = $this->request->getPost('transcript-choice'); if ($transcriptChoice === 'upload-file') { $transcriptFile = $this->request->getFile('transcript_file'); - if ($transcriptFile->isValid()) { + if ($transcriptFile !== null && $transcriptFile->isValid()) { $this->episode->transcript_file = $transcriptFile; $this->episode->transcript_file_remote_url = null; } @@ -287,7 +287,7 @@ class EpisodeController extends BaseController $chaptersChoice = $this->request->getPost('chapters-choice'); if ($chaptersChoice === 'upload-file') { $chaptersFile = $this->request->getFile('chapters_file'); - if ($chaptersFile->isValid()) { + if ($chaptersFile !== null && $chaptersFile->isValid()) { $this->episode->chapters_file = $chaptersFile; $this->episode->chapters_file_remote_url = null; } @@ -411,13 +411,11 @@ class EpisodeController extends BaseController if ($publishMethod === 'schedule') { $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date',); if ($scheduledPublicationDate) { - $scheduledDateUTC = Time::createFromFormat( + $this->episode->published_at = Time::createFromFormat( 'Y-m-d H:i', $scheduledPublicationDate, $this->request->getPost('client_timezone'), )->setTimezone('UTC'); - $this->episode->published_at = $scheduledDateUTC; - $newNote->published_at = $scheduledDateUTC; } else { $db->transRollback(); return redirect() @@ -426,11 +424,11 @@ class EpisodeController extends BaseController ->with('error', 'Schedule date must be set!'); } } else { - $dateNow = Time::now(); - $this->episode->published_at = $dateNow; - $newNote->published_at = $dateNow; + $this->episode->published_at = Time::now(); } + $newNote->published_at = $this->episode->published_at; + $noteModel = new NoteModel(); if (! $noteModel->addNote($newNote)) { $db->transRollback(); @@ -498,20 +496,15 @@ class EpisodeController extends BaseController $db = Database::connect(); $db->transStart(); - $note = (new NoteModel())->getNoteById($this->request->getPost('note_id'),); - $note->message = $this->request->getPost('message'); - $publishMethod = $this->request->getPost('publication_method'); if ($publishMethod === 'schedule') { $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date',); if ($scheduledPublicationDate) { - $scheduledDateUTC = Time::createFromFormat( + $this->episode->published_at = Time::createFromFormat( 'Y-m-d H:i', $scheduledPublicationDate, $this->request->getPost('client_timezone'), )->setTimezone('UTC'); - $this->episode->published_at = $scheduledDateUTC; - $note->published_at = $scheduledDateUTC; } else { $db->transRollback(); return redirect() @@ -520,18 +513,23 @@ class EpisodeController extends BaseController ->with('error', 'Schedule date must be set!'); } } else { - $dateNow = Time::now(); - $this->episode->published_at = $dateNow; - $note->published_at = $dateNow; + $this->episode->published_at = Time::now(); } - $noteModel = new NoteModel(); - if (! $noteModel->editNote($note)) { - $db->transRollback(); - return redirect() - ->back() - ->withInput() - ->with('errors', $noteModel->errors()); + $note = (new NoteModel())->getNoteById($this->request->getPost('note_id'),); + + if ($note !== null) { + $note->message = $this->request->getPost('message'); + $note->published_at = $this->episode->published_at; + + $noteModel = new NoteModel(); + if (! $noteModel->editNote($note)) { + $db->transRollback(); + return redirect() + ->back() + ->withInput() + ->with('errors', $noteModel->errors()); + } } $episodeModel = new EpisodeModel(); diff --git a/app/Controllers/EpisodeController.php b/app/Controllers/EpisodeController.php index 6e8cf7ff2cd7c3ddb3a49099713582f5bd093631..96c1289414fabd2de1fb2ebf2a8d5bce3719fff7 100644 --- a/app/Controllers/EpisodeController.php +++ b/app/Controllers/EpisodeController.php @@ -39,7 +39,7 @@ class EpisodeController extends BaseController } if ( - ($this->episode = (new EpisodeModel())->getEpisodeBySlug($this->podcast->id, $params[1],)) !== null + ($this->episode = (new EpisodeModel())->getEpisodeBySlug($params[0], $params[1],)) !== null ) { unset($params[1]); unset($params[0]); diff --git a/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php b/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php index 0b15bda7e89fb9787dffbabac7ac6b35fa8b148b..15c71043aedb08adf5a239f01b00b7e952c93724 100644 --- a/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php +++ b/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php @@ -57,10 +57,8 @@ class FakePodcastsAnalyticsSeeder extends Seeder $analyticsPodcastsByRegion = []; $episodes = (new EpisodeModel()) - ->where([ - 'podcast_id' => $podcast->id, - 'DATE(published_at) <=' => date('Y-m-d', $date), - ]) + ->where('podcast_id', $podcast->id) + ->where('`published_at` <= NOW()', null, false) ->findAll(); foreach ($episodes as $episode) { $age = floor(($date - strtotime($episode->published_at)) / 86400,); @@ -110,7 +108,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder ? 'N/A' : $city->country->isoCode; - $regionCode = $city->subdivisions[0]->isoCode === null + $regionCode = $city->subdivisions === [] ? 'N/A' : $city->subdivisions[0]->isoCode; $latitude = round($city->location->latitude, 3); diff --git a/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php b/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php index aead2496f61e148b13e6c58ac5c51abbe102857f..ac10549829dc7e3f156382328cedf0bb62c95363 100644 --- a/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php +++ b/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php @@ -196,10 +196,8 @@ class FakeWebsiteAnalyticsSeeder extends Seeder $websiteByReferer = []; $episodes = (new EpisodeModel()) - ->where([ - 'podcast_id' => $podcast->id, - 'DATE(published_at) <=' => date('Y-m-d', $date), - ]) + ->where('podcast_id', $podcast->id) + ->where('`published_at` <= NOW()', null, false) ->findAll(); foreach ($episodes as $episode) { $age = floor(($date - strtotime($episode->published_at)) / 86400,); diff --git a/app/Libraries/Analytics/Controllers/EpisodeController.php b/app/Libraries/Analytics/Controllers/EpisodeController.php index 6e8cf7ff2cd7c3ddb3a49099713582f5bd093631..96c1289414fabd2de1fb2ebf2a8d5bce3719fff7 100644 --- a/app/Libraries/Analytics/Controllers/EpisodeController.php +++ b/app/Libraries/Analytics/Controllers/EpisodeController.php @@ -39,7 +39,7 @@ class EpisodeController extends BaseController } if ( - ($this->episode = (new EpisodeModel())->getEpisodeBySlug($this->podcast->id, $params[1],)) !== null + ($this->episode = (new EpisodeModel())->getEpisodeBySlug($params[0], $params[1],)) !== null ) { unset($params[1]); unset($params[0]); diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index 8b0a28281f2f735deacc4883245292e225a900b8..225c1889bc02ed62839af4be619acbcd6db2911c 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -13,9 +13,9 @@ use CodeIgniter\Model; class EpisodeModel extends Model { - // TODO: remove - /** + * TODO: remove, shouldn't be here + * * @var array<string, array<string, string>> */ public static $themes = [ @@ -135,45 +135,26 @@ class EpisodeModel extends Model */ protected $afterInsert = ['writeEnclosureMetadata', 'clearCache']; - // clear cache beforeUpdate because if slug changes, so will the episode link - - /** - * @var string[] - */ - protected $beforeUpdate = ['clearCache']; - /** * @var string[] */ - protected $afterUpdate = ['writeEnclosureMetadata']; + protected $afterUpdate = ['clearCache', 'writeEnclosureMetadata']; /** * @var string[] */ protected $beforeDelete = ['clearCache']; - /** - * @param int|string $podcastId may be the id or podcast name - */ - public function getEpisodeBySlug(int | string $podcastId, string $episodeSlug): ?Episode + public function getEpisodeBySlug(string $podcastName, string $episodeSlug): ?Episode { - $cacheName = "podcast#{$podcastId}_episode-{$episodeSlug}"; + $cacheName = "podcast-{$podcastName}_episode-{$episodeSlug}"; if (! ($found = cache($cacheName))) { - $builder = $this->select('episodes.*') + $found = $this->select('episodes.*') + ->join('podcasts', 'podcasts.id = episodes.podcast_id') ->where('slug', $episodeSlug) - ->where('`published_at` <= NOW()', null, false); - - if (is_numeric($podcastId)) { - // passed argument is the podcast id - $builder->where('podcast_id', $podcastId); - } else { - // passed argument is the podcast name, must perform join - $builder - ->join('podcasts', 'podcasts.id = episodes.podcast_id') - ->where('podcasts.name', $podcastId); - } - - $found = $builder->first(); + ->where('podcasts.name', $podcastName) + ->where('`published_at` <= NOW()', null, false) + ->first(); cache() ->save($cacheName, $found, DECADE); @@ -278,9 +259,9 @@ class EpisodeModel extends Model * 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 * - * @return int|bool seconds + * @return int|false seconds */ - public function getSecondsToNextUnpublishedEpisode(int $podcastId): int | bool + public function getSecondsToNextUnpublishedEpisode(int $podcastId): int | false { $result = $this->select('TIMESTAMPDIFF(SECOND, NOW(), `published_at`) as timestamp_diff',) ->where([ @@ -291,7 +272,7 @@ class EpisodeModel extends Model ->get() ->getResultArray(); - return count($result) !== 0 + return $result !== [] ? (int) $result[0]['timestamp_diff'] : false; } @@ -305,46 +286,18 @@ class EpisodeModel extends Model { $episode = (new self())->find(is_array($data['id']) ? $data['id'][0] : $data['id'],); - // delete cache for rss feed + // delete podcast cache cache() - ->deleteMatching("podcast#{$episode->podcast_id}_feed*"); - - // delete model requests cache + ->deleteMatching("podcast#{$episode->podcast_id}*"); cache() - ->delete("podcast#{$episode->podcast_id}_episodes"); - + ->deleteMatching("podcast-{$episode->podcast->name}*"); cache() ->delete("podcast_episode#{$episode->id}"); cache() - ->deleteMatching("podcast#{$episode->podcast_id}_episode#{$episode->id}*"); - cache() - ->delete("podcast#{$episode->podcast_id}_episode-{$episode->slug}"); - - cache() - ->deleteMatching("page_podcast#{$episode->podcast_id}_activity*"); - cache() - ->deleteMatching("page_podcast#{$episode->podcast_id}_episode#{$episode->id}_*",); + ->deleteMatching("page_podcast#{$episode->podcast_id}*"); cache() ->deleteMatching('page_credits_*'); - if ($episode->season_number) { - cache()->deleteMatching("podcast#{$episode->podcast_id}_season*"); - cache() - ->deleteMatching("page_podcast#{$episode->podcast_id}_episodes_season*",); - } else { - cache()->deleteMatching("podcast#{$episode->podcast_id}_year*"); - cache() - ->deleteMatching("page_podcast#{$episode->podcast_id}_episodes_year*",); - } - - // 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/PersonModel.php b/app/Models/PersonModel.php index 3101acda4d8354d3d31c74fd1030897dd6215eff..07b2cea57513e90e97a130959eeb233d4d11b60a 100644 --- a/app/Models/PersonModel.php +++ b/app/Models/PersonModel.php @@ -171,7 +171,7 @@ class PersonModel extends Model ->getLocale(); $cacheName = "taxonomy_options_{$locale}"; - /** @var array<string, array<string, string|array<string, array<string, string>>>> $personsTaxonomy */ + /** @var array<string, mixed> $personsTaxonomy */ $personsTaxonomy = lang('PersonsTaxonomy.persons'); if (! ($options = cache($cacheName))) { @@ -285,14 +285,14 @@ class PersonModel extends Model /** * Add persons to podcast * - * @param array<string> $persons + * @param array<string> $personIds * @param array<string, string> $roles * * @return bool|int Number of rows inserted or FALSE on failure */ - public function addPodcastPersons(int $podcastId, array $persons = [], array $roles = []): int | bool + public function addPodcastPersons(int $podcastId, array $personIds = [], array $roles = []): int | bool { - if ($persons === []) { + if ($personIds === []) { return 0; } @@ -303,11 +303,11 @@ class PersonModel extends Model ]); $data = []; - foreach ($persons as $person) { + foreach ($personIds as $personId) { if ($roles === []) { $data[] = [ 'podcast_id' => $podcastId, - 'person_id' => $person, + 'person_id' => $personId, ]; } @@ -315,7 +315,7 @@ class PersonModel extends Model $groupRole = explode(',', $role); $data[] = [ 'podcast_id' => $podcastId, - 'person_id' => $person, + 'person_id' => $personId, 'person_group' => $groupRole[0], 'person_role' => $groupRole[1], ]; @@ -337,6 +337,9 @@ class PersonModel extends Model cache()->deleteMatching("podcast#{$podcastId}_person#{$personId}*"); cache() ->delete("podcast#{$podcastId}_persons"); + (new PodcastModel())->clearCache([ + 'id' => $podcastId, + ]); return $this->db->table('podcasts_persons') ->delete([ @@ -399,6 +402,9 @@ class PersonModel extends Model cache()->deleteMatching("podcast#{$podcastId}_episode#{$episodeId}_person#{$personId}*"); cache() ->delete("podcast#{$podcastId}_episode#{$episodeId}_persons"); + (new EpisodeModel())->clearCache([ + 'id' => $episodeId, + ]); return $this->db->table('episodes_persons') ->delete([ @@ -424,7 +430,7 @@ class PersonModel extends Model // clear cache for every credits page cache() - ->deleteMatching('page_credits_*'); + ->deleteMatching('page_credits*'); return $data; } diff --git a/app/Views/podcast/_partials/note_authenticated.php b/app/Views/podcast/_partials/note_authenticated.php index c60f594274dc1dfc26e0b18aeec43d318c6cf6a1..14973c7ea80d22bbfaec3ca6fa7d8f8b3ba89527 100644 --- a/app/Views/podcast/_partials/note_authenticated.php +++ b/app/Views/podcast/_partials/note_authenticated.php @@ -20,9 +20,9 @@ class="text-xs text-gray-500"> <time itemprop="published" - datetime="<?= $note->created_at->format(DateTime::ATOM) ?>" - title="<?= $note->created_at ?>" - ><?= lang('Common.mediumDate', [$note->created_at]) ?></time> + datetime="<?= $note->published_at->format(DateTime::ATOM) ?>" + title="<?= $note->published_at ?>" + ><?= lang('Common.mediumDate', [$note->published_at]) ?></time> </a> </div> </header> diff --git a/app/Views/podcast/_partials/reply_authenticated.php b/app/Views/podcast/_partials/reply_authenticated.php index 62eab7450479a002c4c6b295bb0224c2a49d0c0d..72d2b6353f0f39c8cbb7980261c4328ce62ff14b 100644 --- a/app/Views/podcast/_partials/reply_authenticated.php +++ b/app/Views/podcast/_partials/reply_authenticated.php @@ -14,9 +14,9 @@ <time class="flex-shrink-0 ml-auto text-xs text-gray-600" itemprop="published" - datetime="<?= $reply->created_at->format(DateTime::ATOM) ?>" - title="<?= $reply->created_at ?>" - ><?= lang('Common.mediumDate', [$reply->created_at]) ?></time> + datetime="<?= $reply->published_at->format(DateTime::ATOM) ?>" + title="<?= $reply->published_at ?>" + ><?= lang('Common.mediumDate', [$reply->published_at]) ?></time> </header> <p class="mb-2 note-content"><?= $reply->message_html ?></p> <?php if ($reply->has_preview_card): ?>