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 %>