CC-6046, CC-6045, CC-6047 - New SoundCloud implementation
This commit is contained in:
parent
51a3f19f43
commit
b0b6e037ac
62 changed files with 4009 additions and 2491 deletions
|
@ -55,23 +55,6 @@ class Application_Service_CalendarService
|
|||
"icon" => "overview",
|
||||
"url" => $baseUrl."library/edit-file-md/id/".$ccFile->getDbId());
|
||||
}
|
||||
|
||||
//recorded show can be uploaded to soundcloud
|
||||
if (Application_Model_Preference::GetUploadToSoundcloudOption()) {
|
||||
$scid = $ccFile->getDbSoundcloudId();
|
||||
|
||||
if ($scid > 0) {
|
||||
$menu["soundcloud_view"] = array(
|
||||
"name" => _("View on Soundcloud"),
|
||||
"icon" => "soundcloud",
|
||||
"url" => $ccFile->getDbSoundcloudLinkToFile());
|
||||
}
|
||||
|
||||
$text = is_null($scid) ? _('Upload to SoundCloud') : _('Re-upload to SoundCloud');
|
||||
$menu["soundcloud_upload"] = array(
|
||||
"name"=> $text,
|
||||
"icon" => "soundcloud");
|
||||
}
|
||||
} else {
|
||||
$menu["content"] = array(
|
||||
"name"=> _("Show Content"),
|
||||
|
|
164
airtime_mvc/application/services/SoundCloudService.php
Normal file
164
airtime_mvc/application/services/SoundCloudService.php
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
require_once "ThirdPartyService.php";
|
||||
|
||||
class SoundcloudService extends ThirdPartyService {
|
||||
|
||||
/**
|
||||
* @var Soundcloud\Service SoundCloud API wrapper object
|
||||
*/
|
||||
private $_client;
|
||||
|
||||
/**
|
||||
* @var string service name to store in ThirdPartyTrackReferences database
|
||||
*/
|
||||
protected $_SERVICE_NAME = 'SoundCloud';
|
||||
|
||||
/**
|
||||
* @var string base URI for SoundCloud tracks
|
||||
*/
|
||||
protected $_THIRD_PARTY_TRACK_URI = 'http://api.soundcloud.com/tracks/';
|
||||
|
||||
/**
|
||||
* @var array Application_Model_Preference functions for SoundCloud and their
|
||||
* associated API parameter keys so that we can call them dynamically
|
||||
*/
|
||||
private $_SOUNDCLOUD_PREF_FUNCTIONS = array(
|
||||
"getDefaultSoundCloudLicenseType" => "license",
|
||||
"getDefaultSoundCloudSharingType" => "sharing"
|
||||
);
|
||||
|
||||
/**
|
||||
* Initialize the service
|
||||
*/
|
||||
public function __construct() {
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
// FIXME: These values are hardcoded into conf.php right now...
|
||||
// we should move these to a global config file
|
||||
$clientId = $CC_CONFIG['soundcloud-client-id'];
|
||||
$clientSecret = $CC_CONFIG['soundcloud-client-secret'];
|
||||
$baseUrl = $CC_CONFIG['baseUrl'] . ":" . $CC_CONFIG['basePort'];
|
||||
$redirectUri = 'http://' . $baseUrl . '/soundcloud/redirect';
|
||||
|
||||
$this->_client = new Soundcloud\Service($clientId, $clientSecret, $redirectUri);
|
||||
$accessToken = Application_Model_Preference::getSoundCloudRequestToken();
|
||||
if (!empty($accessToken)) {
|
||||
$this->_client->setAccessToken($accessToken);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: upload functionality will be moved to python, this is just for testing
|
||||
/**
|
||||
* Upload the file with the given identifier to SoundCloud
|
||||
*
|
||||
* @param int $fileId the local CcFiles identifier
|
||||
*
|
||||
* @throws Soundcloud\Exception\InvalidHttpResponseCodeException
|
||||
* thrown when the upload fails for any reason
|
||||
*/
|
||||
public function upload($fileId) {
|
||||
$file = Application_Model_StoredFile::RecallById($fileId);
|
||||
try {
|
||||
$track = json_decode($this->_client->post('tracks', $this->_buildTrackArray($file)));
|
||||
parent::_createTrackReference($fileId, $track);
|
||||
} catch(Soundcloud\Exception\InvalidHttpResponseCodeException $e) {
|
||||
Logging::info("Invalid request: " . $e->getMessage());
|
||||
// We should only get here if we have an access token, so attempt to refresh
|
||||
$this->accessTokenRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a parameter array for the track being uploaded to SoundCloud
|
||||
*
|
||||
* @param $file Application_Model_StoredFile the file being uploaded
|
||||
*
|
||||
* @return array the track array to send to SoundCloud
|
||||
*/
|
||||
private function _buildTrackArray($file) {
|
||||
$trackArray = array(
|
||||
'track[title]' => $file->getName(),
|
||||
// TODO: verify that S3 uploads work
|
||||
'track[asset_data]' => '@'.$file->getFilePaths()[0]
|
||||
);
|
||||
|
||||
foreach($this->_SOUNDCLOUD_PREF_FUNCTIONS as $func => $param) {
|
||||
$val = Application_Model_Preference::$func();
|
||||
if (!empty($val)) {
|
||||
$trackArray["track[$param]"] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $trackArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a CcFiles identifier for a file that's been uploaded to SoundCloud,
|
||||
* return a link to the remote file
|
||||
*
|
||||
* @param int $fileId the local CcFiles identifier
|
||||
*
|
||||
* @return string the link to the remote file
|
||||
*/
|
||||
public function getLinkToFile($fileId) {
|
||||
$serviceId = $this->getServiceId($fileId);
|
||||
// If we don't find a record for the file we'll get 0 back for the id
|
||||
if ($serviceId == 0) { return ''; }
|
||||
$track = json_decode($this->_client->get('tracks/'. $serviceId));
|
||||
return $track->permalink_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an access token exists for the SoundCloud client
|
||||
*
|
||||
* @return bool true if an access token exists, otherwise false
|
||||
*/
|
||||
public function hasAccessToken() {
|
||||
$accessToken = $this->_client->getAccessToken();
|
||||
return !empty($accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SoundCloud authorization URL
|
||||
*
|
||||
* @return string the authorization URL
|
||||
*/
|
||||
public function getAuthorizeUrl() {
|
||||
// Pass the current URL in the state parameter in order to preserve it
|
||||
// in the redirect. This allows us to create a singular script to redirect
|
||||
// back to any station the request comes from.
|
||||
$url = urlencode('http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
|
||||
return $this->_client->getAuthorizeUrl(array("state" => $url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a new access token from SoundCloud and store it in CcPref
|
||||
*
|
||||
* @param $code string exchange authorization code for access token
|
||||
*/
|
||||
public function requestNewAccessToken($code) {
|
||||
// Get a non-expiring access token
|
||||
$response = $this->_client->accessToken($code, $postData = array('scope' => 'non-expiring'));
|
||||
$accessToken = $response['access_token'];
|
||||
Application_Model_Preference::setSoundCloudRequestToken($accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate the SoundCloud client's access token
|
||||
*
|
||||
* @throws Soundcloud\Exception\InvalidHttpResponseCodeException
|
||||
* thrown when attempting to regenerate a stale token
|
||||
*/
|
||||
public function accessTokenRefresh() {
|
||||
assert($this->hasAccessToken());
|
||||
try {
|
||||
$accessToken = $this->_client->getAccessToken();
|
||||
$this->_client->accessTokenRefresh($accessToken);
|
||||
} catch(Soundcloud\Exception\InvalidHttpResponseCodeException $e) {
|
||||
// If we get here, then that means our token is stale, so remove it
|
||||
// Because we're using non-expiring tokens, we shouldn't get here (!)
|
||||
Application_Model_Preference::setSoundCloudRequestToken("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
120
airtime_mvc/application/services/ThirdPartyService.php
Normal file
120
airtime_mvc/application/services/ThirdPartyService.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class ThirdPartyService generic superclass for third-party services
|
||||
*/
|
||||
abstract class ThirdPartyService {
|
||||
|
||||
/**
|
||||
* @var string service name to store in ThirdPartyTrackReferences database
|
||||
*/
|
||||
protected $_SERVICE_NAME = '';
|
||||
|
||||
/**
|
||||
* @var string base URI for third-party tracks
|
||||
*/
|
||||
protected $_THIRD_PARTY_TRACK_URI = '';
|
||||
|
||||
/**
|
||||
* Upload the file with the given identifier to a third-party service
|
||||
*
|
||||
* @param int $fileId the local CcFiles identifier
|
||||
*/
|
||||
abstract function upload($fileId);
|
||||
|
||||
/**
|
||||
* Create a ThirdPartyTrackReferences and save it to the database
|
||||
*
|
||||
* @param $fileId int local CcFiles identifier
|
||||
* @param $track object third-party service track object
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws PropelException
|
||||
*/
|
||||
protected function _createTrackReference($fileId, $track) {
|
||||
// First, check if the track already has an entry in the database
|
||||
$ref = ThirdPartyTrackReferencesQuery::create()
|
||||
->filterByDbService($this->_SERVICE_NAME)
|
||||
->findOneByDbFileId($fileId);
|
||||
if (is_null($ref)) {
|
||||
$ref = new ThirdPartyTrackReferences();
|
||||
}
|
||||
$ref->setDbService($this->_SERVICE_NAME);
|
||||
$ref->setDbForeignId($track->id);
|
||||
$ref->setDbFileId($fileId);
|
||||
$ref->setDbStatus($track->state);
|
||||
$ref->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a ThirdPartyTrackReferences from the database.
|
||||
* This is necessary if the track was removed from the service
|
||||
* or the foreign id in our database is incorrect
|
||||
*
|
||||
* @param $fileId int local CcFiles identifier
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws PropelException
|
||||
*/
|
||||
public function removeTrackReference($fileId) {
|
||||
$ref = ThirdPartyTrackReferencesQuery::create()
|
||||
->filterByDbService($this->_SERVICE_NAME)
|
||||
->findOneByDbFileId($fileId);
|
||||
$ref->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a CcFiles identifier for a file that's been uploaded to a third-party service,
|
||||
* return the third-party identifier for the remote file
|
||||
*
|
||||
* @param int $fileId the local CcFiles identifier
|
||||
*
|
||||
* @return int the service foreign identifier
|
||||
*/
|
||||
public function getServiceId($fileId) {
|
||||
$ref = ThirdPartyTrackReferencesQuery::create()
|
||||
->filterByDbService($this->_SERVICE_NAME)
|
||||
->findOneByDbFileId($fileId); // There shouldn't be duplicates!
|
||||
return is_null($ref) ? 0 : $ref->getDbForeignId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a CcFiles identifier for a file that's been uploaded to a third-party service,
|
||||
* return a link to the remote file
|
||||
*
|
||||
* @param int $fileId the local CcFiles identifier
|
||||
*
|
||||
* @return string the link to the remote file
|
||||
*/
|
||||
public function getLinkToFile($fileId) {
|
||||
$serviceId = $this->getServiceId($fileId);
|
||||
return $serviceId > 0 ? $this->_THIRD_PARTY_TRACK_URI . $serviceId : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an OAuth access token exists for the third-party client
|
||||
*
|
||||
* @return bool true if an access token exists, otherwise false
|
||||
*/
|
||||
abstract function hasAccessToken();
|
||||
|
||||
/**
|
||||
* Get the OAuth authorization URL
|
||||
*
|
||||
* @return string the authorization URL
|
||||
*/
|
||||
abstract function getAuthorizeUrl();
|
||||
|
||||
/**
|
||||
* Request a new OAuth access token from a third-party service and store it in CcPref
|
||||
*
|
||||
* @param $code string exchange authorization code for access token
|
||||
*/
|
||||
abstract function requestNewAccessToken($code);
|
||||
|
||||
/**
|
||||
* Regenerate the third-party client's OAuth access token
|
||||
*/
|
||||
abstract function accessTokenRefresh();
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue