$lastPolled + self::$_PODCAST_POLL_INTERVAL_SECONDS); } /** * Find all podcasts flagged for automatic ingest whose most recent episode has * yet to be downloaded and download it with Celery. * * @throws InvalidPodcastException * @throws PodcastNotFoundException */ public static function downloadNewestEpisodes() { $autoIngestPodcasts = static::_getAutoIngestPodcasts(); $service = new Application_Service_PodcastEpisodeService(); foreach ($autoIngestPodcasts as $podcast) { $episodes = static::_findUningestedEpisodes($podcast, $service); // Since episodes don't have to be uploaded with a time (H:i:s) component, // store the timestamp of the most recent (first pushed to the array) episode // that we're ingesting. // Note that this folds to the failure case (Celery task timeout/download failure) // but will at least continue to ingest new episodes. if (!empty($episodes)) { $podcast->setDbAutoIngestTimestamp(gmdate('r', strtotime($episodes[0]->getDbPublicationDate())))->save(); $service->downloadEpisodes($episodes); } } Application_Model_Preference::setPodcastPollLock(microtime(true)); } /** * Given an ImportedPodcast, find all uningested episodes since the last automatic ingest, * and add them to a given episodes array. * * @param ImportedPodcast $podcast the podcast to search * @param Application_Service_PodcastEpisodeService $service podcast episode service object * * @return array array of episodes to append be downloaded */ protected static function _findUningestedEpisodes($podcast, $service) { $episodeList = $service->getPodcastEpisodes($podcast->getDbPodcastId()); $episodes = []; usort($episodeList, [__CLASS__, '_sortByEpisodePubDate']); for ($i = 0; $i < count($episodeList); ++$i) { $episodeData = $episodeList[$i]; $ts = $podcast->getDbAutoIngestTimestamp(); // If the timestamp for this podcast is empty (no previous episodes have been ingested) and there are no // episodes in the list of episodes to ingest, don't skip this episode - we should try to ingest the // most recent episode when the user first sets the podcast to automatic ingest. // If the publication date of this episode is before the ingest timestamp, we don't need to ingest it if ((empty($ts) && ($i > 0)) || strtotime($episodeData['pub_date']) < strtotime($ts)) { continue; } $episode = PodcastEpisodesQuery::create()->findOneByDbEpisodeGuid($episodeData['guid']); // Make sure there's no existing episode placeholder or import, and that the data is non-empty if (empty($episode) && !empty($episodeData)) { $placeholder = $service->addPlaceholder($podcast->getDbPodcastId(), $episodeData); array_push($episodes, $placeholder); } } return $episodes; } /** * Find all podcasts flagged for automatic ingest. * * @return PropelObjectCollection collection of ImportedPodcast objects * flagged for automatic ingest */ protected static function _getAutoIngestPodcasts() { return ImportedPodcastQuery::create() ->filterByDbAutoIngest(true) ->find(); } /** * Custom sort function for podcast episodes. * * @param array $a first episode array to compare * @param array $b second episode array to compare * * @return bool boolean for ordering */ protected static function _sortByEpisodePubDate($a, $b) { if ($a['pub_date'] == $b['pub_date']) { return 0; } return (strtotime($a['pub_date']) < strtotime($b['pub_date'])) ? 1 : -1; // Descending order } }