From 92ffa955c30e1bd60e848785d43d077dc05ca984 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Wed, 21 Oct 2015 12:54:50 -0400 Subject: [PATCH] SAAS-1081 - implement station podcast download counter that resets monthly --- .../application/common/TaskManager.php | 41 ++++++++++++++++--- .../controllers/LibraryController.php | 21 ++++++---- .../controllers/plugins/Acl_plugin.php | 8 ++-- airtime_mvc/application/models/Preference.php | 30 ++++++++++++++ .../rest/controllers/MediaController.php | 11 ++++- .../scripts/library/publish-dialog.phtml | 2 +- .../public/js/airtime/library/publish.js | 4 ++ 7 files changed, 94 insertions(+), 23 deletions(-) diff --git a/airtime_mvc/application/common/TaskManager.php b/airtime_mvc/application/common/TaskManager.php index 684585b7f..8a4702d26 100644 --- a/airtime_mvc/application/common/TaskManager.php +++ b/airtime_mvc/application/common/TaskManager.php @@ -25,6 +25,7 @@ final class TaskManager { const TASK_INTERVAL_SECONDS = 30; /** + * * @var $con PDO Propel connection object */ private $_con; @@ -241,6 +242,32 @@ class PodcastTask implements AirtimeTask { } +/** + * Class StationPodcastTask + */ +class StationPodcastTask implements AirtimeTask { + + const STATION_PODCAST_RESET_TIMER_SECONDS = 2.628e+6; // 1 month + + /** + * Check whether or not the download counter for the station podcast should be reset + * + * @return bool true if enough time has passed + */ + public function shouldBeRun() { + $lastReset = Application_Model_Preference::getStationPodcastDownloadResetTimer(); + return empty($lastReset) || (microtime(true) > $lastReset + self::STATION_PODCAST_RESET_TIMER_SECONDS); + } + + /** + * Reset the station podcast download counter + */ + public function run() { + Application_Model_Preference::resetStationPodcastDownloadCounter(); + } + +} + /** * Class TaskFactory Factory class to abstract task instantiation */ @@ -251,17 +278,19 @@ class TaskFactory { * Task types - values don't really matter as long as they're unique */ - const UPGRADE = "upgrade"; - const CELERY = "celery"; - const PODCAST = "podcast"; + const UPGRADE = "upgrade"; + const CELERY = "celery"; + const PODCAST = "podcast"; + const STATION_PODCAST = "station-podcast"; /** * @var array map of arbitrary identifiers to class names to be instantiated reflectively */ public static $tasks = array( - "upgrade" => "UpgradeTask", - "celery" => "CeleryTask", - "podcast" => "PodcastTask", + "upgrade" => "UpgradeTask", + "celery" => "CeleryTask", + "podcast" => "PodcastTask", + "station-podcast" => "StationPodcastTask", ); /** diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 08ff4618a..63ccf4949 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -137,18 +137,20 @@ class LibraryController extends Zend_Controller_Action if ($isAdminOrPM || $ownerId == $user->getId()) { $soundcloudService = new Application_Service_SoundcloudService(); if ($type === "audioclip" && $soundcloudService->hasAccessToken()) { - - //create a menu separator - $menu["sep1"] = "-----------"; - - //create a sub menu for Soundcloud actions. - $menu["soundcloud"] = array("name" => _(SOUNDCLOUD), "icon" => "soundcloud", "items" => array()); - $serviceId = $soundcloudService->getServiceId($id); if (!is_null($file) && $serviceId != 0) { + //create a menu separator + $menu["sep1"] = "-----------"; + + //create a sub menu for Soundcloud actions. + $menu["soundcloud"] = array("name" => _(SOUNDCLOUD), "icon" => "soundcloud", "items" => array()); $menu["soundcloud"]["items"]["view"] = array("name" => _("View track"), "icon" => "soundcloud", "url" => $baseUrl . "soundcloud/view-on-sound-cloud/id/{$id}"); - $menu["soundcloud"]["items"]["remove"] = array("name" => _("Remove track"), "icon" => "soundcloud", "url" => $baseUrl . "soundcloud/delete/id/{$id}"); - } else { + // $menu["soundcloud"]["items"]["remove"] = array("name" => _("Remove track"), "icon" => "soundcloud", "url" => $baseUrl . "soundcloud/delete/id/{$id}"); + } + /* + Since we upload to SoundCloud from the Publish dialog now, this is unnecessary + + else { // If a reference exists for this file ID, that means the user has uploaded the track // but we haven't yet gotten a response from Celery, so disable the menu item if ($soundcloudService->referenceExists($id)) { @@ -163,6 +165,7 @@ class LibraryController extends Zend_Controller_Action ); } } + */ } } } elseif ($type === "playlist" || $type === "block") { diff --git a/airtime_mvc/application/controllers/plugins/Acl_plugin.php b/airtime_mvc/application/controllers/plugins/Acl_plugin.php index deee839ec..01b977079 100644 --- a/airtime_mvc/application/controllers/plugins/Acl_plugin.php +++ b/airtime_mvc/application/controllers/plugins/Acl_plugin.php @@ -217,13 +217,13 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract $request->getActionName())) { /** Redirect to access denied page */ $this->setErrorPage('error403'); - $this->denyAccess(); /* This results in a 404! */ + $this->denyAccess(); } } } private function verifyAuth() { - if ($this->isVerifiedDownload() || $this->verifyAPIKey()) { + if ($this->verifyAPIKey() || $this->isVerifiedDownload()) { return true; } @@ -252,9 +252,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract $action = $request->getActionName(); $stationPodcast = StationPodcastQuery::create() ->findOneByDbPodcastId(Application_Model_Preference::getStationPodcastId()); - return $module == "rest" - && $controller == "media" - && $action == "download" + return $module == "rest" && $controller == "media" && $action == "download" && $key === Application_Model_Preference::getStationPodcastDownloadKey() && $stationPodcast->hasEpisodeForFile($fileId); } diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 49a8c09c0..79900d3df 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -1526,6 +1526,9 @@ class Application_Model_Preference self::setValue("station_podcast_id", $value); } + // SAAS-1081 - Implement a universal download key for downloading episodes from the station podcast + // Store and increment the download counter, resetting every month + public static function getStationPodcastDownloadKey() { return self::getValue("station_podcast_download_key"); } @@ -1534,4 +1537,31 @@ class Application_Model_Preference $value = empty($value) ? (new Application_Model_Auth())->generateRandomString() : $value; self::setValue("station_podcast_download_key", $value); } + + public static function getStationPodcastDownloadResetTimer() { + return self::getValue("station_podcast_download_reset_timer"); + } + + public static function setStationPodcastDownloadResetTimer($value) { + self::setValue("station_podcast_download_reset_timer", $value); + } + + public static function getStationPodcastDownloadCounter() { + return self::getValue("station_podcast_download_counter"); + } + + public static function resetStationPodcastDownloadCounter() { + self::setValue("station_podcast_download_counter", 0); + } + + public static function incrementStationPodcastDownloadCounter() { + $c = self::getStationPodcastDownloadCounter(); + self::setValue("station_podcast_download_counter", empty($c) ? 1 : ++$c); + } + + // For fail cases, we may need to decrement the download counter + public static function decrementStationPodcastDownloadCounter() { + $c = self::getStationPodcastDownloadCounter(); + self::setValue("station_podcast_download_counter", empty($c) ? 0 : --$c); + } } diff --git a/airtime_mvc/application/modules/rest/controllers/MediaController.php b/airtime_mvc/application/modules/rest/controllers/MediaController.php index 424aed435..f24d081b9 100644 --- a/airtime_mvc/application/modules/rest/controllers/MediaController.php +++ b/airtime_mvc/application/modules/rest/controllers/MediaController.php @@ -63,11 +63,17 @@ class Rest_MediaController extends Zend_Rest_Controller return; } - try - { + // In case the download fails + $counterIncremented = false; + try { $this->getResponse() ->setHttpResponseCode(200); $inline = false; + // SAAS-1081 + if ($key = $this->getRequest()->getParam("download_key", false)) { + Application_Model_Preference::incrementStationPodcastDownloadCounter(); + $counterIncremented = true; + } Application_Service_MediaService::streamFileDownload($id, $inline); } catch (FileNotFoundException $e) { @@ -75,6 +81,7 @@ class Rest_MediaController extends Zend_Rest_Controller Logging::error($e->getMessage()); } catch (Exception $e) { + if ($counterIncremented) Application_Model_Preference::decrementStationPodcastDownloadCounter(); $this->unknownErrorResponse(); Logging::error($e->getMessage()); } diff --git a/airtime_mvc/application/views/scripts/library/publish-dialog.phtml b/airtime_mvc/application/views/scripts/library/publish-dialog.phtml index 5b5ebe314..ad9d10131 100644 --- a/airtime_mvc/application/views/scripts/library/publish-dialog.phtml +++ b/airtime_mvc/application/views/scripts/library/publish-dialog.phtml @@ -19,7 +19,7 @@
- + diff --git a/airtime_mvc/public/js/airtime/library/publish.js b/airtime_mvc/public/js/airtime/library/publish.js index 7d553f519..85b760bca 100644 --- a/airtime_mvc/public/js/airtime/library/publish.js +++ b/airtime_mvc/public/js/airtime/library/publish.js @@ -26,8 +26,12 @@ var AIRTIME = (function (AIRTIME) { tab.setName($scope.media.track_title); }); + // TODO: implement GET request to endpoint that returns source information + // ie. SoundCloud connection + publish status + $scope.publish = function() { var sources = {}; + console.log($scope.publishSources); $.each($scope.publishSources, function(k, v) { if (v) sources[k] = 'publish'; // Tentative TODO: decide on a robust implementation });