diff --git a/airtime_mvc/application/models/airtime/Podcast.php b/airtime_mvc/application/models/airtime/Podcast.php index 6a52cb18b..d2323ce51 100644 --- a/airtime_mvc/application/models/airtime/Podcast.php +++ b/airtime_mvc/application/models/airtime/Podcast.php @@ -8,6 +8,10 @@ class InvalidPodcastException extends Exception { } +class PodcastNotFoundException extends \Aws\CloudFront\Exception\Exception +{ +} + /** * Skeleton subclass for representing a row from the 'podcast' table. @@ -16,32 +20,54 @@ class InvalidPodcastException extends Exception */ class Podcast extends BasePodcast { - /** Creates a Podcast object from an array containing metadata. + // These fields should never be modified with POST/PUT data + private static $privateFields = array( + "id", + "url", + "type", + "owner" + ); + + /** Creates a Podcast object from the given podcast URL. * This is used by our Podcast REST API - * @param $podcastArray An array containing metadata for a Podcast object. * - * @return Podcast Array + * @param $podcastArray An array containing the URL for a Podcast object. + * + * @return array - Podcast Array with a full list of episodes * @throws Exception + * @throws InvalidPodcastException + * @throws PodcastLimitReachedException */ + public static function create($podcastArray) { if (Application_Service_PodcastService::podcastLimitReached()) { throw new PodcastLimitReachedException(); } - // TODO are we implementing this here?? - if (!Application_Service_PodcastService::validatePodcastUrl($podcastArray["url"])) { + $rss = Application_Service_PodcastService::getPodcastFeed($podcastArray["url"]); + if (!$rss) { throw new InvalidPodcastException(); } try { $podcast = new Podcast(); - $podcast->fromArray($podcastArray, BasePeer::TYPE_FIELDNAME); + $podcast->setDbUrl($podcastArray["url"]); + $podcast->setDbTitle($rss->title); + $podcast->setDbCreator($rss->author); + $podcast->setDbDescription($rss->description); $podcast->setDbOwner(self::getOwnerId()); $podcast->setDbType(IMPORTED_PODCAST); $podcast->save(); - return $podcast->toArray(BasePeer::TYPE_FIELDNAME); + $podcastArray = array(); + array_push($podcastArray, $podcast->toArray(BasePeer::TYPE_FIELDNAME)); + + $podcastArray["episodes"] = array(); + foreach ($rss->item as $item) { + array_push($podcastArray["episodes"], $item); + } + return $podcastArray; } catch(Exception $e) { $podcast->delete(); throw $e; @@ -49,6 +75,85 @@ class Podcast extends BasePodcast } + /** + * Fetches a Podcast's rss feed and returns all its episodes with + * the Podcast object + * + * @param $podcastId + * + * @throws PodcastNotFoundException + * @return array - Podcast Array with a full list of episodes + */ + public static function getPodcastById($podcastId) + { + $podcast = PodcastQuery::create()->findPk($podcastId); + if (!$podcast) { + throw new PodcastNotFoundException(); + } + + $rss = Application_Service_PodcastService::getPodcastFeed($podcast->getDbUrl()); + + $podcastArray = array(); + array_push($podcastArray, $podcast->toArray(BasePeer::TYPE_FIELDNAME)); + + $podcastArray["episodes"] = array(); + foreach ($rss->item as $item) { + array_push($podcastArray["episodes"], $item); + } + + return $podcastArray; + } + + /** + * Updates a Podcast object with the given metadata + * + * @param $podcastId + * @param $data + * @return array + * @throws Exception + * @throws PodcastNotFoundException + */ + public static function updateFromArray($podcastId, $data) + { + $podcast = PodcastQuery::create()->findPk($podcastId); + if (!$podcast) { + throw new PodcastNotFoundException(); + } + + $data = self::removePrivateFields($data); + + $podcast->fromArray($data, BasePeer::TYPE_FIELDNAME); + $podcast->save(); + + return $podcast->toArray(BasePeer::TYPE_FIELDNAME); + } + + /** + * Deletes a Podcast and its podcast episodes + * + * @param $podcastId + * @throws Exception + * @throws PodcastNotFoundException + */ + public static function deleteById($podcastId) + { + $podcast = PodcastQuery::create()->findPk($podcastId); + if ($podcast) { + $podcast->delete(); + } else { + throw new PodcastNotFoundException(); + } + } + + private static function removePrivateFields($data) + { + foreach (self::$privateFields as $key) { + unset($data[$key]); + } + + return $data; + } + //TODO move this somewhere where it makes sense private static function getOwnerId() { diff --git a/airtime_mvc/application/modules/rest/controllers/PodcastController.php b/airtime_mvc/application/modules/rest/controllers/PodcastController.php index ceefc281e..2f54d537d 100644 --- a/airtime_mvc/application/modules/rest/controllers/PodcastController.php +++ b/airtime_mvc/application/modules/rest/controllers/PodcastController.php @@ -50,8 +50,12 @@ class Rest_PodcastController extends Zend_Rest_Controller } try { - //https://github.com/aaronsnoswell/itunes-podcast-feed/blob/master/feed.php - + $this->getResponse() + ->setHttpResponseCode(200) + ->appendBody(json_encode(Podcast::getPodcastById($id))); + } catch (PodcastNotFoundException $e) { + $this->podcastNotFoundResponse(); + Logging::error($e->getMessage()); } catch (Exception $e) { } @@ -82,8 +86,9 @@ class Rest_PodcastController extends Zend_Rest_Controller ->appendBody("ERROR: Podcast limit reached."); } catch (InvalidPodcastException $e) { - $this->invalidDataResponse(); - Logging::error($e->getMessage()); + $this->getResponse() + ->setHttpResponseCode(400) + ->appendBody("ERROR: Invalid Podcast."); } catch (Exception $e) { $this->unknownErrorResponse(); @@ -94,12 +99,50 @@ class Rest_PodcastController extends Zend_Rest_Controller public function putAction() { - Logging::info("podcast put"); + $id = $this->getId(); + if (!$id) { + return; + } + + try { + $requestData = json_decode($this->getRequest()->getRawBody(), true); + + $podcast = Podcast::updateFromArray($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() { - Logging::info("delete podcast"); + $id = $this->getId(); + if (!$id) { + return; + } + + try { + Podcast::deleteById($id); + $this->getResponse() + ->setHttpResponseCode(204); + } + catch (PodcastNotFoundException $e) { + $this->podcastNotFoundResponse(); + Logging::error($e->getMessage()); + } + catch (Exception $e) { + $this->unknownErrorResponse(); + Logging::error($e->getMessage()); + } } private function getId() @@ -120,4 +163,11 @@ class Rest_PodcastController extends Zend_Rest_Controller $resp->appendBody("An unknown error occurred."); } + private function podcastNotFoundResponse() + { + $resp = $this->getResponse(); + $resp->setHttpResponseCode(404); + $resp->appendBody("ERROR: Podcast not found."); + } + } diff --git a/airtime_mvc/application/services/PodcastService.php b/airtime_mvc/application/services/PodcastService.php index dac1513ca..7ea5a9800 100644 --- a/airtime_mvc/application/services/PodcastService.php +++ b/airtime_mvc/application/services/PodcastService.php @@ -19,16 +19,24 @@ class Application_Service_PodcastService } /** - * Returns true if the given podcast URL is valid. + * Returns parsed rss feed, or false if the given URL cannot be downloaded * * @param $podcastUrl String containing the podcast feed URL * - * @return bool + * @return mixed */ - public static function validatePodcastUrl($podcastUrl) + public static function getPodcastFeed($podcastUrl) { - //TODO - return true; + try { + return Feed::loadRss($podcastUrl); + } catch (FeedException $e) { + return false; + } + } + + public static function getPodcastEpisodeFeed($podcast) + { + } } \ No newline at end of file