SAAS-1081 - implement station podcast download counter that resets monthly

This commit is contained in:
Duncan Sommerville 2015-10-21 12:54:50 -04:00
parent 6c0055895c
commit 92ffa955c3
7 changed files with 94 additions and 23 deletions

View File

@ -25,6 +25,7 @@ final class TaskManager {
const TASK_INTERVAL_SECONDS = 30; const TASK_INTERVAL_SECONDS = 30;
/** /**
*
* @var $con PDO Propel connection object * @var $con PDO Propel connection object
*/ */
private $_con; 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 * 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 * Task types - values don't really matter as long as they're unique
*/ */
const UPGRADE = "upgrade"; const UPGRADE = "upgrade";
const CELERY = "celery"; const CELERY = "celery";
const PODCAST = "podcast"; const PODCAST = "podcast";
const STATION_PODCAST = "station-podcast";
/** /**
* @var array map of arbitrary identifiers to class names to be instantiated reflectively * @var array map of arbitrary identifiers to class names to be instantiated reflectively
*/ */
public static $tasks = array( public static $tasks = array(
"upgrade" => "UpgradeTask", "upgrade" => "UpgradeTask",
"celery" => "CeleryTask", "celery" => "CeleryTask",
"podcast" => "PodcastTask", "podcast" => "PodcastTask",
"station-podcast" => "StationPodcastTask",
); );
/** /**

View File

@ -137,18 +137,20 @@ class LibraryController extends Zend_Controller_Action
if ($isAdminOrPM || $ownerId == $user->getId()) { if ($isAdminOrPM || $ownerId == $user->getId()) {
$soundcloudService = new Application_Service_SoundcloudService(); $soundcloudService = new Application_Service_SoundcloudService();
if ($type === "audioclip" && $soundcloudService->hasAccessToken()) { 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); $serviceId = $soundcloudService->getServiceId($id);
if (!is_null($file) && $serviceId != 0) { 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"]["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}"); // $menu["soundcloud"]["items"]["remove"] = array("name" => _("Remove track"), "icon" => "soundcloud", "url" => $baseUrl . "soundcloud/delete/id/{$id}");
} else { }
/*
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 // 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 // but we haven't yet gotten a response from Celery, so disable the menu item
if ($soundcloudService->referenceExists($id)) { if ($soundcloudService->referenceExists($id)) {
@ -163,6 +165,7 @@ class LibraryController extends Zend_Controller_Action
); );
} }
} }
*/
} }
} }
} elseif ($type === "playlist" || $type === "block") { } elseif ($type === "playlist" || $type === "block") {

View File

@ -217,13 +217,13 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
$request->getActionName())) { $request->getActionName())) {
/** Redirect to access denied page */ /** Redirect to access denied page */
$this->setErrorPage('error403'); $this->setErrorPage('error403');
$this->denyAccess(); /* This results in a 404! */ $this->denyAccess();
} }
} }
} }
private function verifyAuth() { private function verifyAuth() {
if ($this->isVerifiedDownload() || $this->verifyAPIKey()) { if ($this->verifyAPIKey() || $this->isVerifiedDownload()) {
return true; return true;
} }
@ -252,9 +252,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
$action = $request->getActionName(); $action = $request->getActionName();
$stationPodcast = StationPodcastQuery::create() $stationPodcast = StationPodcastQuery::create()
->findOneByDbPodcastId(Application_Model_Preference::getStationPodcastId()); ->findOneByDbPodcastId(Application_Model_Preference::getStationPodcastId());
return $module == "rest" return $module == "rest" && $controller == "media" && $action == "download"
&& $controller == "media"
&& $action == "download"
&& $key === Application_Model_Preference::getStationPodcastDownloadKey() && $key === Application_Model_Preference::getStationPodcastDownloadKey()
&& $stationPodcast->hasEpisodeForFile($fileId); && $stationPodcast->hasEpisodeForFile($fileId);
} }

View File

@ -1526,6 +1526,9 @@ class Application_Model_Preference
self::setValue("station_podcast_id", $value); 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() { public static function getStationPodcastDownloadKey() {
return self::getValue("station_podcast_download_key"); return self::getValue("station_podcast_download_key");
} }
@ -1534,4 +1537,31 @@ class Application_Model_Preference
$value = empty($value) ? (new Application_Model_Auth())->generateRandomString() : $value; $value = empty($value) ? (new Application_Model_Auth())->generateRandomString() : $value;
self::setValue("station_podcast_download_key", $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);
}
} }

View File

@ -63,11 +63,17 @@ class Rest_MediaController extends Zend_Rest_Controller
return; return;
} }
try // In case the download fails
{ $counterIncremented = false;
try {
$this->getResponse() $this->getResponse()
->setHttpResponseCode(200); ->setHttpResponseCode(200);
$inline = false; $inline = false;
// SAAS-1081
if ($key = $this->getRequest()->getParam("download_key", false)) {
Application_Model_Preference::incrementStationPodcastDownloadCounter();
$counterIncremented = true;
}
Application_Service_MediaService::streamFileDownload($id, $inline); Application_Service_MediaService::streamFileDownload($id, $inline);
} }
catch (FileNotFoundException $e) { catch (FileNotFoundException $e) {
@ -75,6 +81,7 @@ class Rest_MediaController extends Zend_Rest_Controller
Logging::error($e->getMessage()); Logging::error($e->getMessage());
} }
catch (Exception $e) { catch (Exception $e) {
if ($counterIncremented) Application_Model_Preference::decrementStationPodcastDownloadCounter();
$this->unknownErrorResponse(); $this->unknownErrorResponse();
Logging::error($e->getMessage()); Logging::error($e->getMessage());
} }

View File

@ -19,7 +19,7 @@
<input ng-model="publishSources.station_podcast" type="checkbox" name="publish_sources" id="station_podcast" value="station_podcast"> <input ng-model="publishSources.station_podcast" type="checkbox" name="publish_sources" id="station_podcast" value="station_podcast">
<label for="station_podcast"><?php echo(_("My Station Podcast"));?></label><br/> <label for="station_podcast"><?php echo(_("My Station Podcast"));?></label><br/>
<input ng-model="publishSources.soundcloud" type="checkbox" name="publish_sources" id="soundcloud" value="soundcloud"> <input ng-model="publishSources.soundcloud" type="checkbox" name="publish_sources" id="soundcloud" value="soundcloud">
<label for="soundcloud">SoundCloud</label> <label for="soundcloud"><?php echo(_(SOUNDCLOUD));?></label>
</fieldset> </fieldset>
</form> </form>

View File

@ -26,8 +26,12 @@ var AIRTIME = (function (AIRTIME) {
tab.setName($scope.media.track_title); tab.setName($scope.media.track_title);
}); });
// TODO: implement GET request to endpoint that returns source information
// ie. SoundCloud connection + publish status
$scope.publish = function() { $scope.publish = function() {
var sources = {}; var sources = {};
console.log($scope.publishSources);
$.each($scope.publishSources, function(k, v) { $.each($scope.publishSources, function(k, v) {
if (v) sources[k] = 'publish'; // Tentative TODO: decide on a robust implementation if (v) sources[k] = 'publish'; // Tentative TODO: decide on a robust implementation
}); });