Rename airtime_mvc/ to legacy/
This commit is contained in:
parent
f0879322c2
commit
3e18d42c8b
1316 changed files with 0 additions and 0 deletions
280
legacy/application/modules/rest/controllers/MediaController.php
Normal file
280
legacy/application/modules/rest/controllers/MediaController.php
Normal file
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
|
||||
class Rest_MediaController extends Zend_Rest_Controller
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
|
||||
// Remove reliance on .phtml files to render requests
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* headAction is needed as it is defined as an abstract function in the base controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function headAction()
|
||||
{
|
||||
Logging::info("HEAD action received");
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$totalFileCount = CcFilesQuery::create()->count();
|
||||
|
||||
// Check if offset and limit were sent with request.
|
||||
// Default limit to zero and offset to $totalFileCount
|
||||
$offset = $this->_getParam('offset', 0);
|
||||
$limit = $this->_getParam('limit', $totalFileCount);
|
||||
|
||||
//Sorting parameters
|
||||
$sortColumn = $this->_getParam('sort', CcFilesPeer::ID);
|
||||
$sortDir = $this->_getParam('sort_dir', Criteria::ASC);
|
||||
|
||||
$query = CcFilesQuery::create()
|
||||
->filterByDbHidden(false)
|
||||
->filterByDbFileExists(true)
|
||||
->filterByDbImportStatus(0)
|
||||
->setLimit($limit)
|
||||
->setOffset($offset)
|
||||
->orderBy($sortColumn, $sortDir);
|
||||
//->orderByDbId();
|
||||
|
||||
|
||||
$queryCount = $query->count();
|
||||
$queryResult = $query->find();
|
||||
|
||||
$files_array = array();
|
||||
foreach ($queryResult as $file)
|
||||
{
|
||||
array_push($files_array, CcFiles::sanitizeResponse($file));
|
||||
}
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->setHeader('X-TOTAL-COUNT', $totalFileCount)
|
||||
->appendBody(json_encode($files_array));
|
||||
|
||||
/** TODO: Use this simpler code instead after we upgrade to Propel 1.7 (Airtime 2.6.x branch):
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode(CcFilesQuery::create()->find()->toArray(BasePeer::TYPE_FIELDNAME)));
|
||||
*/
|
||||
}
|
||||
|
||||
public function downloadAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// In case the download fails
|
||||
$counterIncremented = false;
|
||||
try {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200);
|
||||
$inline = false;
|
||||
// SAAS-1081 - download counter for station podcast downloads
|
||||
if ($key = $this->getRequest()->getParam("download_key", false)) {
|
||||
Application_Model_Preference::incrementStationPodcastDownloadCounter();
|
||||
$counterIncremented = true;
|
||||
}
|
||||
Application_Service_MediaService::streamFileDownload($id, $inline);
|
||||
}
|
||||
catch (LibreTimeFileNotFoundException $e) {
|
||||
$this->fileNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (Exception $e) {
|
||||
if ($counterIncremented) Application_Model_Preference::decrementStationPodcastDownloadCounter();
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode(CcFiles::getSanitizedFileById($id)));
|
||||
}
|
||||
catch (LibreTimeFileNotFoundException $e) {
|
||||
$this->fileNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function postAction()
|
||||
{
|
||||
//If we do get an ID on a POST, then that doesn't make any sense
|
||||
//since POST is only for creating.
|
||||
if ($id = $this->_getParam('id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: ID should not be specified when using POST. POST is only used for file creation, and an ID will be chosen by Airtime");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// REST uploads are not from Zend_Form, hence we handle them using Zend_File_transfer directly
|
||||
// we need to specify an explicit adapter since autodetection broke in php 7.2
|
||||
$upload = new Zend_File_Transfer('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')) {
|
||||
throw new Exception("invalid file uploaded");
|
||||
}
|
||||
$fileInfo = $upload->getFileInfo('file');
|
||||
// this should have more info on any actual faults detected by php
|
||||
if ($fileInfo['file']['error']) {
|
||||
throw new Exception(sprintf('File upload error: %s', $fileInfo['file']['error']));
|
||||
}
|
||||
$sanitizedFile = CcFiles::createFromUpload($fileInfo);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->appendBody(json_encode($sanitizedFile));
|
||||
}
|
||||
catch (InvalidMetadataException $e) {
|
||||
$this->invalidDataResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (OverDiskQuotaException $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody("ERROR: Disk Quota reached.");
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->serviceUnavailableResponse();
|
||||
Logging::error($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public function putAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$requestData = json_decode($this->getRequest()->getRawBody(), true);
|
||||
$sanitizedFile = CcFiles::updateFromArray($id, $requestData);
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->appendBody(json_encode($sanitizedFile));
|
||||
}
|
||||
catch (InvalidMetadataException $e) {
|
||||
$this->invalidDataResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (LibreTimeFileNotFoundException $e) {
|
||||
$this->fileNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
CcFiles::deleteById($id);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(204);
|
||||
}
|
||||
catch (LibreTimeFileNotFoundException $e) {
|
||||
$this->fileNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish endpoint for individual media items
|
||||
*/
|
||||
public function publishAction() {
|
||||
$id = $this->getId();
|
||||
try {
|
||||
// Is there a better way to do this?
|
||||
$data = json_decode($this->getRequest()->getRawBody(), true)["sources"];
|
||||
Application_Service_PublishService::publish($id, $data);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200);
|
||||
} catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function publishSourcesAction() {
|
||||
$id = $this->_getParam('id', false);
|
||||
$sources = Application_Service_PublishService::getSourceLists($id);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode($sources));
|
||||
|
||||
}
|
||||
|
||||
private function getId()
|
||||
{
|
||||
if (!$id = $this->_getParam('id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: No file ID specified.");
|
||||
return false;
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function fileNotFoundResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(404);
|
||||
$resp->appendBody("ERROR: Media not found.");
|
||||
}
|
||||
|
||||
private function importFailedResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(200);
|
||||
$resp->appendBody("ERROR: Import Failed.");
|
||||
}
|
||||
|
||||
private function unknownErrorResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("An unknown error occurred.");
|
||||
}
|
||||
|
||||
private function serviceUnavailableResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("An error occurred while processing your upload. Please try again in a few minutes.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
<?php
|
||||
|
||||
class Rest_PodcastController extends Zend_Rest_Controller
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
|
||||
// Remove reliance on .phtml files to render requests
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
$this->view->setScriptPath(APPLICATION_PATH . 'views/scripts/');
|
||||
}
|
||||
|
||||
/**
|
||||
* headAction is needed as it is defined as an abstract function in the base controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function headAction()
|
||||
{
|
||||
Logging::info("HEAD action received");
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
// Check if offset and limit were sent with request.
|
||||
// Default limit to zero and offset to $totalFileCount
|
||||
$offset = $this->_getParam('offset', 0);
|
||||
$limit = $this->_getParam('limit', 0);
|
||||
|
||||
//Sorting parameters
|
||||
$sortColumn = $this->_getParam('sort', PodcastPeer::ID);
|
||||
$sortDir = $this->_getParam('sort_dir', Criteria::ASC);
|
||||
|
||||
$stationPodcastId = Application_Model_Preference::getStationPodcastId();
|
||||
$result = PodcastQuery::create()
|
||||
// Don't return the Station podcast - we fetch it separately
|
||||
->filterByDbId($stationPodcastId, Criteria::NOT_EQUAL)
|
||||
->leftJoinImportedPodcast()
|
||||
->withColumn('auto_ingest_timestamp');
|
||||
$total = $result->count();
|
||||
if ($limit > 0) { $result->setLimit($limit); }
|
||||
$result->setOffset($offset)
|
||||
->orderBy($sortColumn, $sortDir);
|
||||
$result = $result->find();
|
||||
|
||||
$podcastArray = $result->toArray(null, false, BasePeer::TYPE_FIELDNAME);
|
||||
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->setHeader('X-TOTAL-COUNT', $total)
|
||||
->appendBody(json_encode($podcastArray));
|
||||
}
|
||||
|
||||
public function getAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode(Application_Service_PodcastService::getPodcastById($id)));
|
||||
} catch (PodcastNotFoundException $e) {
|
||||
$this->podcastNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function postAction()
|
||||
{
|
||||
//If we do get an ID on a POST, then that doesn't make any sense
|
||||
//since POST is only for creating.
|
||||
if ($id = $this->_getParam('id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: ID should not be specified when using POST. POST is only used for podcast creation, and an ID will be chosen by Airtime");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$requestData = $this->getRequest()->getPost();
|
||||
$podcast = Application_Service_PodcastService::createFromFeedUrl($requestData["url"]);
|
||||
|
||||
$path = 'podcast/podcast.phtml';
|
||||
|
||||
$this->view->podcast = $podcast;
|
||||
$this->_helper->json->sendJson(array(
|
||||
"podcast"=>json_encode($podcast),
|
||||
"html"=>$this->view->render($path),
|
||||
));
|
||||
}
|
||||
catch (InvalidPodcastException $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody("Invalid podcast!");
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::error($e->getMessage());
|
||||
$this->unknownErrorResponse();
|
||||
}
|
||||
}
|
||||
|
||||
public function putAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$requestData = json_decode($this->getRequest()->getRawBody(), true);
|
||||
$podcast = Application_Service_PodcastService::updatePodcastFromArray($id, $requestData);
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->appendBody(json_encode($podcast));
|
||||
}
|
||||
catch (PodcastNotFoundException $e) {
|
||||
$this->podcastNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Application_Service_PodcastService::deletePodcastById($id);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(204);
|
||||
}
|
||||
catch (PodcastNotFoundException $e) {
|
||||
$this->podcastNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint for performing bulk actions (deleting multiple podcasts, opening multiple editors)
|
||||
*/
|
||||
public function bulkAction() {
|
||||
if ($this->_request->getMethod() != HttpRequestType::POST) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(405)
|
||||
->appendBody("ERROR: Method not accepted");
|
||||
return;
|
||||
}
|
||||
|
||||
$ids = $this->_getParam('ids', []);
|
||||
$method = $this->_getParam('method', HttpRequestType::GET);
|
||||
$responseBody = [];
|
||||
|
||||
// XXX: Should this be a map of HttpRequestType => function call instead? Would be a bit cleaner
|
||||
switch($method) {
|
||||
case HttpRequestType::DELETE:
|
||||
foreach($ids as $id) {
|
||||
Application_Service_PodcastService::deletePodcastById($id);
|
||||
}
|
||||
break;
|
||||
case HttpRequestType::GET:
|
||||
$path = 'podcast/podcast.phtml';
|
||||
foreach($ids as $id) {
|
||||
$responseBody[] = array(
|
||||
"podcast" => json_encode(Application_Service_PodcastService::getPodcastById($id)),
|
||||
"html" => $this->view->render($path)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$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
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function stationAction() {
|
||||
$stationPodcastId = Application_Model_Preference::getStationPodcastId();
|
||||
$podcast = Application_Service_PodcastService::getPodcastById($stationPodcastId);
|
||||
$path = 'podcast/station.phtml';
|
||||
$this->view->podcast = $podcast;
|
||||
$this->_helper->json->sendJson(array(
|
||||
"podcast" => json_encode($podcast),
|
||||
"html" => $this->view->render($path)
|
||||
));
|
||||
}
|
||||
|
||||
private function getId()
|
||||
{
|
||||
if (!$id = $this->_getParam('id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: No podcast ID specified.");
|
||||
return false;
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function unknownErrorResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(500);
|
||||
$resp->appendBody("An unknown error occurred.");
|
||||
}
|
||||
|
||||
private function podcastNotFoundResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(404);
|
||||
$resp->appendBody("ERROR: Podcast not found.");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
class Rest_PodcastEpisodesController extends Zend_Rest_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Application_Service_PodcastEpisodeService
|
||||
*/
|
||||
protected $_service;
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
|
||||
// Remove reliance on .phtml files to render requests
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
$this->_service = new Application_Service_PodcastEpisodeService();
|
||||
}
|
||||
|
||||
/**
|
||||
* headAction is needed as it is defined as an abstract function in the base controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function headAction()
|
||||
{
|
||||
Logging::info("HEAD action received");
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
// podcast ID
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$totalPodcastEpisodesCount = PodcastEpisodesQuery::create()
|
||||
->filterByDbPodcastId($id)
|
||||
->count();
|
||||
|
||||
// Check if offset and limit were sent with request.
|
||||
// Default limit to zero and offset to $totalFileCount
|
||||
$offset = $this->_getParam('offset', 0);
|
||||
$limit = $this->_getParam('limit', $totalPodcastEpisodesCount);
|
||||
|
||||
//Sorting parameters
|
||||
$sortColumn = $this->_getParam('sort', PodcastEpisodesPeer::ID);
|
||||
$sortDir = $this->_getParam('sort_dir', Criteria::ASC);
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->setHeader('X-TOTAL-COUNT', $totalPodcastEpisodesCount)
|
||||
->appendBody(json_encode($this->_service->getPodcastEpisodes($id, $offset, $limit, $sortColumn, $sortDir)));
|
||||
|
||||
} catch (PodcastNotFoundException $e) {
|
||||
$this->podcastNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getAction()
|
||||
{
|
||||
// podcast ID
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$episodeId = $this->getEpisodeId();
|
||||
if (!$episodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->appendBody(json_encode($this->_service->getPodcastEpisodeById($episodeId)));
|
||||
|
||||
} catch (PodcastNotFoundException $e) {
|
||||
$this->podcastNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
} catch (PodcastEpisodeNotFoundException $e) {
|
||||
$this->podcastEpisodeNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function postAction()
|
||||
{
|
||||
//If we do get an episode ID on a POST, then that doesn't make any sense
|
||||
//since POST is only for creating.
|
||||
if ($episodeId = $this->_getParam('episode_id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: Episode ID should not be specified when using POST. POST is only used for "
|
||||
. "importing podcast episodes, and an episode ID will be chosen by Airtime");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure a podcast ID was specified
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$requestData = json_decode($this->getRequest()->getRawBody(), true);
|
||||
$episode = $this->_service->importEpisode($id, $requestData["episode"]);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->appendBody(json_encode($episode));
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
$id = $this->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$episodeId = $this->getEpisodeId();
|
||||
if (!$episodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->_service->deletePodcastEpisodeById($episodeId);
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(204);
|
||||
} catch (PodcastEpisodeNotFoundException $e) {
|
||||
$this->podcastEpisodeNotFoundResponse();
|
||||
Logging::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$this->unknownErrorResponse();
|
||||
Logging::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function putAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private function getId()
|
||||
{
|
||||
if (!$id = $this->_getParam('id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: No podcast ID specified.");
|
||||
return false;
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function getEpisodeId()
|
||||
{
|
||||
if (!$episodeId = $this->_getParam('episode_id', false)) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: No podcast episode ID specified.");
|
||||
return false;
|
||||
}
|
||||
return $episodeId;
|
||||
}
|
||||
|
||||
private function unknownErrorResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("An unknown error occurred.");
|
||||
}
|
||||
|
||||
private function podcastNotFoundResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(404);
|
||||
$resp->appendBody("ERROR: Podcast not found.");
|
||||
}
|
||||
|
||||
private function podcastEpisodeNotFoundResponse()
|
||||
{
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(404);
|
||||
$resp->appendBody("ERROR: Podcast episode not found.");
|
||||
}
|
||||
|
||||
}
|
108
legacy/application/modules/rest/controllers/RouteController.php
Normal file
108
legacy/application/modules/rest/controllers/RouteController.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* Class Rest_RouteController
|
||||
*
|
||||
* Taken from https://github.com/aporat/Application_Rest_Controller_Route
|
||||
* to enable hierarchy routing
|
||||
*/
|
||||
|
||||
class Rest_RouteController extends Zend_Controller_Router_Route
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Zend_Controller_Front
|
||||
*/
|
||||
protected $_front;
|
||||
|
||||
protected $_actionKey = 'action';
|
||||
|
||||
/**
|
||||
* Prepares the route for mapping by splitting (exploding) it
|
||||
* to a corresponding atomic parts. These parts are assigned
|
||||
* a position which is later used for matching and preparing values.
|
||||
*
|
||||
* @param Zend_Controller_Front $front Front Controller object
|
||||
* @param string $route Map used to match with later submitted URL path
|
||||
* @param array $defaults Defaults for map variables with keys as variable names
|
||||
* @param array $reqs Regular expression requirements for variables (keys as variable names)
|
||||
* @param Zend_Translate $translator Translator to use for this instance
|
||||
*/
|
||||
public function __construct(Zend_Controller_Front $front, $route, $defaults = array(), $reqs = array(), Zend_Translate $translator = null, $locale = null)
|
||||
{
|
||||
$this->_front = $front;
|
||||
$this->_dispatcher = $front->getDispatcher();
|
||||
|
||||
parent::__construct($route, $defaults, $reqs, $translator, $locale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Matches a user submitted path with parts defined by a map. Assigns and
|
||||
* returns an array of variables on a successful match.
|
||||
*
|
||||
* @param string $path Path used to match against this routing map
|
||||
* @return array|false An array of assigned values or a false on a mismatch
|
||||
*/
|
||||
public function match($path, $partial = false)
|
||||
{
|
||||
|
||||
|
||||
$return = parent::match($path, $partial);
|
||||
|
||||
// add the RESTful action mapping
|
||||
if ($return) {
|
||||
$request = $this->_front->getRequest();
|
||||
$path = $request->getPathInfo();
|
||||
$params = $request->getParams();
|
||||
|
||||
$path = trim($path, self::URI_DELIMITER);
|
||||
|
||||
if ($path != '') {
|
||||
$path = explode(self::URI_DELIMITER, $path);
|
||||
}
|
||||
|
||||
//Store path count for method mapping
|
||||
$pathElementCount = count($path);
|
||||
|
||||
// Determine Action
|
||||
$requestMethod = strtolower($request->getMethod());
|
||||
if ($requestMethod != 'get') {
|
||||
if ($request->getParam('_method')) {
|
||||
$return[$this->_actionKey] = strtolower($request->getParam('_method'));
|
||||
} elseif ( $request->getHeader('X-HTTP-Method-Override') ) {
|
||||
$return[$this->_actionKey] = strtolower($request->getHeader('X-HTTP-Method-Override'));
|
||||
} else {
|
||||
$return[$this->_actionKey] = $requestMethod;
|
||||
}
|
||||
|
||||
// Map PUT and POST to actual create/update actions
|
||||
// based on parameter count (posting to resource or collection)
|
||||
switch( $return[$this->_actionKey] ){
|
||||
case 'post':
|
||||
$return[$this->_actionKey] = 'post';
|
||||
break;
|
||||
case 'put':
|
||||
$return[$this->_actionKey] = 'put';
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
// if the last argument in the path is a numeric value, consider this request a GET of an item
|
||||
$lastParam = array_pop($path);
|
||||
if (is_numeric($lastParam)) {
|
||||
$return[$this->_actionKey] = 'get';
|
||||
} else {
|
||||
$return[$this->_actionKey] = 'index';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Controller class for handling ShowImage-related functionality.
|
||||
* Changelog:
|
||||
* 16/09/2014 : v1.0 Created class skeleton, added image upload functionality
|
||||
* 18/09/2014 : v1.1 Changed auth references to static calls
|
||||
* 06/02/2015 : v1.2 Changed endpoints to be more RESTful, changed classname to
|
||||
* better reflect functionality
|
||||
* 09/02/2015 : v1.2.1 Added more comments
|
||||
* @author sourcefabric
|
||||
* @version 1.2.1
|
||||
*/
|
||||
|
||||
class Rest_ShowImageController extends Zend_Rest_Controller {
|
||||
|
||||
public function init() {
|
||||
// Remove layout dependencies
|
||||
$this->view->layout()->disableLayout();
|
||||
// Remove reliance on .phtml files to render requests
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* headAction is needed as it is defined as an abstract function in the base controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function headAction()
|
||||
{
|
||||
Logging::info("HEAD action received");
|
||||
}
|
||||
|
||||
public function indexAction() {
|
||||
Logging::info("INDEX action received");
|
||||
}
|
||||
|
||||
public function getAction() {
|
||||
Logging::info("GET action received");
|
||||
}
|
||||
|
||||
public function putAction() {
|
||||
Logging::info("PUT action received");
|
||||
}
|
||||
|
||||
/**
|
||||
* RESTful POST endpoint; used when uploading show images
|
||||
*/
|
||||
public function postAction() {
|
||||
|
||||
$showId = $this->getShowId();
|
||||
|
||||
if (!$showId) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody("No show ID provided");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$path = $this->processUploadedImage($showId, $_FILES["file"]["tmp_name"]);
|
||||
} catch (Exception $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(500)
|
||||
->appendBody("Error processing image: " . $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
$show = CcShowQuery::create()->findPk($showId);
|
||||
|
||||
$con = Propel::getConnection();
|
||||
try {
|
||||
$con->beginTransaction();
|
||||
|
||||
$show->setDbImagePath($path);
|
||||
$show->save();
|
||||
|
||||
$con->commit();
|
||||
} catch (Exception $e) {
|
||||
$con->rollBack();
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(500)
|
||||
->appendBody("Couldn't add show image: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201);
|
||||
}
|
||||
|
||||
/**
|
||||
* RESTful DELETE endpoint; used when deleting show images
|
||||
*/
|
||||
public function deleteAction() {
|
||||
|
||||
$showId = $this->getShowId();
|
||||
|
||||
if (!$showId) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody("No show ID provided");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self::deleteShowImagesFromStor($showId);
|
||||
} catch (Exception $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(500)
|
||||
->appendBody("Error processing image: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$show = CcShowQuery::create()->findPk($showId);
|
||||
|
||||
$con = Propel::getConnection();
|
||||
try {
|
||||
$con->beginTransaction();
|
||||
|
||||
$show->setDbImagePath(null);
|
||||
$show->save();
|
||||
|
||||
$con->commit();
|
||||
} catch (Exception $e) {
|
||||
$con->rollBack();
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(500)
|
||||
->appendBody("Couldn't remove show image: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify and process an uploaded image file, copying it into
|
||||
* .../stor/imported/:owner-id/show-images/:show-id/ to differentiate between
|
||||
* individual users and shows
|
||||
*
|
||||
* @param int $showId the ID of the show we're adding the image to
|
||||
* @param string $tempFilePath temporary filepath assigned to the upload generally of the form /tmp/:tmp_name
|
||||
*
|
||||
* @throws Exception
|
||||
* - when a file with an unsupported file extension is uploaded or an
|
||||
* error occurs in copyFileToStor
|
||||
* @return string the path to the new location for the file
|
||||
*/
|
||||
private function processUploadedImage($showId, $tempFilePath) {
|
||||
$ownerId = RestAuth::getOwnerId();
|
||||
|
||||
//Only accept files with a file extension that we support.
|
||||
$fileExtension = $this->getFileExtension($tempFilePath);
|
||||
|
||||
if (!in_array(strtolower($fileExtension), explode(",", "jpg,png,gif,jpeg"))) {
|
||||
@unlink($tempFilePath);
|
||||
throw new Exception("Bad file extension.");
|
||||
}
|
||||
|
||||
$storDir = Application_Model_MusicDir::getStorDir();
|
||||
$importedStorageDirectory = $storDir->getDirectory() . "imported/" . $ownerId . "/show-images/" . $showId;
|
||||
|
||||
try {
|
||||
$importedStorageDirectory = $this->copyFileToStor($tempFilePath, $importedStorageDirectory, $fileExtension);
|
||||
} catch (Exception $e) {
|
||||
@unlink($tempFilePath);
|
||||
throw new Exception("Failed to copy file: " . $e->getMessage());
|
||||
}
|
||||
|
||||
return $importedStorageDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the MIME type of an uploaded file to determine what extension it should have
|
||||
*
|
||||
* @param $tempFilePath the file path to the uploaded file in /tmp
|
||||
*
|
||||
* @return string the file extension for the new file based on its MIME type
|
||||
*/
|
||||
private function getFileExtension($tempFilePath) {
|
||||
// Don't trust the extension - get the MIME-type instead
|
||||
$fileInfo = finfo_open();
|
||||
$mime = finfo_file($fileInfo, $tempFilePath, FILEINFO_MIME_TYPE);
|
||||
return $this->getExtensionFromMime($mime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a hardcoded list of accepted MIME types to return a file extension
|
||||
*
|
||||
* @param $mime the MIME type of the file
|
||||
*
|
||||
* @return string the file extension based on the given MIME type
|
||||
*/
|
||||
private function getExtensionFromMime($mime) {
|
||||
$extensions = array(
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif'
|
||||
);
|
||||
|
||||
return $extensions[$mime];
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a given file in /tmp to the user's stor directory
|
||||
*
|
||||
* @param string $tempFilePath the path to the file in /tmp
|
||||
* @param string $importedStorageDirectory the path to the new location for the file
|
||||
* @param string $fileExtension the file's extension based on its MIME type
|
||||
*
|
||||
* @return string the new full path to the file in stor
|
||||
* @throws Exception if either the storage directory does not exist and cannot be
|
||||
* created, the storage directory does not have write permissions
|
||||
* enabled, or the user's hard drive does not have enough space to
|
||||
* store the file
|
||||
*/
|
||||
private function copyFileToStor($tempFilePath, $importedStorageDirectory, $fileExtension) {
|
||||
$image_file = $tempFilePath;
|
||||
|
||||
// check if show image dir exists and if not, create one
|
||||
if (!file_exists($importedStorageDirectory)) {
|
||||
if (!mkdir($importedStorageDirectory, 0777, true)) {
|
||||
throw new Exception("Failed to create storage directory.");
|
||||
}
|
||||
}
|
||||
|
||||
if (chmod($image_file, 0644) === false) {
|
||||
Logging::info("Warning: couldn't change permissions of $image_file to 0644");
|
||||
}
|
||||
|
||||
$newFileName = substr($tempFilePath, strrpos($tempFilePath, "/")) . "." . $fileExtension;
|
||||
|
||||
// Did all the checks for real, now trying to copy
|
||||
$image_stor = Application_Common_OsPath::join($importedStorageDirectory, $newFileName);
|
||||
Logging::info("Adding image: " . $image_stor);
|
||||
Logging::info("copyFileToStor: moving file $image_file to $image_stor");
|
||||
|
||||
if (@rename($image_file, $image_stor) === false) {
|
||||
//something went wrong likely there wasn't enough space in .
|
||||
//the audio_stor to move the file too warn the user that .
|
||||
//the file wasn't uploaded and they should check if there .
|
||||
//is enough disk space .
|
||||
unlink($image_file); //remove the file after failed rename
|
||||
|
||||
throw new Exception("The file was not uploaded, this error can occur if the computer "
|
||||
. "hard drive does not have enough disk space or the stor "
|
||||
. "directory does not have correct write permissions.");
|
||||
}
|
||||
|
||||
return $image_stor;
|
||||
}
|
||||
|
||||
// Should this be an endpoint instead?
|
||||
/**
|
||||
* Delete any images belonging to the show with the given ID
|
||||
*
|
||||
* @param int $showId the ID of the show we're deleting images from
|
||||
*
|
||||
* @return bool true if the images were successfully deleted, otherwise false
|
||||
*/
|
||||
public static function deleteShowImagesFromStor($showId) {
|
||||
$ownerId = RestAuth::getOwnerId();
|
||||
|
||||
$storDir = Application_Model_MusicDir::getStorDir();
|
||||
$importedStorageDirectory = $storDir->getDirectory() . "imported/" . $ownerId . "/show-images/" . $showId;
|
||||
|
||||
Logging::info("Deleting images from " . $importedStorageDirectory);
|
||||
|
||||
// to be safe in case image uploading functionality is extended later
|
||||
if (!file_exists($importedStorageDirectory)) {
|
||||
Logging::info("No uploaded images for show with id " . $showId);
|
||||
return true;
|
||||
} else {
|
||||
return self::delTree($importedStorageDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
// from a note @ http://php.net/manual/en/function.rmdir.php
|
||||
private static function delTree($dir) {
|
||||
$files = array_diff(scandir($dir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file")) ? self::delTree("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the id parameter from the request.
|
||||
* @return boolean|int false if the show id wasn't
|
||||
* provided, otherwise returns the id
|
||||
*/
|
||||
private function getShowId() {
|
||||
if (!($id = $this->_getParam('id', false))) {
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(400);
|
||||
$resp->appendBody("ERROR: No show ID specified.");
|
||||
return false;
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue