diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..98a8f4524 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**LibreTime version:** +Version from the upgrade popup if you can reach it. + +**Installation method:** + - OS: [e.g. Ubuntu] + - OS Version [e.g. 16.04.5 LTS (Xenial Xerus)] + - Method: [e.g. `./install` script or packages] + - Details: [how did you call the install script, where did you get packages from] + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Client (please complete the following information if applicable):** + - OS: [e.g. Fedora] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..982a4dc0d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: feature-request +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore index 7e6412ac8..719207802 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ VERSION airtime_mvc/tests/log/*.log .vagrant/ .DS_Store +.idea/ diff --git a/.travis.yml b/.travis.yml index 3a5967e19..dde29a3e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ dist: trusty language: php php: # the latest and greatest, has some issues that are excluded below in matrix.allow_failures +- 7.3 - 7.2 - 7.1 # the 7.0 build demonstrates that everything is basically ok for 7.0, users might want to wait for 7.1 to run it @@ -28,12 +29,15 @@ matrix: # there are some issues with phpunit as well as some deep in zf1 on 7.2 - env: PYTHON=false php: 7.2 + # there are some issues with phpunit as well as some deep in zf1 on 7.3 + - env: PYTHON=false + php: 7.3 exclude: - # by excluding all of python we make way to just runu python tests in one seperate instance + # by excluding all of python we make way to just run python tests in one seperate instance - env: PYTHON=true include: # using latest to run python on since it will last the longest - - php: 7.1 + - php: 7.3 env: PYTHON=true addons: apt: diff --git a/Vagrantfile b/Vagrantfile index f85987c79..0d5cae12a 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -9,10 +9,9 @@ Vagrant.configure("2") do |config| config.vm.network "forwarded_port", guest: 8000, host:8000 # liquidsoap input harbors for instreaming (ie. /master) config.vm.network "forwarded_port", guest: 8001, host:8001 - config.vm.network "forwarded_port", guest: 8002, host:8002 + config.vm.network "forwarded_port", guest: 8002, host:8002 # mkdocs documentation config.vm.network "forwarded_port", guest: 8888, host:8888 - # make sure we are using nfs (doesn't work out of the box with debian) config.vm.synced_folder ".", "/vagrant", type: "nfs" @@ -40,31 +39,31 @@ Vagrant.configure("2") do |config| # define all the OS boxes we support config.vm.define "ubuntu-bionic" do |os| os.vm.box = "bento/ubuntu-18.04" - provision_libretime(os, "ubuntu.sh", installer_args) + provision_libretime(os, "debian.sh", installer_args) end config.vm.define "ubuntu-xenial" do |os| os.vm.box = "bento/ubuntu-16.04" - provision_libretime(os, "ubuntu.sh", installer_args) + provision_libretime(os, "debian.sh", installer_args) end config.vm.define "ubuntu-trusty" do |os| STDERR.puts 'WARNING: The "ubuntu-trusty" option is deprecated. Please migrate to "ubuntu-bionic".' STDERR.puts os.vm.box = "bento/ubuntu-14.04" - provision_libretime(os, "ubuntu.sh", installer_args) + provision_libretime(os, "debian.sh", installer_args) end config.vm.define "debian-jessie" do |os| os.vm.box = "bento/debian-8.7" provision_libretime(os, "debian.sh", installer_args) end config.vm.define "debian-stretch" do |os| - os.vm.box = "bento/debian-9.2" + os.vm.box = "bento/debian-9.6" provision_libretime(os, "debian.sh", installer_args) end - config.vm.define "debian-wheezy" do |os| - STDERR.puts 'WARNING: The "debian-wheezy" option is deprecated. Please migrate to "debian-stretch".' - STDERR.puts - os.vm.box = "bento/debian-7.11" - provision_libretime(os, "debian.sh", installer_args) + config.vm.define "debian-buster" do |os| + # TODO: Replace with generic/debian10 once it is released + os.vm.box = "fujimakishouten/debian-buster64" + # TODO: Remove the manual flags after buster is released + provision_libretime(os, "debian.sh", installer_args + "--distribution=debian --release=buster") end config.vm.define "centos" do |os| os.vm.box = 'centos/7' diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index 37b2ca3af..dcb9ba090 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -43,29 +43,14 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap $view->doctype('XHTML1_STRICT'); } - protected function _initZFDebug() + /** + * initialize front controller + * + * This is call ZFrontController to ensure it is executed last in the bootstrap process. + */ + protected function _initZFrontController() { - Zend_Controller_Front::getInstance()->throwExceptions(false); - - /* - if (APPLICATION_ENV == "development") { - $autoloader = Zend_Loader_Autoloader::getInstance(); - $autoloader->registerNamespace('ZFDebug'); - - $options = array( - 'plugins' => array('Variables', - 'Exception', - 'Memory', - 'Time') - ); - $debug = new ZFDebug_Controller_Plugin_Debug($options); - - $this->bootstrap('frontController'); - $frontController = $this->getResource('frontController'); - $frontController->registerPlugin($debug); - } - */ } protected function _initRouter() diff --git a/airtime_mvc/application/airtime-boot.php b/airtime_mvc/application/airtime-boot.php index 97c00678d..e425fe37e 100644 --- a/airtime_mvc/application/airtime-boot.php +++ b/airtime_mvc/application/airtime-boot.php @@ -64,10 +64,10 @@ set_include_path(APPLICATION_PATH . '/common/' . PATH_SEPARATOR . get_include_pa require_once 'autoload.php'; /** Zend_Application */ -require_once 'Zend/Application.php'; $application = new Zend_Application( APPLICATION_ENV, - CONFIG_PATH . 'application.ini' + CONFIG_PATH . 'application.ini', + true ); require_once(APPLICATION_PATH . "logging/Logging.php"); diff --git a/airtime_mvc/application/common/AutoPlaylistManager.php b/airtime_mvc/application/common/AutoPlaylistManager.php index 2d1304165..c87efc095 100644 --- a/airtime_mvc/application/common/AutoPlaylistManager.php +++ b/airtime_mvc/application/common/AutoPlaylistManager.php @@ -13,7 +13,6 @@ class AutoPlaylistManager { * @return bool true if $_AUTOPLAYLIST_POLL_INTERVAL_SECONDS has passed since the last check */ public static function hasAutoPlaylistPollIntervalPassed() { - Logging::info("Checking autoplaylist poll"); $lastPolled = Application_Model_Preference::getAutoPlaylistPollLock(); return empty($lastPolled) || (microtime(true) > $lastPolled + self::$_AUTOPLAYLIST_POLL_INTERVAL_SECONDS); } @@ -23,35 +22,58 @@ class AutoPlaylistManager { * */ public static function buildAutoPlaylist() { - Logging::info("Checking to run Auto Playlist"); $autoPlaylists = static::_upcomingAutoPlaylistShows(); foreach ($autoPlaylists as $autoplaylist) { // creates a ShowInstance object to build the playlist in from the ShowInstancesQuery Object $si = new Application_Model_ShowInstance($autoplaylist->getDbId()); $playlistid = $si->GetAutoPlaylistId(); - Logging::info("Scheduling $playlistid"); // call the addPlaylist to show function and don't check for user permission to avoid call to non-existant user object $sid = $si->getShowId(); $playlistrepeat = new Application_Model_Show($sid); + $introplaylistid = Application_Model_Preference::GetIntroPlaylist(); + $outroplaylistid = Application_Model_Preference::GetOutroPlaylist(); - if ($playlistrepeat->getAutoPlaylistRepeat()) { - $full = false; - while(!$full) { - $si = new Application_Model_ShowInstance($autoplaylist->getDbId()); + // we want to check and see if we need to repeat this process until the show is 100% scheduled + // so we create a while loop and break it immediately if repeat until full isn't enabled + // otherwise we continue to go through adding playlists, including the intro and outro if enabled + $full = false; + $repeatuntilfull = $playlistrepeat->getAutoPlaylistRepeat(); + $tempPercentScheduled = 0; + while(!$full) { + $si = new Application_Model_ShowInstance($autoplaylist->getDbId()); + // we do not want to try to schedule an empty playlist + if ($playlistid != null) { $si->addPlaylistToShow($playlistid, false); - $ps = $si->getPercentScheduled(); - //Logging::info("The total percent scheduled is % $ps"); - if ($ps > 100) { - $full = true; - } - } - } - else { - $si->addPlaylistToShow($playlistid, false); + $ps = $si->getPercentScheduled(); + if ($introplaylistid != null) { + //Logging::info('adding intro'); + $si->addPlaylistToShowStart($introplaylistid, false); + } + if ($outroplaylistid != null) { + //Logging::info('adding outro'); + $si->addPlaylistToShow($outroplaylistid, false); + //Logging::info("The total percent scheduled is % $ps"); + } + if ($ps > 100) { + $full = true; + } + elseif (!$repeatuntilfull) { + break; + } + // we want to avoid an infinite loop if all of the playlists are null + if ($playlistid == null && $introplaylistid == null && $outroplaylistid == null) { + break; + } + // another possible issue would be if the show isn't increasing in length each loop + // ie if all of the playlists being added are zero lengths this could cause an infinite loop + if ($tempPercentScheduled == $ps) { + break; + } + //now reset it to zero + $tempPercentScheduled = $ps; } $si->setAutoPlaylistBuilt(true); - } Application_Model_Preference::setAutoPlaylistPollLock(microtime(true)); } diff --git a/airtime_mvc/application/common/FileDataHelper.php b/airtime_mvc/application/common/FileDataHelper.php index 6ad391dbc..3cd9c83af 100644 --- a/airtime_mvc/application/common/FileDataHelper.php +++ b/airtime_mvc/application/common/FileDataHelper.php @@ -16,6 +16,7 @@ class FileDataHelper { "audio/mp4" => "m4a", "video/mp4" => "mp4", "audio/x-flac" => "flac", + "audio/flac" => "flac", "audio/wav" => "wav", "audio/x-wav" => "wav", "audio/mp2" => "mp2", diff --git a/airtime_mvc/application/common/PodcastManager.php b/airtime_mvc/application/common/PodcastManager.php index a090ff910..d29816a54 100644 --- a/airtime_mvc/application/common/PodcastManager.php +++ b/airtime_mvc/application/common/PodcastManager.php @@ -101,4 +101,4 @@ class PodcastManager { return (strtotime($a["pub_date"]) < strtotime($b["pub_date"])) ? 1 : -1; // Descending order } -} \ No newline at end of file +} diff --git a/airtime_mvc/application/configs/navigation.php b/airtime_mvc/application/configs/navigation.php index f7c81aafa..b211b323f 100644 --- a/airtime_mvc/application/configs/navigation.php +++ b/airtime_mvc/application/configs/navigation.php @@ -68,10 +68,9 @@ $pages[] = array( ); $pages[] = array( 'label' => _("Settings"), - 'resource' => 'preference', - 'action' => 'index', + 'action' => 'edit-user', 'module' => 'default', - 'controller' => 'preference', + 'controller' => 'user', 'class' => '', 'title' => 'Settings', 'pages' => array( @@ -84,8 +83,7 @@ $pages[] = array( array( 'label' => _('My Profile'), 'controller' => 'user', - 'action' => 'edit-user', - 'resource' => 'usersettings' + 'action' => 'edit-user' ), array( 'label' => _('Users'), diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index bee424f85..cd5027882 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -15,12 +15,12 @@ class ApiController extends Zend_Controller_Action } //Ignore API key and session authentication for these APIs: - $ignoreAuth = array("live-info", - "live-info-v2", - "week-info", - "station-metadata", + $ignoreAuth = array("live-info", + "live-info-v2", + "week-info", + "station-metadata", "station-logo", - "show-history-feed", + "show-history-feed", "item-history-feed", "shows", "show-tracks", @@ -178,6 +178,7 @@ class ApiController extends Zend_Controller_Action //Used by the SaaS monitoring public function onAirLightAction() { + $request = $this->getRequest(); $this->view->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); @@ -185,12 +186,16 @@ class ApiController extends Zend_Controller_Action $result["on_air_light"] = false; $result["on_air_light_expected_status"] = false; $result["station_down"] = false; + $result["master_stream"] = false; + $result["live_stream"] = false; + $result["master_stream_on_air"] = false; + $result["live_stream_on_air"] = false; $range = Application_Model_Schedule::GetPlayOrderRange(); - $isItemCurrentlyScheduled = !is_null($range["current"]) && count($range["currentShow"]) > 0 ? true : false; + $isItemCurrentlyScheduled = !is_null($range["tracks"]["current"]) && count($range["tracks"]["current"]) > 0 ? true : false; - $isCurrentItemPlaying = $range["current"]["media_item_played"] ? true : false; + $isCurrentItemPlaying = $range["tracks"]["current"]["media_item_played"] ? true : false; if ($isItemCurrentlyScheduled || Application_Model_Preference::GetSourceSwitchStatus("live_dj") == "on" || @@ -210,9 +215,28 @@ class ApiController extends Zend_Controller_Action $result["station_down"] = true; } + $live_dj_stream = Application_Model_Preference::GetSourceStatus("live_dj"); + $master_dj_stream = Application_Model_Preference::GetSourceStatus("master_dj"); + $live_dj_on_air = Application_Model_Preference::GetSourceSwitchStatus("live_dj"); + $master_dj_on_air = Application_Model_Preference::GetSourceSwitchStatus("master_dj"); + + if($live_dj_stream == true){ + $result["live_stream"] = true; + if ($live_dj_on_air == "on") { + $result["live_stream_on_air"] = true; + } + } + + if($master_dj_stream == true){ + $result["master_stream"] = true; + if ($master_dj_on_air == "on") { + $result["master_stream_on_air"] = true; + } + } + $this->returnJsonOrJsonp($request, $result); } - + /** * Retrieve the currently playing show as well as upcoming shows. * Number of shows returned and the time interval in which to @@ -234,18 +258,18 @@ class ApiController extends Zend_Controller_Action // disable the view and the layout $this->view->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); - + $request = $this->getRequest(); - + $utcTimeNow = gmdate(DEFAULT_TIMESTAMP_FORMAT); $utcTimeEnd = ""; // if empty, getNextShows will use interval instead of end of day - + // default to the station timezone $timezone = Application_Model_Preference::GetDefaultTimezone(); $userDefinedTimezone = strtolower($request->getParam('timezone')); $upcase = false; // only upcase the timezone abbreviations $this->updateTimezone($userDefinedTimezone, $timezone, $upcase); - + $type = $request->getParam('type'); $limit = $request->getParam('limit'); if ($limit == "" || !is_numeric($limit)) { @@ -255,12 +279,12 @@ class ApiController extends Zend_Controller_Action * we are using two entirely different codepaths for very similar functionality (type = endofday * vs type = interval). Needs to be fixed for 2.3 - MK */ if ($type == "endofday") { - + // make getNextShows use end of day $end = Application_Common_DateHelper::getTodayStationEndDateTime(); $end->setTimezone(new DateTimeZone("UTC")); $utcTimeEnd = $end->format(DEFAULT_TIMESTAMP_FORMAT); - + $result = array( "env" => APPLICATION_ENV, "schedulerTime" => $utcTimeNow, @@ -282,7 +306,7 @@ class ApiController extends Zend_Controller_Action array("starts", "ends", "start_timestamp","end_timestamp"), $timezone ); - + //Convert the UTC scheduler time ("now") to the user-defined timezone. $result["schedulerTime"] = Application_Common_DateHelper::UTCStringToTimezoneString($result["schedulerTime"], $timezone); $result["timezone"] = $upcase ? strtoupper($timezone) : $timezone; @@ -326,13 +350,13 @@ class ApiController extends Zend_Controller_Action $this->_helper->viewRenderer->setNoRender(true); $request = $this->getRequest(); - + // default to the station timezone $timezone = Application_Model_Preference::GetDefaultTimezone(); $userDefinedTimezone = strtolower($request->getParam('timezone')); $upcase = false; // only upcase the timezone abbreviations $this->updateTimezone($userDefinedTimezone, $timezone, $upcase); - + $daysToRetrieve = $request->getParam('days'); $showsToRetrieve = $request->getParam('shows'); if ($daysToRetrieve == "" || !is_numeric($daysToRetrieve)) { @@ -341,7 +365,7 @@ class ApiController extends Zend_Controller_Action if ($showsToRetrieve == "" || !is_numeric($showsToRetrieve)) { $showsToRetrieve = self::DEFAULT_SHOWS_TO_RETRIEVE; } - + // set the end time to the day's start n days from now. // days=1 will return shows until the end of the current day, // days=2 will return shows until the end of tomorrow, etc. @@ -350,7 +374,7 @@ class ApiController extends Zend_Controller_Action $utcTimeEnd = $end->format(DEFAULT_TIMESTAMP_FORMAT); $result = Application_Model_Schedule::GetPlayOrderRange($utcTimeEnd, $showsToRetrieve); - + // apply user-defined timezone, or default to station $this->applyLiveTimezoneAdjustments($result, $timezone, $upcase); @@ -359,7 +383,7 @@ class ApiController extends Zend_Controller_Action // convert image paths to point to api endpoints WidgetHelper::findAndConvertPaths($result); - + // used by caller to determine if the airtime they are running or widgets in use is out of date. $result["station"]["AIRTIME_API_VERSION"] = AIRTIME_API_VERSION; @@ -370,12 +394,12 @@ class ApiController extends Zend_Controller_Action exit; } } - + /** - * Check that the value for the timezone the user gave is valid. - * If it is, override the default (station) timezone. + * Check that the value for the timezone the user gave is valid. + * If it is, override the default (station) timezone. * If it's an abbreviation (pst, edt) we upcase the output. - * + * * @param string $userDefinedTimezone the requested timezone value * @param string $timezone the default timezone * @param boolean $upcase whether the timezone output should be upcased @@ -396,28 +420,28 @@ class ApiController extends Zend_Controller_Action $timezone = $userDefinedTimezone; } } - + /** - * If the user passed in a timezone parameter, adjust timezone-dependent + * If the user passed in a timezone parameter, adjust timezone-dependent * variables in the result to reflect the given timezone. - * + * * @param array $result reference to the object to send back to the user * @param string $timezone the user's timezone parameter value * @param boolean $upcase whether the timezone output should be upcased */ - private function applyLiveTimezoneAdjustments(&$result, $timezone, $upcase) + private function applyLiveTimezoneAdjustments(&$result, $timezone, $upcase) { Application_Common_DateHelper::convertTimestampsToTimezone( $result, array("starts", "ends", "start_timestamp","end_timestamp"), $timezone ); - + //Convert the UTC scheduler time ("now") to the user-defined timezone. $result["station"]["schedulerTime"] = Application_Common_DateHelper::UTCStringToTimezoneString($result["station"]["schedulerTime"], $timezone); $result["station"]["timezone"] = $upcase ? strtoupper($timezone) : $timezone; } - + public function weekInfoAction() { if (Application_Model_Preference::GetAllow3rdPartyApi() || $this->checkAuth()) { @@ -438,11 +462,11 @@ class ApiController extends Zend_Controller_Action exit; } } - + /** * API endpoint to display the show logo */ - public function showLogoAction() + public function showLogoAction() { // Disable the view and the layout $this->view->layout()->disableLayout(); @@ -459,7 +483,7 @@ class ApiController extends Zend_Controller_Action if (empty($show)) { throw new ZendActionHttpException($this, 400, "ERROR: No show with ID $showId exists."); } - + $path = $show->getDbImagePath(); try { $mime_type = mime_content_type($path); @@ -488,9 +512,9 @@ class ApiController extends Zend_Controller_Action header('HTTP/1.0 401 Unauthorized'); print _('You are not allowed to access this resource. '); exit; - } + } } - + /** * API endpoint to provide station metadata */ @@ -500,18 +524,18 @@ class ApiController extends Zend_Controller_Action // disable the view and the layout $this->view->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); - + $CC_CONFIG = Config::getConfig(); $baseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['baseDir']); $path = 'http://'.$_SERVER['HTTP_HOST'].$baseDir."api/station-logo"; - + $result["name"] = Application_Model_Preference::GetStationName(); $result["logo"] = $path; $result["description"] = Application_Model_Preference::GetStationDescription(); $result["timezone"] = Application_Model_Preference::GetDefaultTimezone(); $result["locale"] = Application_Model_Preference::GetDefaultLocale(); $result["stream_data"] = Application_Model_StreamSetting::getEnabledStreamData(); - + // used by caller to determine if the airtime they are running or widgets in use is out of date. $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; @@ -526,27 +550,27 @@ class ApiController extends Zend_Controller_Action /** * API endpoint to display the current station logo */ - public function stationLogoAction() + public function stationLogoAction() { if (Application_Model_Preference::GetAllow3rdPartyApi() || $this->checkAuth()) { // disable the view and the layout $this->view->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); - + $logo = Application_Model_Preference::GetStationLogo(); // if there's no logo, just die - redirects to a 404 if (!$logo || $logo === '') { return; } - + // we're passing this as an image instead of using it in a data uri, so decode it $blob = base64_decode($logo); - + // use finfo to get the mimetype from the decoded blob $f = finfo_open(); $mime_type = finfo_buffer($f, $blob, FILEINFO_MIME_TYPE); finfo_close($f); - + header("Content-Type: " . $mime_type); echo $blob; } else { @@ -555,7 +579,7 @@ class ApiController extends Zend_Controller_Action exit; } } - + public function scheduleAction() { $this->view->layout()->disableLayout(); @@ -571,13 +595,13 @@ class ApiController extends Zend_Controller_Action public function notifyMediaItemStartPlayAction() { $media_id = $this->_getParam("media_id"); - + // We send a fake media id when playing on-demand ads; // in this case, simply return if ($media_id === '0' || $media_id === '-1') { return; } - + Logging::debug("Received notification of new media item start: $media_id"); Application_Model_Schedule::UpdateMediaPlayedStatus($media_id); @@ -619,7 +643,7 @@ class ApiController extends Zend_Controller_Action $this->_helper->json->sendJson(array("status"=>1, "message"=>"")); } - + public function recordedShowsAction() { $utcTimezone = new DateTimeZone("UTC"); @@ -637,7 +661,7 @@ class ApiController extends Zend_Controller_Action $this->view->server_timezone = Application_Model_Preference::GetDefaultTimezone(); $rows = Application_Model_Show::getCurrentShow(); - + if (count($rows) > 0) { $this->view->is_recording = ($rows[0]['record'] == 1); } @@ -664,7 +688,7 @@ class ApiController extends Zend_Controller_Action try { $show_inst = new Application_Model_ShowInstance($show_instance_id); $show_inst->setRecordedFile($file_id); - } + } catch (Exception $e) { //we've reached here probably because the show was //cancelled, and therefore the show instance does not exist @@ -717,7 +741,7 @@ class ApiController extends Zend_Controller_Action if ($md['is_record'] != 0) { $this->uploadRecordedActionParam($md['MDATA_KEY_TRACKNUMBER'], $file->getId()); } - + } elseif ($mode == "modify") { $filepath = $md['MDATA_KEY_FILEPATH']; $file = Application_Model_StoredFile::RecallByFilepath($filepath, $con); @@ -830,7 +854,7 @@ class ApiController extends Zend_Controller_Action } catch (Exception $e) { Logging::warn($e->getMessage()); Logging::warn(gettype($e)); - } + } // We tack on the 'key' back to every request in case the would like to associate // his requests with particular responses $response['key'] = $k; @@ -1085,7 +1109,7 @@ class ApiController extends Zend_Controller_Action } elseif ($djtype == "dj") { //check against show dj auth $showInfo = Application_Model_Show::getCurrentShow(); - + // there is current playing show if (isset($showInfo[0]['id'])) { $current_show_id = $showInfo[0]['id']; @@ -1139,12 +1163,12 @@ class ApiController extends Zend_Controller_Action $this->_helper->json->sendJson($rows); } - + public function getFilesWithoutSilanValueAction() { //connect to db and get get sql $rows = Application_Model_StoredFile::getAllFilesWithoutSilan(); - + $this->_helper->json->sendJson($rows); } @@ -1163,7 +1187,7 @@ class ApiController extends Zend_Controller_Action $this->_helper->json->sendJson(array()); } - + public function updateCueValuesBySilanAction() { $request = $this->getRequest(); @@ -1213,12 +1237,12 @@ class ApiController extends Zend_Controller_Action $data = $request->getParam("data"); $media_id = intval($request->getParam("media_id")); $data_arr = json_decode($data); - + //$media_id is -1 sometimes when a stream has stopped playing if (!is_null($media_id) && $media_id > 0) { if (isset($data_arr->title)) { - + $data_title = substr($data_arr->title, 0, 1024); $previous_metadata = CcWebstreamMetadataQuery::create() @@ -1235,20 +1259,20 @@ class ApiController extends Zend_Controller_Action } if ($do_insert) { - + $startDT = new DateTime("now", new DateTimeZone("UTC")); - + $webstream_metadata = new CcWebstreamMetadata(); $webstream_metadata->setDbInstanceId($media_id); $webstream_metadata->setDbStartTime($startDT); $webstream_metadata->setDbLiquidsoapData($data_title); $webstream_metadata->save(); - + $historyService = new Application_Service_HistoryService(); $historyService->insertWebstreamMetadata($media_id, $startDT, $data_arr); } } - } + } $this->view->response = $data; $this->view->media_id = $media_id; @@ -1271,11 +1295,11 @@ class ApiController extends Zend_Controller_Action Application_Model_ListenerStat::insertDataPoints($data); $this->view->data = $data; } - + public function updateStreamSettingTableAction() { $request = $this->getRequest(); $data = json_decode($request->getParam("data"), true); - + foreach ($data as $k=>$v) { Application_Model_StreamSetting::SetListenerStatError($k, $v); } @@ -1317,9 +1341,9 @@ class ApiController extends Zend_Controller_Action $request = $this->getRequest(); $params = $request->getParams(); $userId = $request->getParam("user_id", null); - + list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request); - + $historyService = new Application_Service_HistoryService(); $shows = $historyService->getShowList($startsDT, $endsDT, $userId); @@ -1343,8 +1367,8 @@ class ApiController extends Zend_Controller_Action $params = $request->getParams(); $showId = $request->getParam("show_id", null); $results = array(); - - if (empty($showId)) { + + if (empty($showId)) { $shows = CcShowQuery::create()->find(); foreach($shows as $show) { $results[] = $show->getShowInfo(); @@ -1361,19 +1385,19 @@ class ApiController extends Zend_Controller_Action Logging::info($e->getMessage()); } } - + /** * display show schedule for given show_id * * @return json array */ - public function showSchedulesAction() + public function showSchedulesAction() { try { $request = $this->getRequest(); $params = $request->getParams(); $showId = $request->getParam("show_id", null); - + list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request); if ((!isset($showId)) || (!is_numeric($showId))) { @@ -1382,7 +1406,7 @@ class ApiController extends Zend_Controller_Action array("jsonrpc" => "2.0", "error" => array("code" => 400, "message" => "missing invalid type for required show_id parameter. use type int.".$showId)) ); } - + $shows = Application_Model_Show::getShows($startsDT, $endsDT, FALSE, $showId); // is this a valid show? @@ -1400,7 +1424,7 @@ class ApiController extends Zend_Controller_Action } } - + /** * displays track listing for given instance_id * @@ -1421,7 +1445,7 @@ class ApiController extends Zend_Controller_Action $showInstance = new Application_Model_ShowInstance($instanceId); $showInstanceContent = $showInstance->getShowListContent($prefTimezone); - + // is this a valid show instance with content? if (empty($showInstanceContent)) { $this->_helper->json->sendJson( diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 7ec84ddef..aefad2114 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -364,6 +364,7 @@ class LibraryController extends Zend_Controller_Action { $user = Application_Model_User::getCurrentUser(); $isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); + $isAdmin = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN)); $request = $this->getRequest(); @@ -380,6 +381,10 @@ class LibraryController extends Zend_Controller_Action $form->removeActionButtons(); $this->view->permissionDenied = true; } + // only admins should be able to edit the owner of a file + if (!$isAdmin) { + $form->removeOwnerEdit(); + } if ($request->isPost()) { diff --git a/airtime_mvc/application/controllers/LocaleController.php b/airtime_mvc/application/controllers/LocaleController.php index c20142f99..01810176c 100644 --- a/airtime_mvc/application/controllers/LocaleController.php +++ b/airtime_mvc/application/controllers/LocaleController.php @@ -63,6 +63,16 @@ final class LocaleController extends Zend_Controller_Action //"Adding 1 Item" => _("Adding 1 Item"), //"Adding %s Items" => _("Adding %s Items"), //library/library.js + "Add" => _("Add"), + "New" => _("New"), + "Edit" => _("Edit"), + "Add to Schedule" => _("Add to Schedule"), + "Add to next show" => _("Add to next show"), + "Add to current show" => _("Add to current show"), + "Add after selected items" => _("Add after selected items"), + "Delete" => _("Delete"), + "Publish" => _("Publish"), + "Remove" => _("Remove"), "Edit Metadata" => _("Edit Metadata"), "Add to selected show" => _("Add to selected show"), "Select" => _("Select"), @@ -108,6 +118,10 @@ final class LocaleController extends Zend_Controller_Action "Are you sure you want to delete the selected item?" => _("Are you sure you want to delete the selected item?"), "Uploading in progress..." => _("Uploading in progress..."), "Retrieving data from the server..." => _("Retrieving data from the server..."), + //library/podcast.js + "Import" => _("Import"), + "Imported?" => _("Imported?"), + "View" => _("View"), // SOUNDCLOUD "Are you sure? SoundCloud stats and comments for this track will be permanently removed." => "Are you sure? SoundCloud stats and comments for this track will be permanently removed.", "Your track is being deleted from SoundCloud" => "Your track is being deleted from SoundCloud", @@ -314,6 +328,7 @@ final class LocaleController extends Zend_Controller_Action "Trim overbooked shows" => _("Trim overbooked shows"), "Remove selected scheduled items" => _("Remove selected scheduled items"), "Jump to the current playing track" => _("Jump to the current playing track"), + "Jump to Current" => _("Jump to Current"), "Cancel current show" => _("Cancel current show"), //already in schedule/schedule.js //"Cancel Current Show?" => _("Cancel Current Show?"), @@ -355,6 +370,7 @@ final class LocaleController extends Zend_Controller_Action "View listener stats" => _("View listener stats"), //dataTables/ColVis.js "Show / hide columns" => _("Show / hide columns"), + "Columns" => _("Columns"), //datatables.columnFilter.js "From {from} to {to}" => _("From {from} to {to}"), "kbps" => _("kbps"), diff --git a/airtime_mvc/application/controllers/LoginController.php b/airtime_mvc/application/controllers/LoginController.php index c12a00153..8065b637d 100644 --- a/airtime_mvc/application/controllers/LoginController.php +++ b/airtime_mvc/application/controllers/LoginController.php @@ -58,11 +58,7 @@ class LoginController extends Zend_Controller_Action //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. //session_start(); - // if the post contains recaptcha field, which means form had recaptcha field. - // Hence add the element for validation. - if (array_key_exists('recaptcha_response_field', $request->getPost())) { - $form->addRecaptcha(); - } + if ($form->isValid($request->getPost())) { //get the username and password from the form $username = $form->getValue('username'); @@ -276,10 +272,6 @@ class LoginController extends Zend_Controller_Action Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']); $form = new Application_Form_Login(); $this->view->error = true; - //Only show the captcha if you get your login wrong 4 times in a row. - if (Application_Model_Subjects::getLoginAttempts($username) > 3) { - $form->addRecaptcha(); - } return $form; } } diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index 4c63d73e5..685bfd480 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -64,7 +64,7 @@ class PlaylistController extends Zend_Controller_Action $this->view->obj = $obj; $this->view->contents = $obj->getContents(); - if ($formIsValid) { + if ($formIsValid && $obj instanceof Application_Model_Block) { $this->view->poolCount = $obj->getListofFilesMeetCriteria()['count']; } $this->view->showPoolCount = true; diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 6c9b0bfd9..5c1baf132 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -47,6 +47,8 @@ class PreferenceController extends Zend_Controller_Action Application_Model_Preference::SetDefaultFadeOut($values["stationDefaultFadeOut"]); Application_Model_Preference::SetPodcastAlbumOverride($values["podcastAlbumOverride"]); Application_Model_Preference::SetPodcastAutoSmartblock($values["podcastAutoSmartblock"]); + Application_Model_Preference::SetIntroPlaylist($values["introPlaylistSelect"]); + Application_Model_Preference::SetOutroPlaylist($values["outroPlaylistSelect"]); Application_Model_Preference::SetAllow3rdPartyApi($values["thirdPartyApi"]); Application_Model_Preference::SetAllowedCorsUrls($values["allowedCorsUrls"]); Application_Model_Preference::SetDefaultLocale($values["locale"]); @@ -110,47 +112,6 @@ class PreferenceController extends Zend_Controller_Action $this->_helper->json->sendJson(array("url" => $url)); } - public function supportSettingAction() - { - $CC_CONFIG = Config::getConfig(); - - $request = $this->getRequest(); - - $baseUrl = Application_Common_OsPath::getBaseDir(); - - $this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/support-setting.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); - $this->view->statusMsg = ""; - - SessionHelper::reopenSessionForWriting(); - - $form = new Application_Form_SupportSettings(); - if ($request->isPost()) { - $values = $request->getPost(); - if ($form->isValid($values)) { - Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view); - Application_Model_Preference::SetPhone($values["Phone"]); - Application_Model_Preference::SetEmail($values["Email"]); - Application_Model_Preference::SetStationWebSite($values["StationWebSite"]); - - Application_Model_Preference::SetStationCountry($values["Country"]); - Application_Model_Preference::SetStationCity($values["City"]); - Application_Model_Preference::SetStationDescription($values["Description"]); - if (isset($values["Privacy"])) { - Application_Model_Preference::SetPrivacyPolicyCheck($values["Privacy"]); - } - } - $this->view->statusMsg = "
+ * $query->filterByDbCriteriaGroup(1234); // WHERE criteriagroup = 1234
+ * $query->filterByDbCriteriaGroup(array(12, 34)); // WHERE criteriagroup IN (12, 34)
+ * $query->filterByDbCriteriaGroup(array('min' => 12)); // WHERE criteriagroup >= 12
+ * $query->filterByDbCriteriaGroup(array('max' => 12)); // WHERE criteriagroup <= 12
+ *
+ *
+ * @param mixed $dbCriteriaGroup The value to use as filter.
+ * Use scalar values for equality.
+ * Use array values for in_array() equivalent.
+ * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
+ * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
+ *
+ * @return CcBlockcriteriaQuery The current query, for fluid interface
+ */
+ public function filterByDbCriteriaGroup($dbCriteriaGroup = null, $comparison = null)
+ {
+ if (is_array($dbCriteriaGroup)) {
+ $useMinMax = false;
+ if (isset($dbCriteriaGroup['min'])) {
+ $this->addUsingAlias(CcBlockcriteriaPeer::CRITERIAGROUP, $dbCriteriaGroup['min'], Criteria::GREATER_EQUAL);
+ $useMinMax = true;
+ }
+ if (isset($dbCriteriaGroup['max'])) {
+ $this->addUsingAlias(CcBlockcriteriaPeer::CRITERIAGROUP, $dbCriteriaGroup['max'], Criteria::LESS_EQUAL);
+ $useMinMax = true;
+ }
+ if ($useMinMax) {
+ return $this;
+ }
+ if (null === $comparison) {
+ $comparison = Criteria::IN;
+ }
+ }
+
+ return $this->addUsingAlias(CcBlockcriteriaPeer::CRITERIAGROUP, $dbCriteriaGroup, $comparison);
+ }
+
/**
* Filter the query on the block_id column
*
diff --git a/airtime_mvc/application/models/airtime/om/BaseCcPlaylistcontents.php b/airtime_mvc/application/models/airtime/om/BaseCcPlaylistcontents.php
index 1c634b382..b0552a756 100644
--- a/airtime_mvc/application/models/airtime/om/BaseCcPlaylistcontents.php
+++ b/airtime_mvc/application/models/airtime/om/BaseCcPlaylistcontents.php
@@ -74,7 +74,7 @@ abstract class BaseCcPlaylistcontents extends BaseObject implements Persistent
/**
* The value for the trackoffset field.
- * Note: this column has a database default value of: 0
+ * Note: this column has a database default value of: 0.0
* @var double
*/
protected $trackoffset;
@@ -161,7 +161,7 @@ abstract class BaseCcPlaylistcontents extends BaseObject implements Persistent
public function applyDefaultValues()
{
$this->type = 0;
- $this->trackoffset = 0;
+ $this->trackoffset = 0.0;
$this->cliplength = '00:00:00';
$this->cuein = '00:00:00';
$this->cueout = '00:00:00';
@@ -677,7 +677,7 @@ abstract class BaseCcPlaylistcontents extends BaseObject implements Persistent
return false;
}
- if ($this->trackoffset !== 0) {
+ if ($this->trackoffset !== 0.0) {
return false;
}
diff --git a/airtime_mvc/application/models/airtime/om/BasePodcastEpisodes.php b/airtime_mvc/application/models/airtime/om/BasePodcastEpisodes.php
index e39015230..23e331847 100644
--- a/airtime_mvc/application/models/airtime/om/BasePodcastEpisodes.php
+++ b/airtime_mvc/application/models/airtime/om/BasePodcastEpisodes.php
@@ -65,6 +65,18 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
*/
protected $episode_guid;
+ /**
+ * The value for the episode_title field.
+ * @var string
+ */
+ protected $episode_title;
+
+ /**
+ * The value for the episode_description field.
+ * @var string
+ */
+ protected $episode_description;
+
/**
* @var CcFiles
*/
@@ -185,6 +197,28 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
return $this->episode_guid;
}
+ /**
+ * Get the [episode_title] column value.
+ *
+ * @return string
+ */
+ public function getDbEpisodeTitle()
+ {
+
+ return $this->episode_title;
+ }
+
+ /**
+ * Get the [episode_description] column value.
+ *
+ * @return string
+ */
+ public function getDbEpisodeDescription()
+ {
+
+ return $this->episode_description;
+ }
+
/**
* Set the value of [id] column.
*
@@ -321,6 +355,48 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
return $this;
} // setDbEpisodeGuid()
+ /**
+ * Set the value of [episode_title] column.
+ *
+ * @param string $v new value
+ * @return PodcastEpisodes The current object (for fluent API support)
+ */
+ public function setDbEpisodeTitle($v)
+ {
+ if ($v !== null && is_numeric($v)) {
+ $v = (string) $v;
+ }
+
+ if ($this->episode_title !== $v) {
+ $this->episode_title = $v;
+ $this->modifiedColumns[] = PodcastEpisodesPeer::EPISODE_TITLE;
+ }
+
+
+ return $this;
+ } // setDbEpisodeTitle()
+
+ /**
+ * Set the value of [episode_description] column.
+ *
+ * @param string $v new value
+ * @return PodcastEpisodes The current object (for fluent API support)
+ */
+ public function setDbEpisodeDescription($v)
+ {
+ if ($v !== null && is_numeric($v)) {
+ $v = (string) $v;
+ }
+
+ if ($this->episode_description !== $v) {
+ $this->episode_description = $v;
+ $this->modifiedColumns[] = PodcastEpisodesPeer::EPISODE_DESCRIPTION;
+ }
+
+
+ return $this;
+ } // setDbEpisodeDescription()
+
/**
* Indicates whether the columns in this object are only set to default values.
*
@@ -359,6 +435,8 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
$this->publication_date = ($row[$startcol + 3] !== null) ? (string) $row[$startcol + 3] : null;
$this->download_url = ($row[$startcol + 4] !== null) ? (string) $row[$startcol + 4] : null;
$this->episode_guid = ($row[$startcol + 5] !== null) ? (string) $row[$startcol + 5] : null;
+ $this->episode_title = ($row[$startcol + 6] !== null) ? (string) $row[$startcol + 6] : null;
+ $this->episode_description = ($row[$startcol + 7] !== null) ? (string) $row[$startcol + 7] : null;
$this->resetModified();
$this->setNew(false);
@@ -368,7 +446,7 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
}
$this->postHydrate($row, $startcol, $rehydrate);
- return $startcol + 6; // 6 = PodcastEpisodesPeer::NUM_HYDRATE_COLUMNS.
+ return $startcol + 8; // 8 = PodcastEpisodesPeer::NUM_HYDRATE_COLUMNS.
} catch (Exception $e) {
throw new PropelException("Error populating PodcastEpisodes object", $e);
@@ -635,6 +713,12 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
if ($this->isColumnModified(PodcastEpisodesPeer::EPISODE_GUID)) {
$modifiedColumns[':p' . $index++] = '"episode_guid"';
}
+ if ($this->isColumnModified(PodcastEpisodesPeer::EPISODE_TITLE)) {
+ $modifiedColumns[':p' . $index++] = '"episode_title"';
+ }
+ if ($this->isColumnModified(PodcastEpisodesPeer::EPISODE_DESCRIPTION)) {
+ $modifiedColumns[':p' . $index++] = '"episode_description"';
+ }
$sql = sprintf(
'INSERT INTO "podcast_episodes" (%s) VALUES (%s)',
@@ -664,6 +748,12 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
case '"episode_guid"':
$stmt->bindValue($identifier, $this->episode_guid, PDO::PARAM_STR);
break;
+ case '"episode_title"':
+ $stmt->bindValue($identifier, $this->episode_title, PDO::PARAM_STR);
+ break;
+ case '"episode_description"':
+ $stmt->bindValue($identifier, $this->episode_description, PDO::PARAM_STR);
+ break;
}
}
$stmt->execute();
@@ -827,6 +917,12 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
case 5:
return $this->getDbEpisodeGuid();
break;
+ case 6:
+ return $this->getDbEpisodeTitle();
+ break;
+ case 7:
+ return $this->getDbEpisodeDescription();
+ break;
default:
return null;
break;
@@ -862,6 +958,8 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
$keys[3] => $this->getDbPublicationDate(),
$keys[4] => $this->getDbDownloadUrl(),
$keys[5] => $this->getDbEpisodeGuid(),
+ $keys[6] => $this->getDbEpisodeTitle(),
+ $keys[7] => $this->getDbEpisodeDescription(),
);
$virtualColumns = $this->virtualColumns;
foreach ($virtualColumns as $key => $virtualColumn) {
@@ -927,6 +1025,12 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
case 5:
$this->setDbEpisodeGuid($value);
break;
+ case 6:
+ $this->setDbEpisodeTitle($value);
+ break;
+ case 7:
+ $this->setDbEpisodeDescription($value);
+ break;
} // switch()
}
@@ -957,6 +1061,8 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
if (array_key_exists($keys[3], $arr)) $this->setDbPublicationDate($arr[$keys[3]]);
if (array_key_exists($keys[4], $arr)) $this->setDbDownloadUrl($arr[$keys[4]]);
if (array_key_exists($keys[5], $arr)) $this->setDbEpisodeGuid($arr[$keys[5]]);
+ if (array_key_exists($keys[6], $arr)) $this->setDbEpisodeTitle($arr[$keys[6]]);
+ if (array_key_exists($keys[7], $arr)) $this->setDbEpisodeDescription($arr[$keys[7]]);
}
/**
@@ -974,6 +1080,8 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
if ($this->isColumnModified(PodcastEpisodesPeer::PUBLICATION_DATE)) $criteria->add(PodcastEpisodesPeer::PUBLICATION_DATE, $this->publication_date);
if ($this->isColumnModified(PodcastEpisodesPeer::DOWNLOAD_URL)) $criteria->add(PodcastEpisodesPeer::DOWNLOAD_URL, $this->download_url);
if ($this->isColumnModified(PodcastEpisodesPeer::EPISODE_GUID)) $criteria->add(PodcastEpisodesPeer::EPISODE_GUID, $this->episode_guid);
+ if ($this->isColumnModified(PodcastEpisodesPeer::EPISODE_TITLE)) $criteria->add(PodcastEpisodesPeer::EPISODE_TITLE, $this->episode_title);
+ if ($this->isColumnModified(PodcastEpisodesPeer::EPISODE_DESCRIPTION)) $criteria->add(PodcastEpisodesPeer::EPISODE_DESCRIPTION, $this->episode_description);
return $criteria;
}
@@ -1042,6 +1150,8 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
$copyObj->setDbPublicationDate($this->getDbPublicationDate());
$copyObj->setDbDownloadUrl($this->getDbDownloadUrl());
$copyObj->setDbEpisodeGuid($this->getDbEpisodeGuid());
+ $copyObj->setDbEpisodeTitle($this->getDbEpisodeTitle());
+ $copyObj->setDbEpisodeDescription($this->getDbEpisodeDescription());
if ($deepCopy && !$this->startCopy) {
// important: temporarily setNew(false) because this affects the behavior of
@@ -1215,6 +1325,8 @@ abstract class BasePodcastEpisodes extends BaseObject implements Persistent
$this->publication_date = null;
$this->download_url = null;
$this->episode_guid = null;
+ $this->episode_title = null;
+ $this->episode_description = null;
$this->alreadyInSave = false;
$this->alreadyInValidation = false;
$this->alreadyInClearAllReferencesDeep = false;
diff --git a/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesPeer.php b/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesPeer.php
index 3415c9345..91fcbeee2 100644
--- a/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesPeer.php
+++ b/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesPeer.php
@@ -24,13 +24,13 @@ abstract class BasePodcastEpisodesPeer
const TM_CLASS = 'PodcastEpisodesTableMap';
/** The total number of columns. */
- const NUM_COLUMNS = 6;
+ const NUM_COLUMNS = 8;
/** The number of lazy-loaded columns. */
const NUM_LAZY_LOAD_COLUMNS = 0;
/** The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */
- const NUM_HYDRATE_COLUMNS = 6;
+ const NUM_HYDRATE_COLUMNS = 8;
/** the column name for the id field */
const ID = 'podcast_episodes.id';
@@ -50,6 +50,12 @@ abstract class BasePodcastEpisodesPeer
/** the column name for the episode_guid field */
const EPISODE_GUID = 'podcast_episodes.episode_guid';
+ /** the column name for the episode_title field */
+ const EPISODE_TITLE = 'podcast_episodes.episode_title';
+
+ /** the column name for the episode_description field */
+ const EPISODE_DESCRIPTION = 'podcast_episodes.episode_description';
+
/** The default string format for model objects of the related table **/
const DEFAULT_STRING_FORMAT = 'YAML';
@@ -69,12 +75,12 @@ abstract class BasePodcastEpisodesPeer
* e.g. PodcastEpisodesPeer::$fieldNames[PodcastEpisodesPeer::TYPE_PHPNAME][0] = 'Id'
*/
protected static $fieldNames = array (
- BasePeer::TYPE_PHPNAME => array ('DbId', 'DbFileId', 'DbPodcastId', 'DbPublicationDate', 'DbDownloadUrl', 'DbEpisodeGuid', ),
- BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbFileId', 'dbPodcastId', 'dbPublicationDate', 'dbDownloadUrl', 'dbEpisodeGuid', ),
- BasePeer::TYPE_COLNAME => array (PodcastEpisodesPeer::ID, PodcastEpisodesPeer::FILE_ID, PodcastEpisodesPeer::PODCAST_ID, PodcastEpisodesPeer::PUBLICATION_DATE, PodcastEpisodesPeer::DOWNLOAD_URL, PodcastEpisodesPeer::EPISODE_GUID, ),
- BasePeer::TYPE_RAW_COLNAME => array ('ID', 'FILE_ID', 'PODCAST_ID', 'PUBLICATION_DATE', 'DOWNLOAD_URL', 'EPISODE_GUID', ),
- BasePeer::TYPE_FIELDNAME => array ('id', 'file_id', 'podcast_id', 'publication_date', 'download_url', 'episode_guid', ),
- BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, )
+ BasePeer::TYPE_PHPNAME => array ('DbId', 'DbFileId', 'DbPodcastId', 'DbPublicationDate', 'DbDownloadUrl', 'DbEpisodeGuid', 'DbEpisodeTitle', 'DbEpisodeDescription', ),
+ BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbFileId', 'dbPodcastId', 'dbPublicationDate', 'dbDownloadUrl', 'dbEpisodeGuid', 'dbEpisodeTitle', 'dbEpisodeDescription', ),
+ BasePeer::TYPE_COLNAME => array (PodcastEpisodesPeer::ID, PodcastEpisodesPeer::FILE_ID, PodcastEpisodesPeer::PODCAST_ID, PodcastEpisodesPeer::PUBLICATION_DATE, PodcastEpisodesPeer::DOWNLOAD_URL, PodcastEpisodesPeer::EPISODE_GUID, PodcastEpisodesPeer::EPISODE_TITLE, PodcastEpisodesPeer::EPISODE_DESCRIPTION, ),
+ BasePeer::TYPE_RAW_COLNAME => array ('ID', 'FILE_ID', 'PODCAST_ID', 'PUBLICATION_DATE', 'DOWNLOAD_URL', 'EPISODE_GUID', 'EPISODE_TITLE', 'EPISODE_DESCRIPTION', ),
+ BasePeer::TYPE_FIELDNAME => array ('id', 'file_id', 'podcast_id', 'publication_date', 'download_url', 'episode_guid', 'episode_title', 'episode_description', ),
+ BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, )
);
/**
@@ -84,12 +90,12 @@ abstract class BasePodcastEpisodesPeer
* e.g. PodcastEpisodesPeer::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0
*/
protected static $fieldKeys = array (
- BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbFileId' => 1, 'DbPodcastId' => 2, 'DbPublicationDate' => 3, 'DbDownloadUrl' => 4, 'DbEpisodeGuid' => 5, ),
- BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbFileId' => 1, 'dbPodcastId' => 2, 'dbPublicationDate' => 3, 'dbDownloadUrl' => 4, 'dbEpisodeGuid' => 5, ),
- BasePeer::TYPE_COLNAME => array (PodcastEpisodesPeer::ID => 0, PodcastEpisodesPeer::FILE_ID => 1, PodcastEpisodesPeer::PODCAST_ID => 2, PodcastEpisodesPeer::PUBLICATION_DATE => 3, PodcastEpisodesPeer::DOWNLOAD_URL => 4, PodcastEpisodesPeer::EPISODE_GUID => 5, ),
- BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'FILE_ID' => 1, 'PODCAST_ID' => 2, 'PUBLICATION_DATE' => 3, 'DOWNLOAD_URL' => 4, 'EPISODE_GUID' => 5, ),
- BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'file_id' => 1, 'podcast_id' => 2, 'publication_date' => 3, 'download_url' => 4, 'episode_guid' => 5, ),
- BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, )
+ BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbFileId' => 1, 'DbPodcastId' => 2, 'DbPublicationDate' => 3, 'DbDownloadUrl' => 4, 'DbEpisodeGuid' => 5, 'DbEpisodeTitle' => 6, 'DbEpisodeDescription' => 7, ),
+ BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbFileId' => 1, 'dbPodcastId' => 2, 'dbPublicationDate' => 3, 'dbDownloadUrl' => 4, 'dbEpisodeGuid' => 5, 'dbEpisodeTitle' => 6, 'dbEpisodeDescription' => 7, ),
+ BasePeer::TYPE_COLNAME => array (PodcastEpisodesPeer::ID => 0, PodcastEpisodesPeer::FILE_ID => 1, PodcastEpisodesPeer::PODCAST_ID => 2, PodcastEpisodesPeer::PUBLICATION_DATE => 3, PodcastEpisodesPeer::DOWNLOAD_URL => 4, PodcastEpisodesPeer::EPISODE_GUID => 5, PodcastEpisodesPeer::EPISODE_TITLE => 6, PodcastEpisodesPeer::EPISODE_DESCRIPTION => 7, ),
+ BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'FILE_ID' => 1, 'PODCAST_ID' => 2, 'PUBLICATION_DATE' => 3, 'DOWNLOAD_URL' => 4, 'EPISODE_GUID' => 5, 'EPISODE_TITLE' => 6, 'EPISODE_DESCRIPTION' => 7, ),
+ BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'file_id' => 1, 'podcast_id' => 2, 'publication_date' => 3, 'download_url' => 4, 'episode_guid' => 5, 'episode_title' => 6, 'episode_description' => 7, ),
+ BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, )
);
/**
@@ -169,6 +175,8 @@ abstract class BasePodcastEpisodesPeer
$criteria->addSelectColumn(PodcastEpisodesPeer::PUBLICATION_DATE);
$criteria->addSelectColumn(PodcastEpisodesPeer::DOWNLOAD_URL);
$criteria->addSelectColumn(PodcastEpisodesPeer::EPISODE_GUID);
+ $criteria->addSelectColumn(PodcastEpisodesPeer::EPISODE_TITLE);
+ $criteria->addSelectColumn(PodcastEpisodesPeer::EPISODE_DESCRIPTION);
} else {
$criteria->addSelectColumn($alias . '.id');
$criteria->addSelectColumn($alias . '.file_id');
@@ -176,6 +184,8 @@ abstract class BasePodcastEpisodesPeer
$criteria->addSelectColumn($alias . '.publication_date');
$criteria->addSelectColumn($alias . '.download_url');
$criteria->addSelectColumn($alias . '.episode_guid');
+ $criteria->addSelectColumn($alias . '.episode_title');
+ $criteria->addSelectColumn($alias . '.episode_description');
}
}
diff --git a/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesQuery.php b/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesQuery.php
index fbf44a00f..f96d61b8d 100644
--- a/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesQuery.php
+++ b/airtime_mvc/application/models/airtime/om/BasePodcastEpisodesQuery.php
@@ -12,6 +12,8 @@
* @method PodcastEpisodesQuery orderByDbPublicationDate($order = Criteria::ASC) Order by the publication_date column
* @method PodcastEpisodesQuery orderByDbDownloadUrl($order = Criteria::ASC) Order by the download_url column
* @method PodcastEpisodesQuery orderByDbEpisodeGuid($order = Criteria::ASC) Order by the episode_guid column
+ * @method PodcastEpisodesQuery orderByDbEpisodeTitle($order = Criteria::ASC) Order by the episode_title column
+ * @method PodcastEpisodesQuery orderByDbEpisodeDescription($order = Criteria::ASC) Order by the episode_description column
*
* @method PodcastEpisodesQuery groupByDbId() Group by the id column
* @method PodcastEpisodesQuery groupByDbFileId() Group by the file_id column
@@ -19,6 +21,8 @@
* @method PodcastEpisodesQuery groupByDbPublicationDate() Group by the publication_date column
* @method PodcastEpisodesQuery groupByDbDownloadUrl() Group by the download_url column
* @method PodcastEpisodesQuery groupByDbEpisodeGuid() Group by the episode_guid column
+ * @method PodcastEpisodesQuery groupByDbEpisodeTitle() Group by the episode_title column
+ * @method PodcastEpisodesQuery groupByDbEpisodeDescription() Group by the episode_description column
*
* @method PodcastEpisodesQuery leftJoin($relation) Adds a LEFT JOIN clause to the query
* @method PodcastEpisodesQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query
@@ -40,6 +44,8 @@
* @method PodcastEpisodes findOneByDbPublicationDate(string $publication_date) Return the first PodcastEpisodes filtered by the publication_date column
* @method PodcastEpisodes findOneByDbDownloadUrl(string $download_url) Return the first PodcastEpisodes filtered by the download_url column
* @method PodcastEpisodes findOneByDbEpisodeGuid(string $episode_guid) Return the first PodcastEpisodes filtered by the episode_guid column
+ * @method PodcastEpisodes findOneByDbEpisodeTitle(string $episode_title) Return the first PodcastEpisodes filtered by the episode_title column
+ * @method PodcastEpisodes findOneByDbEpisodeDescription(string $episode_description) Return the first PodcastEpisodes filtered by the episode_description column
*
* @method array findByDbId(int $id) Return PodcastEpisodes objects filtered by the id column
* @method array findByDbFileId(int $file_id) Return PodcastEpisodes objects filtered by the file_id column
@@ -47,6 +53,8 @@
* @method array findByDbPublicationDate(string $publication_date) Return PodcastEpisodes objects filtered by the publication_date column
* @method array findByDbDownloadUrl(string $download_url) Return PodcastEpisodes objects filtered by the download_url column
* @method array findByDbEpisodeGuid(string $episode_guid) Return PodcastEpisodes objects filtered by the episode_guid column
+ * @method array findByDbEpisodeTitle(string $episode_title) Return PodcastEpisodes objects filtered by the episode_title column
+ * @method array findByDbEpisodeDescription(string $episode_description) Return PodcastEpisodes objects filtered by the episode_description column
*
* @package propel.generator.airtime.om
*/
@@ -154,7 +162,7 @@ abstract class BasePodcastEpisodesQuery extends ModelCriteria
*/
protected function findPkSimple($key, $con)
{
- $sql = 'SELECT "id", "file_id", "podcast_id", "publication_date", "download_url", "episode_guid" FROM "podcast_episodes" WHERE "id" = :p0';
+ $sql = 'SELECT "id", "file_id", "podcast_id", "publication_date", "download_url", "episode_guid", "episode_title", "episode_description" FROM "podcast_episodes" WHERE "id" = :p0';
try {
$stmt = $con->prepare($sql);
$stmt->bindValue(':p0', $key, PDO::PARAM_INT);
@@ -474,6 +482,64 @@ abstract class BasePodcastEpisodesQuery extends ModelCriteria
return $this->addUsingAlias(PodcastEpisodesPeer::EPISODE_GUID, $dbEpisodeGuid, $comparison);
}
+ /**
+ * Filter the query on the episode_title column
+ *
+ * Example usage:
+ *
+ * $query->filterByDbEpisodeTitle('fooValue'); // WHERE episode_title = 'fooValue'
+ * $query->filterByDbEpisodeTitle('%fooValue%'); // WHERE episode_title LIKE '%fooValue%'
+ *
+ *
+ * @param string $dbEpisodeTitle The value to use as filter.
+ * Accepts wildcards (* and % trigger a LIKE)
+ * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
+ *
+ * @return PodcastEpisodesQuery The current query, for fluid interface
+ */
+ public function filterByDbEpisodeTitle($dbEpisodeTitle = null, $comparison = null)
+ {
+ if (null === $comparison) {
+ if (is_array($dbEpisodeTitle)) {
+ $comparison = Criteria::IN;
+ } elseif (preg_match('/[\%\*]/', $dbEpisodeTitle)) {
+ $dbEpisodeTitle = str_replace('*', '%', $dbEpisodeTitle);
+ $comparison = Criteria::LIKE;
+ }
+ }
+
+ return $this->addUsingAlias(PodcastEpisodesPeer::EPISODE_TITLE, $dbEpisodeTitle, $comparison);
+ }
+
+ /**
+ * Filter the query on the episode_description column
+ *
+ * Example usage:
+ *
+ * $query->filterByDbEpisodeDescription('fooValue'); // WHERE episode_description = 'fooValue'
+ * $query->filterByDbEpisodeDescription('%fooValue%'); // WHERE episode_description LIKE '%fooValue%'
+ *
+ *
+ * @param string $dbEpisodeDescription The value to use as filter.
+ * Accepts wildcards (* and % trigger a LIKE)
+ * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
+ *
+ * @return PodcastEpisodesQuery The current query, for fluid interface
+ */
+ public function filterByDbEpisodeDescription($dbEpisodeDescription = null, $comparison = null)
+ {
+ if (null === $comparison) {
+ if (is_array($dbEpisodeDescription)) {
+ $comparison = Criteria::IN;
+ } elseif (preg_match('/[\%\*]/', $dbEpisodeDescription)) {
+ $dbEpisodeDescription = str_replace('*', '%', $dbEpisodeDescription);
+ $comparison = Criteria::LIKE;
+ }
+ }
+
+ return $this->addUsingAlias(PodcastEpisodesPeer::EPISODE_DESCRIPTION, $dbEpisodeDescription, $comparison);
+ }
+
/**
* Filter the query by a related CcFiles object
*
diff --git a/airtime_mvc/application/modules/rest/Bootstrap.php b/airtime_mvc/application/modules/rest/Bootstrap.php
index b8575a2cf..3ac5a1891 100644
--- a/airtime_mvc/application/modules/rest/Bootstrap.php
+++ b/airtime_mvc/application/modules/rest/Bootstrap.php
@@ -21,6 +21,17 @@ class Rest_Bootstrap extends Zend_Application_Module_Bootstrap
);
$router->addRoute('podcast-bulk', $podcastBulkRoute);
+
+ $smartblockPodcastRoute = new Zend_Controller_Router_Route(
+ 'rest/podcast/smartblock',
+ array(
+ 'controller' => 'podcast',
+ 'action' => 'smartblock',
+ 'module' => 'rest'
+ )
+ );
+ $router->addRoute('podcast-smartblock', $smartblockPodcastRoute);
+
$stationPodcastRoute = new Zend_Controller_Router_Route(
'rest/podcast/station',
array(
diff --git a/airtime_mvc/application/modules/rest/controllers/MediaController.php b/airtime_mvc/application/modules/rest/controllers/MediaController.php
index 79208f56c..8444e1841 100644
--- a/airtime_mvc/application/modules/rest/controllers/MediaController.php
+++ b/airtime_mvc/application/modules/rest/controllers/MediaController.php
@@ -130,7 +130,8 @@ class Rest_MediaController extends Zend_Rest_Controller
try {
// REST uploads are not from Zend_Form, hence we handle them using Zend_File_transfer directly
- $upload = new Zend_File_Transfer();
+ // we need to specify an explicit adapter since autodetection broke in php 7.2
+ $upload = new Zend_File_Transfer('Zend_File_Transfer_Adapter_Http');
// this error should not really get hit, letting the user know if it does is nice for debugging
// see: https://github.com/LibreTime/libretime/issues/3#issuecomment-281143417
if (!$upload->isValid('file')) {
diff --git a/airtime_mvc/application/modules/rest/controllers/PodcastController.php b/airtime_mvc/application/modules/rest/controllers/PodcastController.php
index f80b16c34..eb454cb94 100644
--- a/airtime_mvc/application/modules/rest/controllers/PodcastController.php
+++ b/airtime_mvc/application/modules/rest/controllers/PodcastController.php
@@ -191,6 +191,26 @@ class Rest_PodcastController extends Zend_Rest_Controller
$this->_helper->json->sendJson($responseBody);
}
+
+ /**
+ * Endpoint for triggering the generation of a smartblock and playlist to match the podcast name
+ */
+
+ public function smartblockAction() {
+
+ $title = $this->_getParam('title', []);
+ $id = $this->_getParam('id', []);
+ if (!$id) {
+ return;
+ }
+ $podcast = Application_Service_PodcastService::getPodcastById($id);
+
+ // logging::info($podcast);
+ Application_Service_PodcastService::createPodcastSmartblockAndPlaylist($podcast, $title);
+ }
+
+
+
/**
* @throws PodcastNotFoundException
*
diff --git a/airtime_mvc/application/services/PodcastEpisodeService.php b/airtime_mvc/application/services/PodcastEpisodeService.php
index 124290ac2..c6b604563 100644
--- a/airtime_mvc/application/services/PodcastEpisodeService.php
+++ b/airtime_mvc/application/services/PodcastEpisodeService.php
@@ -46,7 +46,7 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
public function importEpisode($podcastId, $episode) {
$e = $this->addPlaceholder($podcastId, $episode);
$p = $e->getPodcast();
- $this->_download($e->getDbId(), $e->getDbDownloadUrl(), $p->getDbTitle(), $this->_getAlbumOverride($p));
+ $this->_download($e->getDbId(), $e->getDbDownloadUrl(), $p->getDbTitle(), $this->_getAlbumOverride($p), $episode["title"]);
return $e;
}
@@ -93,7 +93,7 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
// feed object, or whether it's passed in as json
$enclosure = $episode["enclosure"];
$url = $enclosure instanceof SimplePie_Enclosure ? $enclosure->get_link() : $enclosure["link"];
- return $this->_buildEpisode($podcastId, $url, $episode["guid"], $episode["pub_date"]);
+ return $this->_buildEpisode($podcastId, $url, $episode["guid"], $episode["pub_date"], $episode["title"], $episode["description"]);
}
/**
@@ -103,18 +103,22 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
* @param string $url the download URL for the episode
* @param string $guid the unique id for the episode. Often the same as the download URL
* @param string $publicationDate the publication date of the episode
+ * @param string $title the title of the episode
+ * @param string $description the description of the epsiode
*
* @return PodcastEpisodes the newly created PodcastEpisodes object
*
* @throws Exception
* @throws PropelException
*/
- private function _buildEpisode($podcastId, $url, $guid, $publicationDate) {
+ private function _buildEpisode($podcastId, $url, $guid, $publicationDate, $title, $description) {
$e = new PodcastEpisodes();
$e->setDbPodcastId($podcastId);
$e->setDbDownloadUrl($url);
$e->setDbEpisodeGuid($guid);
$e->setDbPublicationDate($publicationDate);
+ $e->setDbEpisodeTitle($title);
+ $e->setDbEpisodeDescription($description);
$e->save();
return $e;
}
@@ -128,7 +132,7 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
/** @var PodcastEpisodes $episode */
foreach($episodes as $episode) {
$podcast = $episode->getPodcast();
- $this->_download($episode->getDbId(), $episode->getDbDownloadUrl(), $podcast->getDbTitle(), $this->_getAlbumOverride($podcast));
+ $this->_download($episode->getDbId(), $episode->getDbDownloadUrl(), $podcast->getDbTitle(), $this->_getAlbumOverride($podcast), $episode->getDbEpisodeTitle());
}
}
@@ -158,7 +162,7 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
* @param string $title title of podcast to be downloaded - added as album to track metadata
* @param boolean $album_override should we override the album name when downloading
*/
- private function _download($id, $url, $title, $album_override) {
+ private function _download($id, $url, $title, $album_override, $track_title = null) {
$CC_CONFIG = Config::getConfig();
$stationUrl = Application_Common_HTTPHelper::getStationUrl();
$stationUrl .= substr($stationUrl, -1) == '/' ? '' : '/';
@@ -169,7 +173,7 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
'api_key' => $CC_CONFIG["apiKey"][0],
'podcast_name' => $title,
'album_override' => $album_override,
- );
+ 'track_title' => $track_title);
$task = $this->_executeTask(static::$_CELERY_TASKS[self::DOWNLOAD], $data);
// Get the created ThirdPartyTaskReference and set the episode ID so
// we can remove the placeholder if the import ends up stuck in a pending state
@@ -393,9 +397,47 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
foreach ($rss->get_items() as $item) {
/** @var SimplePie_Item $item */
// If the enclosure is empty or has not URL, this isn't a podcast episode (there's no audio data)
+ // technically podcasts shouldn't have multiple enclosures but often CMS add non-audio files
$enclosure = $item->get_enclosure();
$url = $enclosure instanceof SimplePie_Enclosure ? $enclosure->get_link() : $enclosure["link"];
- if (empty($url)) { continue; }
+ if (empty($url)) {
+ continue;
+ }
+ // next we check and see if the enclosure is not an audio file - this can happen from improperly
+ // formatted podcasts and we instead will search through the enclosures and see if there is an audio item
+ // then we pass that on, otherwise we just pass the first item since it is probably an audio file
+ elseif (!(substr($enclosure->get_type(), 0, 5) === 'audio')) {
+ // this is a rather hackish way of accessing the enclosures but get_enclosures() didnt detect multiple
+ // enclosures at certain points so we search through them and then manually create an enclosure object
+ // if we find an audio file in an enclosure and send it off
+ Logging::info('found a non audio');
+ $testenclosures = $enclosures = $item->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure');
+ Logging::info($testenclosures);
+ // we need to check if this is an array otherwise sizeof will fail and stop this whole script
+ if (is_array($testenclosures)) {
+ $numenclosures = sizeof($testenclosures);
+ // now we loop through and look for a audio file and then stop the loop at the first one we find
+ for ($i = 0; $i < $numenclosures + 1; $i++) {
+ $enclosure_attribs = array_values($testenclosures[$i]['attribs'])[0];
+ if (stripos($enclosure_attribs['type'], 'audio') !== false) {
+ $url = $enclosure_attribs['url'];
+ $enclosure = new SimplePie_Enclosure($enclosure_attribs['url'], $enclosure_attribs['type'], $length = $enclosure_attribs['length']);
+ break;
+ }
+ // if we didn't find an audio file we need to continue because there were no audio item enclosures
+ // so this should keep it from showing items without audio items on the episodes list
+ if ($i = $numenclosures) {
+ continue;
+ }
+ }
+ }
+ else {
+ continue;
+ }
+ } else {
+ $enclosure = $item->get_enclosure();
+ }
+ //Logging::info($enclosure);
$itemId = $item->get_id();
$ingested = in_array($itemId, $episodeIds) ? (empty($episodeFiles[$itemId]) ? -1 : 1) : 0;
$file = $ingested > 0 && !empty($episodeFiles[$itemId]) ?
@@ -415,12 +457,11 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
"author" => $this->_buildAuthorString($item),
"description" => htmlspecialchars($item->get_description()),
"pub_date" => $item->get_gmdate(),
- "link" => $item->get_link(),
- "enclosure" => $item->get_enclosure(),
+ "link" => $url,
+ "enclosure" => $enclosure,
"file" => $file
));
}
-
return $episodesArray;
}
diff --git a/airtime_mvc/application/services/PodcastService.php b/airtime_mvc/application/services/PodcastService.php
index b9aecb389..8ea319772 100644
--- a/airtime_mvc/application/services/PodcastService.php
+++ b/airtime_mvc/application/services/PodcastService.php
@@ -162,49 +162,59 @@ class Application_Service_PodcastService
/**
* @param $podcast
+ * @param $title passed in directly from web UI input
* This will automatically create a smartblock and playlist for this podcast.
*/
- public static function createPodcastSmartblockAndPlaylist($podcast)
+ public static function createPodcastSmartblockAndPlaylist($podcast, $title = null)
{
- $newBl = new Application_Model_Block();
- $newBl->setCreator(Application_Model_User::getCurrentUser()->getId());
- $newBl->setName($podcast->getDbTitle());
- $newBl->setDescription('Auto-generated smartblock for podcast');
- $newBl->saveType('dynamic');
- // limit the smartblock to 1 item
- $row = new CcBlockcriteria();
- $row->setDbCriteria('limit');
- $row->setDbModifier('items');
- $row->setDbValue(1);
- $row->setDbBlockId($newBl->getId());
- $row->save();
-
- // sort so that it is the newest item
- $row = new CcBlockcriteria();
- $row->setDbCriteria('sort');
- $row->setDbModifier('N/A');
- $row->setDbValue('newest');
- $row->setDbBlockId($newBl->getId());
- $row->save();
-
- // match the track by ensuring the album title matches the podcast
- $row = new CcBlockcriteria();
- $row->setDbCriteria('album_title');
- $row->setDbModifier('is');
- $row->setDbValue($newBl->getName());
- $row->setDbBlockId($newBl->getId());
- $row->save();
-
- $newPl = new Application_Model_Playlist();
- $newPl->setName($podcast->getDbTitle());
- $newPl->setCreator(Application_Model_User::getCurrentUser()->getId());
- $row = new CcPlaylistcontents();
- $row->setDbBlockId($newBl->getId());
- $row->setDbPlaylistId($newPl->getId());
- $row->setDbType(2);
- $row->save();
+ if (is_array($podcast)) {
+ $newpodcast = new Podcast();
+ $newpodcast->fromArray($podcast, BasePeer::TYPE_FIELDNAME);
+ $podcast = $newpodcast;
}
+ if ($title == null) {
+ $title = $podcast->getDbTitle();
+ }
+ // Base class
+ $newBl = new Application_Model_Block();
+ $newBl->setCreator(Application_Model_User::getCurrentUser()->getId());
+ $newBl->setName($title);
+ $newBl->setDescription('Auto-generated smartblock for podcast');
+ $newBl->saveType('dynamic');
+ // limit the smartblock to 1 item
+ $row = new CcBlockcriteria();
+ $row->setDbCriteria('limit');
+ $row->setDbModifier('items');
+ $row->setDbValue(1);
+ $row->setDbBlockId($newBl->getId());
+ $row->save();
+
+ // sort so that it is the newest item
+ $row = new CcBlockcriteria();
+ $row->setDbCriteria('sort');
+ $row->setDbModifier('N/A');
+ $row->setDbValue('newest');
+ $row->setDbBlockId($newBl->getId());
+ $row->save();
+
+ // match the track by ensuring the album title matches the podcast
+ $row = new CcBlockcriteria();
+ $row->setDbCriteria('album_title');
+ $row->setDbModifier('is');
+ $row->setDbValue($title);
+ $row->setDbBlockId($newBl->getId());
+ $row->save();
+
+ $newPl = new Application_Model_Playlist();
+ $newPl->setName($title);
+ $newPl->setCreator(Application_Model_User::getCurrentUser()->getId());
+ $row = new CcPlaylistcontents();
+ $row->setDbBlockId($newBl->getId());
+ $row->setDbPlaylistId($newPl->getId());
+ $row->setDbType(2);
+ $row->save();
+ }
public static function createStationPodcast()
diff --git a/airtime_mvc/application/upgrade/Upgrades.php b/airtime_mvc/application/upgrade/Upgrades.php
index e305ca228..110584874 100644
--- a/airtime_mvc/application/upgrade/Upgrades.php
+++ b/airtime_mvc/application/upgrade/Upgrades.php
@@ -532,3 +532,60 @@ class AirtimeUpgrader300alpha6 extends AirtimeUpgrader
return '3.0.0-alpha.6';
}
}
+/**
+ * Class AirtimeUpgrader300alpha7
+ *
+ * GH-#636 - https://github.com/LibreTime/libretime/pull/636 - Change dynamic smartblock to be default smartblock type
+ */
+
+
+class AirtimeUpgrader300alpha7 extends AirtimeUpgrader
+{
+ protected function getSupportedSchemaVersions() {
+ return array(
+ '3.0.0-alpha.6'
+ );
+ }
+ public function getNewVersion() {
+ return '3.0.0-alpha.7';
+ }
+
+}
+/**
+ * Class AirtimeUpgrader300alpha7-1
+ *
+ * GH-#659 - https://github.com/LibreTime/libretime/pull/659/ - Add description and title to podcast episodes database table
+ */
+
+
+class AirtimeUpgrader300alpha7_1 extends AirtimeUpgrader
+{
+ protected function getSupportedSchemaVersions() {
+ return array(
+ '3.0.0-alpha.7'
+ );
+ }
+ public function getNewVersion() {
+ return '3.0.0-alpha.7.1';
+ }
+
+}
+/**
+ * Class AirtimeUpgrader300alpha7-2
+ *
+ * GH-#704 - https://github.com/LibreTime/libretime/pull/704/ - Add criteria group to smartblock table to enable database to store separately
+ */
+
+
+
+class AirtimeUpgrader300alpha7_2 extends AirtimeUpgrader
+{
+ protected function getSupportedSchemaVersions() {
+ return array(
+ '3.0.0-alpha.7.1'
+ );
+ }
+ public function getNewVersion() {
+ return '3.0.0-alpha.7.2';
+ }
+}
diff --git a/airtime_mvc/application/views/scripts/embeddablewidgets/schedule.phtml b/airtime_mvc/application/views/scripts/embeddablewidgets/schedule.phtml
index 94538187c..ffbfacb48 100644
--- a/airtime_mvc/application/views/scripts/embeddablewidgets/schedule.phtml
+++ b/airtime_mvc/application/views/scripts/embeddablewidgets/schedule.phtml
@@ -13,12 +13,12 @@