diff --git a/README.md b/README.md index a2a5c6e..02afe25 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A module for adding a podcast or multiple podcasts to your SilverStripe site. Wi ## Requirements -* SilverStripe 3.1 +* SilverStripe 3.4 ## Installation diff --git a/code/dataobjects/PodcastEpisode.php b/code/dataobjects/PodcastEpisode.php index 6c3de21..cbf3c6b 100644 --- a/code/dataobjects/PodcastEpisode.php +++ b/code/dataobjects/PodcastEpisode.php @@ -1,154 +1,236 @@ 'File' - ,'EpisodeImage' => 'Image' - ,'PodcastPage' => 'PodcastPage' - ); - - private static $db = array( - 'EpisodeTitle' => 'VarChar(255)' - ,'EpisodeSubtitle' => 'VarChar(255)' - ,'EpisodeSummary' => 'HTMLText' - ,'EpisodeAuthor' => 'VarChar(127)' - ,'BlockEpisode' => 'Boolean' - ,'ExplicitEpisode' => 'enum("No, Clean, Yes");' - ,'EpisodeDate' => 'SS_Datetime' - ,'EpisodeDuration' => 'Time' - ,'EpisodeKeywords' => 'Text' - ); - - - private static $searchable_fields = array( - 'EpisodeTitle' - ,'EpisodeSubtitle' - ,'EpisodeAuthor' - ,'BlockEpisode' - ,'ExplicitEpisode' - ,'EpisodeDate' - ,'EpisodeKeywords' - ); - - private static $summary_fields = array( - 'ID' - ,'EpisodeDate' - ,'EpisodeTitle' - ,'EpisodeDuration' - ); - - public function getCMSFields() { - $fields = parent::getCMSFields(); - - $fields->fieldByName('Root.Main.EpisodeDate')->dateField->setConfig('showcalendar', true); - $fields->fieldByName('Root.Main.EpisodeDate')->dateField->setConfig('dateformat', 'dd/MM/YYYY'); - $fields->fieldByName('Root.Main.EpisodeDate')->timeField->setConfig('timeformat', 'HH:MM'); - $fields->fieldByName('Root.Main.EpisodeDate')->setDescription('Date when the episode was published.'); - $fields->fieldByName('Root.Main.EpisodeDate')->setValue(date('r')); - - $fields->fieldByName('Root.Main.BlockEpisode')->setDescription('Prevent the episode from appearing in the iTunes podcast directory.'); - $fields->fieldByName('Root.Main.ExplicitEpisode')->setDescription("Displays an 'Explicit', 'Clean' or no parental advisory graphic next to your episode in iTunes."); - - $fields->fieldByName('Root.Main.EpisodeFile') - ->setFolderName('podcast/episodes') - ->getValidator()->setAllowedExtensions(array( - 'pdf' - ,'zip' - ,'doc' - ,'docx' - ,'xls' - ,'xlsx' - ,'ppt' - ,'pptx' - ,'mp3' - ,'wav' - ,'m4a' - ,'m4v' - ,'mpeg' - ,'mpg' - ,'mp4' - ,'mpe' - ,'mov' - ,'avi' - ,'3gp' - )); - - $fields->fieldByName('Root.Main.EpisodeImage') - ->setFolderName('podcast/episode-images') - ->getValidator()->setAllowedExtensions(array('jpg', 'png')); - - return $fields; - } - - /** - * Returns the absolute link to the episode's page - * @return string - */ - public function EpisodeLink() { - return $this->PodcastPage()->AbsoluteLink('episode/' . $this->ID); - } - - /** - * Returns mime type for use in PodcastRSS enclosure - * @return string - */ - public function getMime() { - $filename = $this->EpisodeFile()->getFilename(); - $filename = explode('.', $filename); - - $mime_types = array( - 'pdf' => 'application/pdf' - ,'zip' => 'application/zip' - ,'doc' => 'application/msword' - ,'docx' => 'application/msword' - ,'xls' => 'application/vnd.ms-excel' - ,'xlsx' => 'application/vnd.ms-excel' - ,'ppt' => 'application/vnd.ms-powerpoint' - ,'pptx' => 'application/vnd.ms-powerpoint' - ,'mp3' => 'audio/mpeg' - ,'wav' => 'audio/x-wav' - ,'m4a' => 'audio/x-m4a' - ,'m4v' => 'video/x-m4v' - ,'mpeg' => 'video/mpeg' - ,'mpg' => 'video/mpeg' - ,'mp4' => 'video/mpeg' - ,'mpe' => 'video/mpeg' - ,'mov' => 'video/quicktime' - ,'avi' => 'video/x-msvideo' - ,'3gp' => 'video/3gpp' - ); - - $extension = strtolower(end($filename)); - - return $mime_types[$extension]; - } - - /** - * Returns the type for page template for audio, video tags or download link - * @return string - */ - public function getType() { - // return an empty string if there's no file - if(!$this->EpisodeFileID){ - return ''; - } - - $mime_types = array( - 'mp3' => 'audio' - ,'wav' => 'audio' - ,'m4a' => 'audio' - ,'m4v' => 'video' - ,'mpeg' => 'video' - ,'mpg' => 'video' - ,'mp4' => 'video' - ,'mpe' => 'video' - ,'mov' => 'video' - ,'avi' => 'video' - ,'3gp' => 'video' - ); - - $extension = strtolower($this->EpisodeFile()->getExtension()); - - return $mime_types[$extension]; - } -} \ No newline at end of file +class PodcastEpisode extends DataObject +{ + private static $has_one = array( + 'EpisodeFile' => 'File' + ,'EpisodeImage' => 'Image' + ,'PodcastPage' => 'PodcastPage' + ); + + private static $db = array( + 'EpisodeTitle' => 'VarChar(255)' + ,'EpisodeSubtitle' => 'VarChar(255)' + ,'EpisodeSummary' => 'HTMLText' + ,'EpisodeAuthor' => 'VarChar(127)' + ,'BlockEpisode' => 'Boolean' + ,'ExplicitEpisode' => 'enum("No, Clean, Yes");' + ,'EpisodeDate' => 'SS_Datetime' + ,'EpisodeDuration' => 'Time' + ); + + private static $searchable_fields = array( + 'EpisodeTitle' + ,'EpisodeSubtitle' + ,'EpisodeAuthor' + ,'BlockEpisode' + ,'ExplicitEpisode' + ,'EpisodeDate' + ); + + private static $summary_fields = array( + 'EpisodeThumb' => 'Image' + ,'EpisodeDate' => 'Date' + ,'EpisodeTitle' => 'Title' + ,'EpisodeDuration' => 'Duration' + ); + + private static $better_buttons_actions = array( + 'getTags' + ); + + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + $fields->fieldByName('Root.Main.EpisodeDate')->dateField + ->setConfig('showcalendar', true) + ->setConfig('dateformat', 'dd/MM/YYYY'); + $fields->fieldByName('Root.Main.EpisodeDate')->timeField + ->setConfig('timeformat', 'HH:mm'); + $fields->fieldByName('Root.Main.EpisodeDate') + ->setDescription('Date when the episode was published.') + ->setValue(date('r')); + + $fields->fieldByName('Root.Main.EpisodeDuration') + ->setConfig('timeformat', 'HH:mm:ss') + ->setDescription('In the format HH:mm:ss e.g. 00:56:18'); + + $fields->fieldByName('Root.Main.BlockEpisode') + ->setDescription('Prevent the episode from appearing in the iTunes podcast directory.'); + $fields->fieldByName('Root.Main.ExplicitEpisode') + ->setDescription("Displays an 'Explicit', 'Clean' or no parental advisory graphic next to your episode in iTunes."); + + $fields->fieldByName('Root.Main.EpisodeFile') + ->setFolderName('podcast/episodes') + ->getValidator()->setAllowedExtensions(array( + 'pdf', + 'zip', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'ppt', + 'pptx', + 'mp3', + 'wav', + 'm4a', + 'm4v', + 'mpeg', + 'mpg', + 'mp4', + 'mpe', + 'mov', + 'avi', + '3gp', + )); + + $fields->fieldByName('Root.Main.EpisodeImage') + ->setFolderName('podcast/episode-images') + ->getValidator()->setAllowedExtensions(array('jpg', 'png')); + + return $fields; + } + + public function getBetterButtonsUtils() + { + $fields = parent::getBetterButtonsUtils(); + $fields->push( + BetterButtonCustomAction::create('getTags', 'Get ID3 Tags') + ->setRedirectType(BetterButtonCustomAction::REFRESH) + ); + + return $fields; + } + + + /** + * Returns the episode's title + * @return string + */ + public function getTitle() + { + return $this->EpisodeTitle; + } + + /** + * Returns the absolute link to the episode's page + * @return string + */ + public function episodeLink() + { + return $this->PodcastPage()->AbsoluteLink('episode/' . $this->ID); + } + + /** + * Returns a thumbnail of the Episode Image + * @return Image + */ + public function episodeThumb() + { + return $this->EpisodeImage()->fill(40, 40); + } + + /** + * Returns mime type for use in PodcastRSS enclosure + * @return string + */ + public function getMime() + { + $filename = $this->EpisodeFile()->getFilename(); + $filename = explode('.', $filename); + + $mime_types = array( + 'pdf' => 'application/pdf', + 'zip' => 'application/zip', + 'doc' => 'application/msword', + 'docx' => 'application/msword', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptx' => 'application/vnd.ms-powerpoint', + 'mp3' => 'audio/mpeg', + 'wav' => 'audio/x-wav', + 'm4a' => 'audio/x-m4a', + 'm4v' => 'video/x-m4v', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mp4' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mov' => 'video/quicktime', + 'avi' => 'video/x-msvideo', + '3gp' => 'video/3gpp', + ); + + $extension = strtolower(end($filename)); + + return $mime_types[$extension]; + } + + /** + * Returns the type for page template for audio, video tags or download link + * @return string + */ + public function getType() + { + // return an empty string if there's no file + if (!$this->EpisodeFileID) { + return ''; + } + + $mime_types = array( + 'mp3' => 'audio' + ,'wav' => 'audio' + ,'m4a' => 'audio' + ,'m4v' => 'video' + ,'mpeg' => 'video' + ,'mpg' => 'video' + ,'mp4' => 'video' + ,'mpe' => 'video' + ,'mov' => 'video' + ,'avi' => 'video' + ,'3gp' => 'video' + ); + + $extension = strtolower($this->EpisodeFile()->getExtension()); + + return $mime_types[$extension]; + } + + public function getTags() + { + if (!$this->EpisodeFileID) { + return ''; + } + $getID3 = new \getID3; + $file = $getID3->analyze($this->EpisodeFile()->FullPath); + $tags = $file['tags']['id3v2']; + if (!empty($tags)) { + $this->EpisodeTitle = $tags['title'][0] ? $tags['title'][0] : ''; + $this->EpisodeAuthor = $tags['artist'][0] ? $tags['artist'][0] : ''; + $this->EpisodeSummary = $tags['comment'][0] ? $tags['comment'][0] : ''; + $this->EpisodeDuration = $file['playtime_seconds'] ? gmdate('H:i:s', $file['playtime_seconds']) : ''; + $this->write(); + } + } + + public function canView($member = null) + { + return true; + } + + public function canEdit($member = null) + { + return Permission::check('PODCAST_ADMIN'); + } + + public function canDelete($member = null) + { + return Permission::check('PODCAST_ADMIN'); + } + + public function canCreate($member = null) + { + return Permission::check('PODCAST_ADMIN'); + } +} diff --git a/code/pagetypes/PodcastPage.php b/code/pagetypes/PodcastPage.php index c193385..9c2e2ca 100644 --- a/code/pagetypes/PodcastPage.php +++ b/code/pagetypes/PodcastPage.php @@ -1,237 +1,279 @@ 'VarChar(255)' - ,'Subtitle' => 'VarChar(255)' - ,'Language' => 'VarChar(32)' - ,'Author' => 'VarChar(127)' - ,'Summary' => 'HTMLText' - ,'OwnerName' => 'VarChar(127)' - ,'OwnerEmail' => 'VarChar(127)' - ,'Copyright' => 'VarChar(127)' - ,'Complete' => 'Boolean' - ,'Block' => 'Boolean' - ,'Explicit' => 'enum("No, Clean, Yes");' - ,'Keywords' => 'Text' - ); - - private static $has_one = array( - 'PodcastImage' => 'Image' - ); - - private static $has_many = array( - 'PodcastEpisodes' => 'PodcastEpisode' - ); - - public function getCMSFields() { - $fields = parent::getCMSFields(); - - $languageField = new DropdownField('Language', 'Language', array( - 'af' => 'Afrikaans' - ,'sq' => 'Albanian' - ,'eu' => 'Basque' - ,'be' => 'Belarusian' - ,'bg' => 'Bulgarian' - ,'ca' => 'Catalan' - ,'zh-cn' => 'Chinese (Simplified)' - ,'zh-tw' => 'Chinese (Traditional)' - ,'hr' => 'Croatian' - ,'cs' => 'Czech' - ,'da' => 'Danish' - ,'nl' => 'Dutch' - ,'nl-be' => 'Dutch (Belgium)' - ,'nl-nl' => 'Dutch (Netherlands)' - ,'en' => 'English' - ,'en-au' => 'English (Australia)' - ,'en-bz' => 'English (Belize)' - ,'en-ca' => 'English (Canada)' - ,'en-ie' => 'English (Ireland)' - ,'en-jm' => 'English (Jamaica)' - ,'en-nz' => 'English (New Zealand)' - ,'en-ph' => 'English (Phillipines)' - ,'en-za' => 'English (South Africa)' - ,'en-tt' => 'English (Trinidad)' - ,'en-gb' => 'English (United Kingdom)' - ,'en-us' => 'English (United States)' - ,'en-zw' => 'English (Zimbabwe)' - ,'et' => 'Estonian' - ,'fo' => 'Faeroese' - ,'fi' => 'Finnish' - ,'fr' => 'French' - ,'fr-be' => 'French (Belgium)' - ,'fr-ca' => 'French (Canada)' - ,'fr-fr' => 'French (France)' - ,'fr-lu' => 'French (Luxembourg)' - ,'fr-mc' => 'French (Monaco)' - ,'fr-ch' => 'French (Switzerland)' - ,'gl' => 'Galician' - ,'gd' => 'Gaelic' - ,'de' => 'German' - ,'de-at' => 'German (Austria)' - ,'de-de' => 'German (Germany)' - ,'de-li' => 'German (Liechtenstein)' - ,'de-lu' => 'German (Luxembourg)' - ,'de-ch' => 'German (Switzerland)' - ,'el' => 'Greek' - ,'haw' => 'Hawaiian' - ,'hu' => 'Hungarian' - ,'is' => 'Icelandic' - ,'in' => 'Indonesian' - ,'ga' => 'Irish' - ,'it' => 'Italian' - ,'it-it' => 'Italian (Italy)' - ,'it-ch' => 'Italian (Switzerland)' - ,'ja' => 'Japanese' - ,'ko' => 'Korean' - ,'mk' => 'Macedonian' - ,'no' => 'Norwegian' - ,'pl' => 'Polish' - ,'pt' => 'Portuguese' - ,'pt-br' => 'Portuguese (Brazil)' - ,'pt-pt' => 'Portuguese (Portugal)' - ,'ro' => 'Romanian' - ,'ro-mo' => 'Romanian (Moldova)' - ,'ro-ro' => 'Romanian (Romania)' - ,'ru' => 'Russian' - ,'ru-mo' => 'Russian (Moldova)' - ,'ru-ru' => 'Russian (Russia)' - ,'sr' => 'Serbian' - ,'sk' => 'Slovak' - ,'sl' => 'Slovenian' - ,'es' => 'Spanish' - ,'es-ar' => 'Spanish (Argentina)' - ,'es-bo' => 'Spanish (Bolivia)' - ,'es-cl' => 'Spanish (Chile)' - ,'es-co' => 'Spanish (Colombia)' - ,'es-cr' => 'Spanish (Costa Rica)' - ,'es-do' => 'Spanish (Dominican Republic)' - ,'es-ec' => 'Spanish (Ecuador)' - ,'es-sv' => 'Spanish (El Salvador)' - ,'es-gt' => 'Spanish (Guatemala)' - ,'es-hn' => 'Spanish (Honduras)' - ,'es-mx' => 'Spanish (Mexico)' - ,'es-ni' => 'Spanish (Nicaragua)' - ,'es-pa' => 'Spanish (Panama)' - ,'es-py' => 'Spanish (Paraguay)' - ,'es-pe' => 'Spanish (Peru)' - ,'es-pr' => 'Spanish (Puerto Rico)' - ,'es-es' => 'Spanish (Spain)' - ,'es-uy' => 'Spanish (Uruguay)' - ,'es-ve' => 'Spanish (Venezuela)' - ,'sv' => 'Swedish' - ,'sv-fi' => 'Swedish (Finland)' - ,'sv-se' => 'Swedish (Sweden)' - ,'tr' => 'Turkish' - ,'uk' => 'Ukranian' - )); - $languageField - ->setHasEmptyDefault(true) - ->setEmptyString('Select Language'); - - $podcastImage = new UploadField('PodcastImage', 'Podcast Image'); - $podcastImage - ->setFolderName('podcast/podcast-artwork') - ->setDescription("iTunes recommends a size of at least 1400x1400") - ->getValidator()->setAllowedExtensions(array('jpg', 'png')); - - $completeField = new CheckboxField('Complete'); - $completeField->setDescription('This podcast is complete. No more episodes will be added to the podcast.'); - - $blockField = new CheckboxField('Block'); - $blockField->setDescription('Prevent the entire podcast from appearing in the iTunes podcast directory.'); - - $explicitField = new DropdownField('Explicit', 'Explicit', $this->dbObject('Explicit')->enumValues()); - $explicitField->setDescription("Displays an 'Explicit', 'Clean' or no parental advisory graphic next to your podcast artwork in iTunes."); - - $fields->addFieldsToTab('Root.Podcast', array( - new TextField('PodcastTitle', 'Podcast Title') - ,new TextField('Subtitle') - ,$languageField - ,new TextField('Author') - ,new TextAreaField('Summary') - ,new TextField('OwnerName', 'Owner Name') - ,new EmailField('OwnerEmail', 'Owner Email') - ,new TextField('Copyright') - ,$completeField - ,$blockField - ,$explicitField - ,new TextAreaField('Keywords') - ,$podcastImage - )); - - $config = GridFieldConfig_RelationEditor::create(); - - $episodesTable = new GridField( - 'PodcastEpisodes' - ,'Podcast Episodes' - ,$this->PodcastEpisodes()->sort('EpisodeDate', 'DESC') - ,$config - ); - - $fields->addFieldToTab('Root.Episodes', $episodesTable); - - return $fields; - } +class PodcastPage extends Page implements PermissionProvider +{ + private static $icon = 'podcast/images/podcast-page.png'; + private static $description = 'A page that allows the input of podcast information and the addition of episodes to generate a working podcast with a generated RSS Feed'; + + private static $db = array( + 'PodcastTitle' => 'VarChar(255)' + ,'Subtitle' => 'VarChar(255)' + ,'Language' => 'VarChar(32)' + ,'Author' => 'VarChar(127)' + ,'Summary' => 'HTMLText' + ,'OwnerName' => 'VarChar(127)' + ,'OwnerEmail' => 'VarChar(127)' + ,'Copyright' => 'VarChar(127)' + ,'Complete' => 'Boolean' + ,'Block' => 'Boolean' + ,'Explicit' => 'enum("No, Clean, Yes");' + ,'Keywords' => 'Text' + ); + + private static $has_one = array( + 'PodcastImage' => 'Image' + ); + + private static $has_many = array( + 'PodcastEpisodes' => 'PodcastEpisode' + ); + + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + $languageField = DropdownField::create('Language', 'Language', array( + 'af' => 'Afrikaans', + 'sq' => 'Albanian', + 'eu' => 'Basque', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'ca' => 'Catalan', + 'zh-cn' => 'Chinese (Simplified)', + 'zh-tw' => 'Chinese (Traditional)', + 'hr' => 'Croatian', + 'cs' => 'Czech', + 'da' => 'Danish', + 'nl' => 'Dutch', + 'nl-be' => 'Dutch (Belgium)', + 'nl-nl' => 'Dutch (Netherlands)', + 'en' => 'English', + 'en-au' => 'English (Australia)', + 'en-bz' => 'English (Belize)', + 'en-ca' => 'English (Canada)', + 'en-ie' => 'English (Ireland)', + 'en-jm' => 'English (Jamaica)', + 'en-nz' => 'English (New Zealand)', + 'en-ph' => 'English (Phillipines)', + 'en-za' => 'English (South Africa)', + 'en-tt' => 'English (Trinidad)', + 'en-gb' => 'English (United Kingdom)', + 'en-us' => 'English (United States)', + 'en-zw' => 'English (Zimbabwe)', + 'et' => 'Estonian', + 'fo' => 'Faeroese', + 'fi' => 'Finnish', + 'fr' => 'French', + 'fr-be' => 'French (Belgium)', + 'fr-ca' => 'French (Canada)', + 'fr-fr' => 'French (France)', + 'fr-lu' => 'French (Luxembourg)', + 'fr-mc' => 'French (Monaco)', + 'fr-ch' => 'French (Switzerland)', + 'gl' => 'Galician', + 'gd' => 'Gaelic', + 'de' => 'German', + 'de-at' => 'German (Austria)', + 'de-de' => 'German (Germany)', + 'de-li' => 'German (Liechtenstein)', + 'de-lu' => 'German (Luxembourg)', + 'de-ch' => 'German (Switzerland)', + 'el' => 'Greek', + 'haw' => 'Hawaiian', + 'hu' => 'Hungarian', + 'is' => 'Icelandic', + 'in' => 'Indonesian', + 'ga' => 'Irish', + 'it' => 'Italian', + 'it-it' => 'Italian (Italy)', + 'it-ch' => 'Italian (Switzerland)', + 'ja' => 'Japanese', + 'ko' => 'Korean', + 'mk' => 'Macedonian', + 'no' => 'Norwegian', + 'pl' => 'Polish', + 'pt' => 'Portuguese', + 'pt-br' => 'Portuguese (Brazil)', + 'pt-pt' => 'Portuguese (Portugal)', + 'ro' => 'Romanian', + 'ro-mo' => 'Romanian (Moldova)', + 'ro-ro' => 'Romanian (Romania)', + 'ru' => 'Russian', + 'ru-mo' => 'Russian (Moldova)', + 'ru-ru' => 'Russian (Russia)', + 'sr' => 'Serbian', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'es' => 'Spanish', + 'es-ar' => 'Spanish (Argentina)', + 'es-bo' => 'Spanish (Bolivia)', + 'es-cl' => 'Spanish (Chile)', + 'es-co' => 'Spanish (Colombia)', + 'es-cr' => 'Spanish (Costa Rica)', + 'es-do' => 'Spanish (Dominican Republic)', + 'es-ec' => 'Spanish (Ecuador)', + 'es-sv' => 'Spanish (El Salvador)', + 'es-gt' => 'Spanish (Guatemala)', + 'es-hn' => 'Spanish (Honduras)', + 'es-mx' => 'Spanish (Mexico)', + 'es-ni' => 'Spanish (Nicaragua)', + 'es-pa' => 'Spanish (Panama)', + 'es-py' => 'Spanish (Paraguay)', + 'es-pe' => 'Spanish (Peru)', + 'es-pr' => 'Spanish (Puerto Rico)', + 'es-es' => 'Spanish (Spain)', + 'es-uy' => 'Spanish (Uruguay)', + 'es-ve' => 'Spanish (Venezuela)', + 'sv' => 'Swedish', + 'sv-fi' => 'Swedish (Finland)', + 'sv-se' => 'Swedish (Sweden)', + 'tr' => 'Turkish', + 'uk' => 'Ukranian', + )); + $languageField + ->setHasEmptyDefault(true) + ->setEmptyString('Select Language'); + + $podcastImage = UploadField::create('PodcastImage', 'Podcast Image'); + $podcastImage + ->setFolderName('podcast/podcast-artwork') + ->setDescription("iTunes recommends a size of at least 1400x1400") + ->getValidator()->setAllowedExtensions(array('jpg', 'png')); + + $completeField = CheckboxField::create('Complete'); + $completeField->setDescription('This podcast is complete. No more episodes will be added to the podcast.'); + + $blockField = CheckboxField::create('Block'); + $blockField->setDescription('Prevent the entire podcast from appearing in the iTunes podcast directory.'); + + $explicitField = DropdownField::create('Explicit', 'Explicit', $this->dbObject('Explicit')->enumValues()); + $explicitField->setDescription("Displays an 'Explicit', 'Clean' or no parental advisory graphic next to your podcast artwork in iTunes."); + + $fields->addFieldsToTab('Root.Podcast', array( + TextField::create('PodcastTitle', 'Podcast Title') + ,TextField::create('Subtitle') + ,$languageField + ,TextField::create('Author') + ,TextAreaField::create('Summary') + ,TextField::create('OwnerName', 'Owner Name') + ,EmailField::create('OwnerEmail', 'Owner Email') + ,TextField::create('Copyright') + ,$completeField + ,$blockField + ,$explicitField + ,TextAreaField::create('Keywords') + ,$podcastImage + )); + + $config = GridFieldConfig_RelationEditor::create(); + + $episodesTable = GridField::create( + 'PodcastEpisodes', + 'Podcast Episodes', + $this->PodcastEpisodes()->sort('EpisodeDate', 'DESC'), + $config + ); + + $fields->addFieldToTab('Root.Episodes', $episodesTable); + + return $fields; + } + + public function canView($member = null) + { + return true; + } + + public function canEdit($member = null) + { + return Permission::check('PODCAST_ADMIN'); + } + + public function canDelete($member = null) + { + return Permission::check('PODCAST_ADMIN'); + } + + public function canCreate($member = null) + { + return Permission::check('PODCAST_ADMIN'); + } + + public function providePermissions() + { + return array( + 'PODCAST_ADMIN' => array( + 'name' => 'Edit and upload to podcast', + 'category' => 'Content permissions', + ) + ); + } } -class PodcastPage_Controller extends Page_Controller { - private static $allowed_actions = array( - 'rss', 'episode' - ); - - public function init() { - // Provides a link to the Podcast RSS in the HTML head - RSSFeed::linkToFeed($this->Link('rss')); - - parent::init(); - } - - /** - * Returns the RSS Feed at the URL /rss - * @return SiteTree - */ - public function rss() { - return $this->renderWith("PodcastRSSFeed"); - } - - /** - * Returns a SS_list of podcast episodes for use in the RSS template - * @return SS_List - */ - public function podcastEpisodes() { - return PodcastEpisode::get() - ->filter(array('PodcastPageID' => $this->ID)) - ->sort('EpisodeDate', 'DESC') - ; - } - - - /** - * Returns a paginated list of podcast episodes for use on the podcast page - * @return SS_List - */ - public function paginatedPodcastEpisodes() { - $paginatedList = new PaginatedList( - $this->podcastEpisodes() - ->filter(array('BlockEpisode' => '0')) - ->sort('EpisodeDate', 'DESC') - , $this->request - ); - $paginatedList->setPageLength(5); - return $paginatedList; - } - - /** - * Returns an episode as a page based on ID parameter at the URL -> $PodcastPage/episode/$ID - * @return SiteTree - */ - public function episode() { - $episode = PodcastEpisode::get()->byID($this->Request->param("ID")); - if(!$episode) return $this->httpError(404); - return array("PodcastEpisode" => $episode); - } -} \ No newline at end of file +class PodcastPage_Controller extends Page_Controller +{ + private static $allowed_actions = array( + 'rss', + 'episode', + ); + + public function init() + { + // Provides a link to the Podcast RSS in the HTML head + RSSFeed::linkToFeed($this->Link('rss')); + + parent::init(); + } + + /** + * Returns the RSS Feed at the URL /rss + * @return SiteTree + */ + public function rss() + { + return $this->renderWith("PodcastRSSFeed"); + } + + /** + * Returns a SS_list of podcast episodes for use in the RSS template + * @return SS_List + */ + public function podcastEpisodes() + { + return PodcastEpisode::get() + ->filter(array('PodcastPageID' => $this->ID)) + ->sort('EpisodeDate', 'DESC') + ; + } + + + /** + * Returns a paginated list of podcast episodes for use on the podcast page + * @return SS_List + */ + public function paginatedPodcastEpisodes() + { + $paginatedList = PaginatedList::create( + $this->podcastEpisodes() + ->filter(array('BlockEpisode' => '0')) + ->sort('EpisodeDate', 'DESC'), + $this->request + ); + $paginatedList->setPageLength(5); + return $paginatedList; + } + + /** + * Returns an episode as a page based on ID parameter at the URL -> $PodcastPage/episode/$ID + * @return SiteTree + */ + public function episode(SS_HTTPRequest $request) + { + $episode = PodcastEpisode::get()->byID($request->param('ID')); + if (!$episode) { + return $this->httpError(404, 'That episode could not be found'); + } return array( + 'PodcastEpisode' => $episode + ); + } +} diff --git a/composer.json b/composer.json index 5f694f3..7c65338 100644 --- a/composer.json +++ b/composer.json @@ -6,11 +6,12 @@ "license": "MIT", "authors": [{ "name": "Luke Edwards", - "email": "luke@lukeedwards.co.nz" + "email": "luke@edwards.co.nz" }], "require": { - "silverstripe/framework": "3.1.*", - "silverstripe/cms": "3.1.*" + "silverstripe/framework": "~3.4", + "silverstripe/cms": "~3.4", + "james-heinrich/getid3": "~1.9.12" }, "extra": { "installer-name": "podcast" diff --git a/templates/RSS/PodcastRSSFeed.ss b/templates/RSS/PodcastRSSFeed.ss index 0b40422..833d6f3 100644 --- a/templates/RSS/PodcastRSSFeed.ss +++ b/templates/RSS/PodcastRSSFeed.ss @@ -1,5 +1,5 @@ - + @@ -20,7 +20,6 @@ <% end_if %> <% if $PodcastImage %><% end_if %> -<% if $Keywords %>$Keywords.XML<% end_if %> <% if $Block %>yes<% end_if %> <% if $Explicit %>$Explicit<% end_if %> @@ -33,7 +32,6 @@ $EpisodeSummary.NoHTML.XML $EpisodeSummary.NoHTML.XML <% end_if %> - <% if $EpisodeKeywords %>$Keywords.XML<% end_if %> <% if $EpisodeImage %><% end_if %> <% if $EpisodeFile %> $EpisodeLink<%end_if %>