* SAAS-1182 - added sanity checks and additional logic to rss import and episode generation

* SAAS-1184 - started work on podcast UI polishing
* Fixed pull request issues
This commit is contained in:
Duncan Sommerville 2015-11-09 18:17:49 -05:00
parent 1bc0f9e54b
commit 0360b5e460
8 changed files with 59 additions and 32 deletions

View file

@ -310,7 +310,7 @@ class StationPodcastTask implements AirtimeTask {
class TaskFactory { class TaskFactory {
/** /**
* PHP doesn't have ENUMs so declare them as interface constants * PHP doesn't have ENUMs so declare them as constants
* 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
*/ */

View file

@ -222,7 +222,6 @@ class LibraryController extends Zend_Controller_Action
$message = null; $message = null;
$noPermissionMsg = _("You don't have permission to delete selected items."); $noPermissionMsg = _("You don't have permission to delete selected items.");
Logging::info($mediaItems);
foreach ($mediaItems as $media) { foreach ($mediaItems as $media) {
if ($media["type"] === "audioclip") { if ($media["type"] === "audioclip") {

View file

@ -288,6 +288,12 @@ class Application_Service_PodcastEpisodeService extends Application_Service_Thir
$episodesArray = array(); $episodesArray = array();
foreach ($rss->get_items() as $item) { foreach ($rss->get_items() as $item) {
// If the enclosure is empty, this isn't a podcast episode
$enclosure = $item->get_enclosure();
$url = $enclosure instanceof SimplePie_Enclosure ? $enclosure->get_link() : $enclosure["link"];
if (empty($url)) {
continue;
}
$itemId = $item->get_id(); $itemId = $item->get_id();
$ingested = in_array($itemId, $episodeIds) ? (empty($episodeFiles[$itemId]) ? -1 : 1) : 0; $ingested = in_array($itemId, $episodeIds) ? (empty($episodeFiles[$itemId]) ? -1 : 1) : 0;
$file = $ingested > 0 && !empty($episodeFiles[$itemId]) ? $file = $ingested > 0 && !empty($episodeFiles[$itemId]) ?

View file

@ -86,8 +86,17 @@ class Application_Service_PodcastService
$podcastArray["link"] = htmlspecialchars($rss->get_link()); $podcastArray["link"] = htmlspecialchars($rss->get_link());
$podcastArray["language"] = htmlspecialchars($rss->get_language()); $podcastArray["language"] = htmlspecialchars($rss->get_language());
$podcastArray["copyright"] = htmlspecialchars($rss->get_copyright()); $podcastArray["copyright"] = htmlspecialchars($rss->get_copyright());
$podcastArray["creator"] = htmlspecialchars($rss->get_author()->get_name());
$podcastArray["category"] = htmlspecialchars($rss->get_categories()); $name = empty($rss->get_author()) ? "" : $rss->get_author()->get_name();
$podcastArray["creator"] = htmlspecialchars($name);
$categories = array();
if (is_array($rss->get_categories())) {
foreach ($rss->get_categories() as $category) {
array_push($categories, $category->get_scheme() . ":" . $category->get_term());
}
}
$podcastArray["category"] = htmlspecialchars(implode($categories));
//TODO: put in constants //TODO: put in constants
$itunesChannel = "http://www.itunes.com/dtds/podcast-1.0.dtd"; $itunesChannel = "http://www.itunes.com/dtds/podcast-1.0.dtd";
@ -97,11 +106,13 @@ class Application_Service_PodcastService
$itunesCategory = $rss->get_channel_tags($itunesChannel, 'category'); $itunesCategory = $rss->get_channel_tags($itunesChannel, 'category');
$categoryArray = array(); $categoryArray = array();
if (is_array($itunesCategory)) {
foreach ($itunesCategory as $c => $data) { foreach ($itunesCategory as $c => $data) {
foreach ($data["attribs"] as $attrib) { foreach ($data["attribs"] as $attrib) {
array_push($categoryArray, $attrib["text"]); array_push($categoryArray, $attrib["text"]);
} }
} }
}
$podcastArray["itunes_category"] = implode(",", $categoryArray); $podcastArray["itunes_category"] = implode(",", $categoryArray);
$itunesAuthor = $rss->get_channel_tags($itunesChannel, 'author'); $itunesAuthor = $rss->get_channel_tags($itunesChannel, 'author');
@ -128,6 +139,7 @@ class Application_Service_PodcastService
$importedPodcast = new ImportedPodcast(); $importedPodcast = new ImportedPodcast();
$importedPodcast->fromArray($podcastArray, BasePeer::TYPE_FIELDNAME); $importedPodcast->fromArray($podcastArray, BasePeer::TYPE_FIELDNAME);
$importedPodcast->setPodcast($podcast); $importedPodcast->setPodcast($podcast);
$importedPodcast->setDbAutoIngest(true);
$importedPodcast->save(); $importedPodcast->save();
return $podcast->toArray(BasePeer::TYPE_FIELDNAME); return $podcast->toArray(BasePeer::TYPE_FIELDNAME);

View file

@ -18,7 +18,7 @@
</form> </form>
</div> </div>
<table class="datatable podcast_episodes" cellpadding="0" cellspacing="0"></table> <!-- <table class="datatable podcast_episodes" cellpadding="0" cellspacing="0"></table>-->
<div class="btn-toolbar clearfix"> <div class="btn-toolbar clearfix">
<div class="btn-group pull-right"> <div class="btn-group pull-right">

View file

@ -54,22 +54,22 @@
<fieldset> <fieldset>
<legend><?php echo _("iTunes Fields") ?></legend> <legend><?php echo _("iTunes Fields") ?></legend>
<label><?php echo _("iTunes Author") ?></label> <label><?php echo _("Author") ?></label>
<input name="podcast_itunes_author" ng-model="podcast.itunes_author" type="text"/> <input name="podcast_itunes_author" ng-model="podcast.itunes_author" type="text"/>
<label><?php echo _("iTunes Keywords") ?></label> <label><?php echo _("Keywords") ?></label>
<input name="podcast_itunes_keywords" ng-model="podcast.itunes_keywords" type="text"/> <input name="podcast_itunes_keywords" ng-model="podcast.itunes_keywords" type="text"/>
<label><?php echo _("iTunes Summary") ?></label> <label><?php echo _("Summary") ?></label>
<textarea name="podcast_itunes_summary" ng-model="podcast.itunes_summary"></textarea> <textarea name="podcast_itunes_summary" ng-model="podcast.itunes_summary"></textarea>
<label><?php echo _("iTunes Subtitle") ?></label> <label><?php echo _("Subtitle") ?></label>
<textarea name="podcast_itunes_subtitle" ng-model="podcast.itunes_subtitle"></textarea> <textarea name="podcast_itunes_subtitle" ng-model="podcast.itunes_subtitle"></textarea>
<label><?php echo _("iTunes Category") ?></label> <label><?php echo _("Category") ?></label>
<input name="podcast_itunes_category" ng-model="podcast.itunes_category" type="text"/> <input name="podcast_itunes_category" ng-model="podcast.itunes_category" type="text"/>
<label><?php echo _("iTunes Explicit") ?></label> <label><?php echo _("Explicit") ?></label>
<input name="podcast_itunes_explicit" ng-model="podcast.itunes_explicit" type="checkbox"/> <input name="podcast_itunes_explicit" ng-model="podcast.itunes_explicit" type="checkbox"/>
</fieldset> </fieldset>
</form> </form>

View file

@ -1274,7 +1274,7 @@ var AIRTIME = (function(AIRTIME) {
var dialog = $("#podcast_episode_dialog").html(episode.description); var dialog = $("#podcast_episode_dialog").html(episode.description);
dialog.html(dialog.text()); dialog.html(dialog.text());
dialog.dialog({ dialog.dialog({
title: $.i18n._(episode.title), title: episode.title,
width: "auto", width: "auto",
height: "auto", height: "auto",
modal: true, modal: true,

View file

@ -12,8 +12,8 @@ var AIRTIME = (function (AIRTIME) {
/** /**
* PodcastController constructor. * PodcastController constructor.
* *
* @param {Object} $scope angular scope service object * @param {angular.scope} $scope angular scope service object
* @param {Object} $http angular http service object * @param {angular.http} $http angular http service object
* @param {Object} podcast podcast metadata object * @param {Object} podcast podcast metadata object
* @param {int} podcast.id podcast unique identifier * @param {int} podcast.id podcast unique identifier
* @param {string} podcast.title podcast metadata title * @param {string} podcast.title podcast metadata title
@ -80,6 +80,9 @@ var AIRTIME = (function (AIRTIME) {
* @private * @private
*/ */
PodcastController.prototype._initTable = function() { PodcastController.prototype._initTable = function() {
/*
* Remove the episode table for imported podcasts since its functionality is replicated in the left-hand pane
*
var self = this, var self = this,
$scope = self.$scope; $scope = self.$scope;
// We want to fetch the data statically for imported podcasts because we would need to implement sorting // We want to fetch the data statically for imported podcasts because we would need to implement sorting
@ -91,12 +94,12 @@ var AIRTIME = (function (AIRTIME) {
// If we load sequentially there's a delay before the table appears // If we load sequentially there's a delay before the table appears
aaData : {}, aaData : {},
aoColumns : [ aoColumns : [
/* GUID */ { "sTitle" : "" , "mDataProp" : "guid" , "sClass" : "podcast_episodes_guid" , "bVisible" : false }, { "sTitle" : "" , "mDataProp" : "guid" , "sClass" : "podcast_episodes_guid" , "bVisible" : false },
/* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" }, { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" },
/* Author */ { "sTitle" : $.i18n._("Author") , "mDataProp" : "author" , "sClass" : "podcast_episodes_author" , "sWidth" : "170px" }, { "sTitle" : $.i18n._("Author") , "mDataProp" : "author" , "sClass" : "podcast_episodes_author" , "sWidth" : "170px" },
/* Description */ { "sTitle" : $.i18n._("Description") , "mDataProp" : "description" , "sClass" : "podcast_episodes_description" , "sWidth" : "300px" }, { "sTitle" : $.i18n._("Description") , "mDataProp" : "description" , "sClass" : "podcast_episodes_description" , "sWidth" : "300px" },
/* Link */ { "sTitle" : $.i18n._("Link") , "mDataProp" : "link" , "sClass" : "podcast_episodes_link" , "sWidth" : "170px" }, { "sTitle" : $.i18n._("Link") , "mDataProp" : "link" , "sClass" : "podcast_episodes_link" , "sWidth" : "170px" },
/* Publication Date */ { "sTitle" : $.i18n._("Publication Date") , "mDataProp" : "pub_date" , "sClass" : "podcast_episodes_pub_date" , "sWidth" : "170px" } { "sTitle" : $.i18n._("Publication Date") , "mDataProp" : "pub_date" , "sClass" : "podcast_episodes_pub_date" , "sWidth" : "170px" }
] ]
}, },
buttons = { buttons = {
@ -127,6 +130,7 @@ var AIRTIME = (function (AIRTIME) {
} }
); );
self.reloadEpisodeTable(); self.reloadEpisodeTable();
*/
}; };
/** /**
@ -151,9 +155,11 @@ var AIRTIME = (function (AIRTIME) {
/** /**
* StationPodcastController constructor. * StationPodcastController constructor.
* *
* @param {{}} $scope angular scope service object * @param {angular.scope} $scope angular scope service object
* @param {{}} $http angular http service object * @param {angular.http} $http angular http service object
* @param {{}} podcast podcast metadata object * @param {Object} podcast podcast metadata object
* @param {int} podcast.id podcast unique identifier
* @param {string} podcast.title podcast metadata title
* @param {Tab} tab Tab object the controller is being bootstrapped in * @param {Tab} tab Tab object the controller is being bootstrapped in
* *
* @constructor * @constructor
@ -496,6 +502,10 @@ var AIRTIME = (function (AIRTIME) {
mod.addPodcast = function () { mod.addPodcast = function () {
$.post(endpoint, $("#podcast_url_dialog").find("form").serialize(), function(json) { $.post(endpoint, $("#podcast_url_dialog").find("form").serialize(), function(json) {
_initAppFromResponse(json); _initAppFromResponse(json);
// Open the episode view for the newly created podcast in the left-hand pane
AIRTIME.library.podcastEpisodeTableWidget.reload(JSON.parse(json.podcast).id);
AIRTIME.library.podcastTableWidget.clearSelection();
AIRTIME.library.setCurrentTable(AIRTIME.library.DataTableTypeEnum.PODCAST_EPISODES);
$("#podcast_url_dialog").dialog("close"); $("#podcast_url_dialog").dialog("close");
}); });
}; };
@ -613,7 +623,7 @@ var AIRTIME = (function (AIRTIME) {
var selected = self.getSelectedRows().length, container, var selected = self.getSelectedRows().length, container,
width = self._$wrapperDOMNode.closest(".dataTables_wrapper").outerWidth(), message; width = self._$wrapperDOMNode.closest(".dataTables_wrapper").outerWidth(), message;
message = sprintf($.i18n._("Adding %s Item%s"), selected, selected > 1 ? "s" : ""); message = sprintf($.i18n._(selected > 1 ? "Adding %s Items" : "Adding %s Item"), selected);
container = $('<div/>').attr('id', 'draggingContainer').append('<tr/>') container = $('<div/>').attr('id', 'draggingContainer').append('<tr/>')
.find("tr").append('<td/>').find("td") .find("tr").append('<td/>').find("td")
.attr("colspan", 100).width(width).css("max-width", "none") .attr("colspan", 100).width(width).css("max-width", "none")