mirror of
https://github.com/jgonyea/grav-plugin-podcast.git
synced 2025-12-05 16:00:02 +01:00
Tons of work on Grav 1.7 compatibility. Theming updates started
This commit is contained in:
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,3 +1,17 @@
|
|||||||
|
# v3.0.0
|
||||||
|
## 01/23/2021
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Grav v1.7 support. Grav v1.6 is no longer supported.
|
||||||
|
* Individual file field uploads are no longer supported in Grav v1.7. Instead, use the general media upoader and then the filepicker fields to select the appropriate audio/ image files.
|
||||||
|
2. [](#improved)
|
||||||
|
* Better multi-language support while creating new content via the admin plugin.
|
||||||
|
* Twig formatting is improved.
|
||||||
|
* Updated README to indicate that admin is now required. If this becomes a problem, I can revisit the requirements.
|
||||||
|
* Removed `max_upload` audio file size value from plugin configuration.
|
||||||
|
3. [](#bugfix)
|
||||||
|
* Episode subtitle in the rss feed now points to the correct field in the admin form. You may need to re-save this data on v2 Podcast episodes.
|
||||||
|
|
||||||
# v2.1.10
|
# v2.1.10
|
||||||
## 01/21/2021
|
## 01/21/2021
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Podcast Plugin
|
# Podcast Plugin
|
||||||
|
|
||||||
The **Podcast** Plugin is for [Grav CMS](http://github.com/getgrav/grav). This plugin creates the following:
|
The **Podcast** Plugin is for [Grav CMS](http://github.com/getgrav/grav). This plugin creates the following:
|
||||||
- Page templates for Podcast Channel, Podcast Series, and Podcast Episode
|
- Admin Page templates for Podcast Channel, Podcast Series, and Podcast Episode
|
||||||
- An iTunes compatible podcast RSS feed, both at the Podcast Channel (all episodes) and Podcast Series (only a series' episodes)
|
- An iTunes compatible podcast RSS feed, both at the Podcast Channel (all episodes) and Podcast Series (only a series' episodes)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -25,14 +25,13 @@ You should now have all the plugin files under
|
|||||||
/your/site/grav/user/plugins/podcast
|
/your/site/grav/user/plugins/podcast
|
||||||
|
|
||||||
> NOTE: This plugin is a modular component for Grav which requires the following to operate:
|
> NOTE: This plugin is a modular component for Grav which requires the following to operate:
|
||||||
|
* [Grav Core](http://github.com/getgrav/grav)
|
||||||
|
* [Admin](https://github.com/getgrav/grav-plugin-admin)
|
||||||
* [Auto Date](https://github.com/getgrav/grav-plugin-auto-date)
|
* [Auto Date](https://github.com/getgrav/grav-plugin-auto-date)
|
||||||
* [Error](https://github.com/getgrav/grav-plugin-error)
|
|
||||||
* [Feed](https://github.com/getgrav/grav-plugin-feed)
|
* [Feed](https://github.com/getgrav/grav-plugin-feed)
|
||||||
* [GetId3](https://github.com/jgonyea/grav-plugin-get-id3), along with its accompanying [getID3 php library](http://www.getid3.org/)
|
* [GetId3](https://github.com/jgonyea/grav-plugin-get-id3), along with its accompanying [getID3 php library](http://www.getid3.org/)
|
||||||
* [Grav](http://github.com/getgrav/grav)
|
|
||||||
* [Problems](https://github.com/getgrav/grav-plugin-problems)
|
|
||||||
|
|
||||||
> While technically not required, using the [Admin](https://github.com/getgrav/grav-plugin-admin) plugin will assist in adding new content.
|
...and any other required plugins the above list requires.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
# A sample Gemfile
|
|
||||||
source "https://rubygems.org"
|
|
||||||
gem 'compass', ">=1.0.3"
|
|
||||||
gem "sassy-buttons", ">=0.1.4"
|
|
||||||
gem "breakpoint", ">=2.4.0"
|
|
||||||
gem "compass-rgbapng", ">=0.2.1"
|
|
||||||
gem "autoprefixer-rails"
|
|
||||||
gem "ffi", ">= 1.9.24"
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
GEM
|
|
||||||
remote: https://rubygems.org/
|
|
||||||
specs:
|
|
||||||
autoprefixer-rails (9.4.7)
|
|
||||||
execjs
|
|
||||||
breakpoint (2.7.1)
|
|
||||||
sass (~> 3.3)
|
|
||||||
sassy-maps (< 1.0.0)
|
|
||||||
chunky_png (1.3.11)
|
|
||||||
compass (1.0.3)
|
|
||||||
chunky_png (~> 1.2)
|
|
||||||
compass-core (~> 1.0.2)
|
|
||||||
compass-import-once (~> 1.0.5)
|
|
||||||
rb-fsevent (>= 0.9.3)
|
|
||||||
rb-inotify (>= 0.9)
|
|
||||||
sass (>= 3.3.13, < 3.5)
|
|
||||||
compass-core (1.0.3)
|
|
||||||
multi_json (~> 1.0)
|
|
||||||
sass (>= 3.3.0, < 3.5)
|
|
||||||
compass-import-once (1.0.5)
|
|
||||||
sass (>= 3.2, < 3.5)
|
|
||||||
compass-rgbapng (0.2.1)
|
|
||||||
chunky_png (>= 0.8.0)
|
|
||||||
compass (>= 0.10.0)
|
|
||||||
execjs (2.7.0)
|
|
||||||
ffi (1.10.0-x64-mingw32)
|
|
||||||
multi_json (1.13.1)
|
|
||||||
rb-fsevent (0.10.3)
|
|
||||||
rb-inotify (0.10.0)
|
|
||||||
ffi (~> 1.0)
|
|
||||||
sass (3.4.25)
|
|
||||||
sassy-buttons (0.2.6)
|
|
||||||
compass (>= 0.12.2)
|
|
||||||
sassy-maps (0.4.0)
|
|
||||||
sass (~> 3.3)
|
|
||||||
|
|
||||||
PLATFORMS
|
|
||||||
x64-mingw32
|
|
||||||
|
|
||||||
DEPENDENCIES
|
|
||||||
autoprefixer-rails
|
|
||||||
breakpoint (>= 2.4.0)
|
|
||||||
compass (>= 1.0.3)
|
|
||||||
compass-rgbapng (>= 0.2.1)
|
|
||||||
ffi (>= 1.9.24)
|
|
||||||
sassy-buttons (>= 0.1.4)
|
|
||||||
|
|
||||||
BUNDLED WITH
|
|
||||||
2.0.1
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is only needed for Compass/Sass integration. If you are not using
|
|
||||||
# Compass, you may safely ignore or delete this file.
|
|
||||||
#
|
|
||||||
# If you'd like to learn more about Sass and Compass, see the sass/README.txt
|
|
||||||
# file for more information.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Suppressing warnings due to old Zen theme and deprecated legacy browser support.
|
|
||||||
disable_warnings = true
|
|
||||||
|
|
||||||
# Change this to :production when ready to deploy the CSS to the live server.
|
|
||||||
#environment = :development
|
|
||||||
environment = :production
|
|
||||||
|
|
||||||
# Create sourcemaps
|
|
||||||
sourcemap = true
|
|
||||||
|
|
||||||
# In development, we can turn on the FireSass-compatible debug_info.
|
|
||||||
#firesass = false
|
|
||||||
firesass = false
|
|
||||||
Sass::Plugin.options[:debug_info] = false
|
|
||||||
|
|
||||||
# Location of the theme's resources.
|
|
||||||
css_dir = "css"
|
|
||||||
sass_dir = "sass"
|
|
||||||
fonts_dir = "css/fonts"
|
|
||||||
extensions_dir = "sass-extensions"
|
|
||||||
images_dir = "images"
|
|
||||||
javascripts_dir = "js"
|
|
||||||
cache_path = '/tmp/.sass-cache'
|
|
||||||
|
|
||||||
|
|
||||||
# Require any additional compass plugins installed on your system.
|
|
||||||
require 'autoprefixer-rails'
|
|
||||||
require 'sassy-buttons'
|
|
||||||
require 'breakpoint'
|
|
||||||
require "rgbapng"
|
|
||||||
|
|
||||||
|
|
||||||
# You can select your preferred output style here (can be overridden via the command line):
|
|
||||||
# output_style = :expanded or :nested or :compact or :compressed
|
|
||||||
output_style = (environment == :development) ? :expanded : :compressed
|
|
||||||
|
|
||||||
# To enable relative paths to assets via compass helper functions. Since Drupal
|
|
||||||
# themes can be installed in multiple locations, we don't need to worry about
|
|
||||||
# the absolute path to the theme from the server root.
|
|
||||||
relative_assets = true
|
|
||||||
|
|
||||||
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
|
||||||
line_comments = false
|
|
||||||
|
|
||||||
# Pass options to sass. For development, we turn on the FireSass-compatible
|
|
||||||
# debug_info if the firesass config variable above is true.
|
|
||||||
# sass_options = (environment == :development && firesass == true) ? {:debug_info => true} : {}
|
|
||||||
|
|
||||||
# Run autoprefixer after compass compiles
|
|
||||||
# Using on_stylesheet_saved post-compile hook
|
|
||||||
on_stylesheet_saved do |file|
|
|
||||||
css = File.read(file)
|
|
||||||
File.open(file, 'w') { |io| io << AutoprefixerRails.process(css, browsers: ['> 20%', 'IE 10'], remove: false) }
|
|
||||||
|
|
||||||
cssfile = File.basename file
|
|
||||||
|
|
||||||
# Append sourcemap reference that autoprefixer removed to css file.
|
|
||||||
system( "printf '/*# sourceMappingURL=" + cssfile + ".map */' >> " + File.absolute_path(file) )
|
|
||||||
system( "echo '" + cssfile + ".map sourcemap reference appended to '" + cssfile )
|
|
||||||
system( "echo 'Autoprefixer has processed " + cssfile + "'" )
|
|
||||||
end
|
|
||||||
@@ -1,2 +1,36 @@
|
|||||||
.podcast-channel-header{width:100%;clear:both;display:inline-block;border-bottom:3px solid #000}.podcast-channel-image{width:25%;float:left;display:inline-block;border:1px solid #000}.channel-meta{width:74%;float:left;display:inline-block}.channel-meta h1{text-align:center;margin:0}.channel-meta h2{text-align:center}.channel-meta p.owner{text-align:center;margin:-1em 0 0 0}.channel-meta p.description{margin-left:auto;margin-right:auto;text-align:center;line-height:1.2}.channel-links{float:left;margin-left:2em}.channel-content{display:inline-block}#episodes{display:inline-block;clear:both;width:75%;float:left}#episodes ul{list-style-type:none}.clearfix{clear:both}#podcast-series{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;display:inline-block;background:#ccc;width:24%;float:right;min-height:16em}#podcast-series h2{font-size:20px;text-align:center}#podcast-series a{color:#000}#podcast-series a:hover{font-weight:bold}
|
.episode-container h1,h2{
|
||||||
/*# sourceMappingURL=podcast.css.map */
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.episode-flex-wrapper{
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
}
|
||||||
|
.episode-flex-child {
|
||||||
|
flex: 1;
|
||||||
|
border: 2px solid yellow;
|
||||||
|
padding: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.episode-flex-child h3 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.episode-top {
|
||||||
|
flex: 0 0 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.episode-content {
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
.episode-nav {
|
||||||
|
border-bottom: 1px solid #3A414E;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width:800px){
|
||||||
|
.episode-flex-wrapper{
|
||||||
|
flex-flow: column wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"mappings": "AAQA,uBAAwB,CACpB,KAAK,CAAE,IAAI,CACX,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,aAAa,CAAE,cAAc,CAEjC,sBAAuB,CACnB,KAAK,CAAE,GAAG,CACV,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,cAAc,CAG1B,aAAc,CACV,KAAK,CAAE,GAAG,CACV,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,gBAAG,CACC,UAAU,CAAE,MAAM,CAClB,MAAM,CAAE,CAAC,CAEb,gBAAG,CACC,UAAU,CAAE,MAAM,CAEtB,qBAAQ,CACJ,UAAU,CAAE,MAAM,CAClB,MAAM,CAAE,UAAU,CAGtB,2BAAc,CACV,WAAW,CAAE,IAAI,CACjB,YAAY,CAAE,IAAI,CAClB,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAIxB,cAAe,CACX,KAAK,CAAE,IAAI,CACX,WAAW,CAAE,GAAG,CAIpB,gBAAiB,CACb,OAAO,CAAE,YAAY,CAGzB,SAAU,CACN,OAAO,CAAE,YAAY,CACrB,KAAK,CAAE,IAAI,CACX,KAAK,CAAE,GAAG,CACV,KAAK,CAAE,IAAI,CACX,YAAG,CACC,eAAe,CAAE,IAAI,CAI7B,SAAU,CACN,KAAK,CAAE,IAAI,CAGf,eAAgB,CCuRd,kBAAwC,CDtRf,GAAG,CCsR5B,qBAAwC,CC9Sb,GAAuB,CD8SlD,aAAwC,CDtRf,GAAG,CAC1B,OAAO,CAAE,YAAY,CACrB,UAAU,CAlEM,IAAI,CAmEpB,KAAK,CAAE,GAAG,CACV,KAAK,CAAE,KAAK,CACZ,UAAU,CAAE,IAAI,CAChB,kBAAG,CACC,SAAS,CAAE,IAAI,CACf,UAAU,CAAE,MAAM,CAEtB,iBAAE,CACE,KAAK,CA5EO,IAAI,CA8EpB,uBAAQ,CACJ,WAAW,CAAE,IAAI",
|
|
||||||
"sources": ["../sass/podcast.scss","../../../../../../../../../xampp/ruby/lib/ruby/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../../../../../../xampp/ruby/lib/ruby/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss"],
|
|
||||||
"names": [],
|
|
||||||
"file": "podcast.css"
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/* Styling for podcast related content */
|
|
||||||
@import "compass/css3";
|
|
||||||
@import "compass/utilities";
|
|
||||||
|
|
||||||
|
|
||||||
$series-foreground: #000;
|
|
||||||
$series-background: #ccc;
|
|
||||||
|
|
||||||
.podcast-channel-header {
|
|
||||||
width: 100%;
|
|
||||||
clear: both;
|
|
||||||
display: inline-block;
|
|
||||||
border-bottom: 3px solid #000;
|
|
||||||
}
|
|
||||||
.podcast-channel-image {
|
|
||||||
width: 25%;
|
|
||||||
float: left;
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-meta {
|
|
||||||
width: 74%;
|
|
||||||
float: left;
|
|
||||||
display: inline-block;
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
p.owner {
|
|
||||||
text-align: center;
|
|
||||||
margin: -1em 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.description {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.channel-links {
|
|
||||||
float: left;
|
|
||||||
margin-left: 2em;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-content {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#episodes {
|
|
||||||
display: inline-block;
|
|
||||||
clear: both;
|
|
||||||
width: 75%;
|
|
||||||
float: left;
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.clearfix {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
#podcast-series {
|
|
||||||
@include border-radius(2px);
|
|
||||||
display: inline-block;
|
|
||||||
background: $series-background;
|
|
||||||
width: 24%;
|
|
||||||
float: right;
|
|
||||||
min-height: 16em;
|
|
||||||
h2 {
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: $series-foreground;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: Podcast
|
name: Podcast
|
||||||
version: 2.1.10
|
version: 3.0.0
|
||||||
description: Creates Podcast page types and related podcast RSS feeds
|
description: Creates Podcast page types and related podcast RSS feeds
|
||||||
icon: microphone
|
icon: microphone
|
||||||
author:
|
author:
|
||||||
@@ -12,6 +12,7 @@ docs: https://github.com/jgonyea/grav-plugin-podcast/blob/develop/README.md
|
|||||||
license: MIT
|
license: MIT
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
- admin
|
||||||
- auto-date
|
- auto-date
|
||||||
- feed
|
- feed
|
||||||
- get-id3
|
- get-id3
|
||||||
@@ -29,8 +30,3 @@ form:
|
|||||||
0: PLUGIN_ADMIN.DISABLED
|
0: PLUGIN_ADMIN.DISABLED
|
||||||
validate:
|
validate:
|
||||||
type: bool
|
type: bool
|
||||||
max_upload:
|
|
||||||
type: text
|
|
||||||
label: PLUGIN_PODCAST.CONFIG.MAX_UPLOAD_LABEL
|
|
||||||
help: PLUGIN_PODCAST.CONFIG.MAX_UPLOAD_HELP
|
|
||||||
default: 50
|
|
||||||
|
|||||||
@@ -12,13 +12,11 @@ form:
|
|||||||
content:
|
content:
|
||||||
type: tab
|
type: tab
|
||||||
ordering@: 0
|
ordering@: 0
|
||||||
title: Podcast Page Content
|
title: PLUGIN_PODCAST.ADMIN.CHANNEL.CONTENT.TAB_TITLE
|
||||||
fields:
|
fields:
|
||||||
header.media_order:
|
|
||||||
unset@: true
|
|
||||||
header.title:
|
header.title:
|
||||||
type: text
|
type: text
|
||||||
label: Page Title
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CONTENT.PAGE_TITLE_LABEL
|
||||||
|
|
||||||
header.feed.rss:
|
header.feed.rss:
|
||||||
type: hidden
|
type: hidden
|
||||||
@@ -30,84 +28,84 @@ form:
|
|||||||
channelMetaTab:
|
channelMetaTab:
|
||||||
type: tab
|
type: tab
|
||||||
ordering@: 1
|
ordering@: 1
|
||||||
title: Channel Meta
|
title: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.TAB_TITLE
|
||||||
fields:
|
fields:
|
||||||
helptext:
|
helptext:
|
||||||
type: spacer
|
type: spacer
|
||||||
title:
|
title:
|
||||||
text: Metadata related to the podcast's channel section.
|
text: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.TAB_HELPTEXT
|
||||||
underline: true
|
underline: true
|
||||||
uploads:
|
|
||||||
unset@: true
|
|
||||||
header.podcast.title:
|
header.podcast.title:
|
||||||
type: text
|
type: text
|
||||||
label: Podcast Title
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_TITLE_LABEL
|
||||||
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_TITLE_HELPTEXT
|
||||||
header.podcast.itunes.subtitle:
|
header.podcast.itunes.subtitle:
|
||||||
type: text
|
type: text
|
||||||
label: iTunes Subtitle
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_SUBTITLE_LABEL
|
||||||
help: 'Example: "A show about everything..."'
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_SUBTITLE_HELPTEXT
|
||||||
header.podcast.description:
|
header.podcast.description:
|
||||||
type: markdown
|
type: markdown
|
||||||
label: Channel Description
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_DESCRIPTION_LABEL
|
||||||
ordering@: 0
|
|
||||||
header.podcast.link:
|
header.podcast.link:
|
||||||
type: text
|
type: text
|
||||||
label: Channel URL
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_LINK_LABEL
|
||||||
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_LINK_HELPTEXT
|
||||||
default: 'https://www.example.com'
|
default: 'https://www.example.com'
|
||||||
header.podcast.channelLanguage:
|
header.podcast.channelLanguage:
|
||||||
type: select
|
type: select
|
||||||
label: Channel Language
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_LANG_LABEL
|
||||||
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_LANG_HELPTEXT
|
||||||
default: 'en'
|
default: 'en'
|
||||||
data-options@: '\Grav\Plugin\PodcastPlugin::getLanguageOptions'
|
data-options@: '\Grav\Plugin\PodcastPlugin::getLanguageOptions'
|
||||||
header.podcast.copyright:
|
header.podcast.copyright:
|
||||||
type: text
|
type: text
|
||||||
label: Copyright
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.CHANNEL_META.PODCAST_COPYRIGHT_LABEL
|
||||||
default: 2017 Example.com
|
default: 2021 Example.com
|
||||||
|
|
||||||
itunesMetaTab:
|
itunesMetaTab:
|
||||||
type: tab
|
type: tab
|
||||||
ordering@: 2
|
ordering@: 2
|
||||||
title: iTunes Meta
|
title: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.TAB_TITLE
|
||||||
fields:
|
fields:
|
||||||
helptext:
|
helptext:
|
||||||
type: spacer
|
type: spacer
|
||||||
title:
|
title:
|
||||||
text: Metadata related to the podcast's itunes section.
|
text: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.TAB_HELPTEXT
|
||||||
underline: true
|
underline: true
|
||||||
header.podcast.itunes.author:
|
header.podcast.itunes.author:
|
||||||
type: text
|
type: text
|
||||||
label: Author
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_AUTHOR_LABEL
|
||||||
help: 'Example: "John Doe"'
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_AUTHOR_HELPTEXT
|
||||||
header.podcast.itunes.owner.name:
|
header.podcast.itunes.owner.name:
|
||||||
type: text
|
type: text
|
||||||
label: Owner Name
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_OWNER_LABEL
|
||||||
help: 'Example: "John Doe"'
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_OWNER_HELPTEXT
|
||||||
header.podcast.itunes.owner.email:
|
header.podcast.itunes.owner.email:
|
||||||
type: email
|
type: email
|
||||||
label: Owner Email
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_OWNER_EMAIL_LABEL
|
||||||
help: 'Example: "jdoe@example.com"'
|
help: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_OWNER_EMAIL_HELPTEXT
|
||||||
header.podcast.itunes.image:
|
header.podcast.itunes.image:
|
||||||
type: file
|
type: filepicker
|
||||||
label: Channel Image
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_IMAGE_LABEL
|
||||||
destination: 'self@'
|
|
||||||
multiple: false
|
|
||||||
fileszie: 5
|
|
||||||
accept:
|
accept:
|
||||||
- image/*
|
- .bmp
|
||||||
|
- .png
|
||||||
|
- .jpg
|
||||||
|
- .jpeg
|
||||||
header.podcast.itunes.category:
|
header.podcast.itunes.category:
|
||||||
type: select
|
type: select
|
||||||
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_CATEGORY_LABEL
|
||||||
size: long
|
size: long
|
||||||
classes: fancy
|
classes: fancy
|
||||||
label: Category
|
|
||||||
data-options@: '\Grav\Plugin\PodcastPlugin::getCategoryOptions'
|
data-options@: '\Grav\Plugin\PodcastPlugin::getCategoryOptions'
|
||||||
header.podcast.itunes.subcategory:
|
header.podcast.itunes.subcategory:
|
||||||
type: select
|
type: select
|
||||||
label: Sub-Category
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_SUBCATEGORY_LABEL
|
||||||
data-options@: '\Grav\Plugin\PodcastPlugin::getSubCategoryOptions'
|
data-options@: '\Grav\Plugin\PodcastPlugin::getSubCategoryOptions'
|
||||||
|
|
||||||
header.podcast.itunes.explicit:
|
header.podcast.itunes.explicit:
|
||||||
type: toggle
|
type: toggle
|
||||||
label: Explicit Content
|
label: PLUGIN_PODCAST.ADMIN.CHANNEL.ITUNES_META.ITUNES_EXPLICIT_LABEL
|
||||||
highlight: 0
|
highlight: 0
|
||||||
default: no
|
default: no
|
||||||
help: Does this podcast contain content that might be inappropriate for children?
|
help: Does this podcast contain content that might be inappropriate for children?
|
||||||
|
|||||||
@@ -11,78 +11,75 @@ form:
|
|||||||
fields:
|
fields:
|
||||||
content:
|
content:
|
||||||
type: tab
|
type: tab
|
||||||
title: Podcast
|
title: PLUGIN_PODCAST.ADMIN.EPISODE.CONTENT.TAB_TITLE
|
||||||
fields:
|
fields:
|
||||||
header.title:
|
header.title:
|
||||||
ordering@: 1
|
ordering@: 1
|
||||||
type: text
|
type: text
|
||||||
label: Episode Title
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.CONTENT.PAGE_TITLE_LABEL
|
||||||
header.subtitle:
|
header.podcast.itunes.subtitle:
|
||||||
ordering@: 2
|
ordering@: 2
|
||||||
type: text
|
type: text
|
||||||
label: Episode subtitle
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.CONTENT.SUBTITLE_LABEL
|
||||||
header.podcast.episode_number:
|
header.podcast.episode_number:
|
||||||
ordering@: 3
|
ordering@: 3
|
||||||
type: text
|
type: text
|
||||||
label: Episode number
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.CONTENT.EPISODE_NUMBER_LABEL
|
||||||
size: x-small
|
size: x-small
|
||||||
header.media_order:
|
|
||||||
unset@: true
|
|
||||||
podcastAudio:
|
podcastAudio:
|
||||||
type: tab
|
type: tab
|
||||||
title: Podcast Audio
|
title: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.TAB_TITLE
|
||||||
ordering@: 1
|
ordering@: 1
|
||||||
fields:
|
fields:
|
||||||
locally_hosted:
|
locally_hosted:
|
||||||
type: spacer
|
type: spacer
|
||||||
title: Locally Hosted Files
|
title: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.LOCAL_HOSTED_LABEL
|
||||||
text: If you host your audio files on <strong>this</strong> server, upload the media below
|
text: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.LOVAL_HOSTED_HELPTEXT
|
||||||
header.podcast.audio.local:
|
header.podcast.audio.local.select:
|
||||||
type: file
|
type: filepicker
|
||||||
label: Local Podcast Audio
|
label: Local Podcast Audio
|
||||||
destination: '@self'
|
|
||||||
multiple: false
|
|
||||||
config-filesize@: plugins.podcast.max_upload
|
|
||||||
limit: 1
|
|
||||||
accept:
|
accept:
|
||||||
- 'audio/*'
|
- .mp3
|
||||||
|
- .wav
|
||||||
|
- .ogg
|
||||||
external_cdn:
|
external_cdn:
|
||||||
type: spacer
|
type: spacer
|
||||||
title: External Files
|
title: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.EXTERNAL_HOSTED_LABEL
|
||||||
text: If you host your audio files on <strong>another</strong> server/CDN, fill in the field below
|
text: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.EXTERNAL_HOSTED_HELPTEXT
|
||||||
header.podcast.audio.remote:
|
header.podcast.audio.remote:
|
||||||
type: text
|
type: text
|
||||||
label: Remote Podcast URL
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.EXTERNAL_URL_LABEL
|
||||||
help: Remote files will take precendence over locally hosted when viewed on a page.
|
help: PLUGIN_PODCAST.ADMIN.EPISODE.PODCAST_AUDIO.EXTERNAL_URL_HELPTEXT
|
||||||
itunesMetaTab:
|
itunesMetaTab:
|
||||||
type: tab
|
type: tab
|
||||||
ordering@: 2
|
ordering@: 2
|
||||||
title: iTunes Episode Meta
|
title: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.TAB_TITLE
|
||||||
fields:
|
fields:
|
||||||
helptext:
|
helptext:
|
||||||
type: spacer
|
type: spacer
|
||||||
title:
|
text: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.TAB_HELPTEXT
|
||||||
text: Metadata related to the podcast episode
|
|
||||||
underline: true
|
underline: true
|
||||||
header.podcast.itunes.author:
|
header.podcast.itunes.author:
|
||||||
type: text
|
type: text
|
||||||
label: Episode Author
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.AUTHOR_LABEL
|
||||||
help: 'Example: "John Doe"'
|
help: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.AUTHOR_HELPTEXT
|
||||||
header.podcast.itunes.image:
|
header.podcast.itunes.image:
|
||||||
type: file
|
type: filepicker
|
||||||
label: Episode Image
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.IMAGE_LABEL
|
||||||
destination: 'self@'
|
help: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.IMAGE_HELPTEXT
|
||||||
multiple: false
|
|
||||||
filesize: 5
|
|
||||||
accept:
|
accept:
|
||||||
- image/*
|
- .png
|
||||||
|
- .bmp
|
||||||
|
- .jpeg
|
||||||
|
- .jpg
|
||||||
header.podcast.itunes.explicit:
|
header.podcast.itunes.explicit:
|
||||||
type: toggle
|
type: toggle
|
||||||
label: Explicit Content
|
label: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.EXPLICIT_LABEL
|
||||||
highlight: 0
|
help: PLUGIN_PODCAST.ADMIN.EPISODE.ITUNES_META.EXPLICIT_HELPTEXT
|
||||||
default: no
|
default: no
|
||||||
help: Does this podcast contain content that might be inappropriate for children?
|
|
||||||
options:
|
options:
|
||||||
yes: Yes
|
yes: PLUGIN_ADMIN.YES
|
||||||
no: No
|
no: PLUGIN_ADMIN.NO
|
||||||
|
validate:
|
||||||
|
type: bool
|
||||||
|
|
||||||
|
|||||||
@@ -12,27 +12,24 @@ form:
|
|||||||
content:
|
content:
|
||||||
type: tab
|
type: tab
|
||||||
ordering@: 0
|
ordering@: 0
|
||||||
title: Podcast Series Content
|
title: PLUGIN_PODCAST.ADMIN.SERIES.CONTENT.TAB_TITLE
|
||||||
fields:
|
fields:
|
||||||
header.media_order:
|
|
||||||
unset@: true
|
|
||||||
header.title:
|
header.title:
|
||||||
type: text
|
type: text
|
||||||
label: Series Title
|
label: PLUGIN_PODCAST.ADMIN.SERIES.CONTENT.PAGE_TITLE_LABEL
|
||||||
|
|
||||||
header.feed.rss:
|
header.feed.rss:
|
||||||
type: hidden
|
type: hidden
|
||||||
default: 'true'
|
default: 'true'
|
||||||
header.feed.items:
|
header.feed.items:
|
||||||
type: hidden
|
type: hidden
|
||||||
default: '@self.children'
|
default: '@self.children'
|
||||||
|
|
||||||
header.series.image:
|
header.series.image:
|
||||||
type: file
|
type: filepicker
|
||||||
@ordering: 2
|
label: PLUGIN_PODCAST.ADMIN.SERIES.CONTENT.SERIES_IMAGE_LABEL
|
||||||
label: Series Image
|
help: PLUGIN_PODCAST.ADMIN.SERIES.CONTENT.SERIES_IMAGE_HELPTEXT
|
||||||
destination: 'self@'
|
ordering@: 2
|
||||||
multiple: false
|
|
||||||
fileszie: 5
|
|
||||||
accept:
|
accept:
|
||||||
- image/*
|
- .png
|
||||||
|
- .bmp
|
||||||
|
- .jpg
|
||||||
|
- .jpeg
|
||||||
|
|||||||
@@ -4,4 +4,70 @@ en:
|
|||||||
MAX_UPLOAD_LABEL: Max Podcast Filesize (MB)
|
MAX_UPLOAD_LABEL: Max Podcast Filesize (MB)
|
||||||
MAX_UPLOAD_HELP: 'Set "upload_max_filesize" and "post_max_size" in php.ini to at least this value or higher.'
|
MAX_UPLOAD_HELP: 'Set "upload_max_filesize" and "post_max_size" in php.ini to at least this value or higher.'
|
||||||
PODCAST: Podcast Channel
|
PODCAST: Podcast Channel
|
||||||
SERIES: Podcast Series
|
SERIES: Podcast Series
|
||||||
|
EPISODE_CONTENT:
|
||||||
|
HEADER: Episode Content
|
||||||
|
DOWNLOAD: Download Audio
|
||||||
|
WARNING: Your browser does not support the audio tag.
|
||||||
|
OTHER: Other Episodes In
|
||||||
|
ADMIN:
|
||||||
|
CHANNEL:
|
||||||
|
CONTENT:
|
||||||
|
TAB_TITLE: Podcast Page Content
|
||||||
|
PAGE_TITLE_LABEL: Page Title
|
||||||
|
CHANNEL_META:
|
||||||
|
TAB_TITLE: Channel Meta
|
||||||
|
TAB_HELPTEXT: Metadata related to the podcast's channel section.
|
||||||
|
PODCAST_TITLE_LABEL: Podcast Title
|
||||||
|
PODCAST_TITLE_HELPTEXT: Used in the RSS feed.
|
||||||
|
PODCAST_SUBTITLE_LABEL: iTunes Subtitle
|
||||||
|
PODCAST_SUBTITLE_HELPTEXT: 'Example: "A show about everything..."'
|
||||||
|
PODCAST_DESCRIPTION_LABEL: Channel Description
|
||||||
|
PODCAST_LINK_LABEL: Channel URL
|
||||||
|
PODCAST_LINK_HELPTEXT: Used in the RSS feed.
|
||||||
|
PODCAST_LANG_LABEL: Channel Language
|
||||||
|
PODCAST_LANG_HELPTEXT: Used only for the RSS feed.
|
||||||
|
PODCAST_COPYRIGHT_LABEL: Copyright
|
||||||
|
ITUNES_META:
|
||||||
|
TAB_TITLE: iTunes Meta
|
||||||
|
TAB_HELPTEXT: Metadata related to the podcast's iTunes section.
|
||||||
|
ITUNES_AUTHOR_LABEL: Author
|
||||||
|
ITUNES_AUTHOR_HELPTEXT: 'Example: "John Doe"'
|
||||||
|
ITUNES_OWNER_LABEL: Owner
|
||||||
|
ITUNES_OWNER_HELPTEXT: 'Example: "John Doe"'
|
||||||
|
ITUNES_OWNER_EMAIL_LABEL: Owner Email
|
||||||
|
ITUNES_OWNER_EMAIL_HELPTEXT: 'Example: "jdoe@example.com"'
|
||||||
|
ITUNES_IMAGE_LABEL: Channel Image
|
||||||
|
ITUNES_CATEGORY_LABEL: Category
|
||||||
|
ITUNES_SUBCATEGORY_LABEL: Sub-Category
|
||||||
|
ITUNES_EXPLICIT_LABEL: Explicit Content
|
||||||
|
ITUNES_EXPLICIT_HELPTEXT: Does this podcast contain content that might be inappropriate for children?
|
||||||
|
SERIES:
|
||||||
|
CONTENT:
|
||||||
|
TAB_TITLE: Podcast Series Content
|
||||||
|
PAGE_TITLE_LABEL: Series Title
|
||||||
|
SERIES_IMAGE_LABEL: Series Image
|
||||||
|
SERIES_IMAGE_HELPTEXT: Upload and save images below in the Page Media field. Then select one in this dropdown to act as the series main image.
|
||||||
|
EPISODE:
|
||||||
|
CONTENT:
|
||||||
|
TAB_TITLE: Podcast Episode
|
||||||
|
PAGE_TITLE_LABEL: Episode Title
|
||||||
|
SUBTITLE_LABEL: Episode Title
|
||||||
|
EPISODE_NUMBER_LABEL: Episode Number
|
||||||
|
PODCAST_AUDIO:
|
||||||
|
TAB_TITLE: Podcast Audio
|
||||||
|
LOCAL_HOSTED_LABEL: Locally Hosted Files
|
||||||
|
LOVAL_HOSTED_HELPTEXT: If you host your audio files on <strong>this</strong> server, upload the media on the Podcast tab.
|
||||||
|
EXTERNAL_HOSTED_LABEL: External Files
|
||||||
|
EXTERNAL_HOSTED_HELPTEXT: If you host your audio files on <strong>another</strong> server/CDN, fill in the field below
|
||||||
|
EXTERNAL_URL_LABEL: Remote Podcast URL
|
||||||
|
EXTERNAL_URL_HELPTEXT: Remote files will take precendence over locally hosted when viewed on a page.
|
||||||
|
ITUNES_META:
|
||||||
|
TAB_TITLE: iTunes Episode Meta
|
||||||
|
TAB_HELPTEXT: Metadata related to the podcast episode
|
||||||
|
AUTHOR_LABEL: Episode Author
|
||||||
|
AUTHOR_HELPTEXT: 'Example: "John Doe"'
|
||||||
|
IMAGE_LABEL: Episode Image
|
||||||
|
IMAGE_HELPTEXT: Upload and save images below in the Page Media field on the Podcast Episode tab. Then select one in this dropdown to act as the series main image.
|
||||||
|
EXPLICIT_LABEL: Explicit Content
|
||||||
|
EXPLICIT_HELPTEXT: Does this podcast contain content that might be inappropriate for children?
|
||||||
|
|||||||
82
podcast.php
82
podcast.php
@@ -75,30 +75,49 @@ class PodcastPlugin extends Plugin
|
|||||||
$this->grav['assets']
|
$this->grav['assets']
|
||||||
->addCss('plugin://podcast/assets/css/podcast.css');
|
->addCss('plugin://podcast/assets/css/podcast.css');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the page header being saved to include getID3 metadata.
|
||||||
|
*/
|
||||||
public function onAdminSave($event)
|
public function onAdminSave($event)
|
||||||
{
|
{
|
||||||
$obj = $event['object'];
|
$obj = $event['object'];
|
||||||
// Process only podcast episodes page types.
|
// Process only podcast episodes page types.
|
||||||
if (!($obj instanceof \Grav\Common\Page\Page) || $obj->template() != 'podcast-episode') {
|
$obj_class = get_class($obj);
|
||||||
|
if (($obj_class != 'Grav\Common\Page\Page' && $obj_class != 'Grav\Common\Flex\Types\Pages\PageObject') || $obj->template() != 'podcast-episode') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$header = $obj->header();
|
$header = $obj->header();
|
||||||
|
|
||||||
// Use local file for meta calculations, if present.
|
// Use local file for meta calculations, if present.
|
||||||
// Else use remote file for meta, if present.
|
// Else, use remote file for meta, if present.
|
||||||
// Else cleanup media entry in markdown header.
|
// Else, cleanup media entry in markdown header.
|
||||||
|
|
||||||
if (isset($header->podcast['audio']['local'])) {
|
if (isset($header->podcast['audio']['local']['select'])) {
|
||||||
// Create a temporary array to perform the array_shift on.
|
$local['select'] = $header->podcast['audio']['local']['select'];
|
||||||
$local_audio = $header->podcast['audio']['local'];
|
$media = $obj->media()->audios()[$local['select']];
|
||||||
$local_audio = array_shift($local_audio);
|
|
||||||
|
// Create array for backawards compatability with Grav content created with < v1.7.
|
||||||
$audio_meta['guid'] = $local_audio['path'];
|
$audio = $header->podcast['audio'];
|
||||||
$audio_meta['type'] = $this->retreiveAudioType($audio_meta['guid']);
|
$file_path = $media->relativePath();
|
||||||
$audio_meta['duration'] = $this->retreiveAudioDuration($audio_meta['guid']);
|
//$file_url = $obj->getRoute()->getUri()->getPath() . DS . $local['select'];
|
||||||
$audio_meta['enclosure_length'] = filesize($audio_meta['guid']);
|
$file_url = $obj->getRoute()->getRootPrefix();
|
||||||
|
$file_url .= DS . implode('/', $obj->getRoute()->getRouteParts());
|
||||||
|
$file_url .= DS . $local['select'];
|
||||||
|
|
||||||
|
$audio_meta['guid'] = $file_url;
|
||||||
|
$audio_meta['type'] = $this->retreiveAudioType($file_path);
|
||||||
|
$audio_meta['duration'] = $this->retreiveAudioDuration($file_path);
|
||||||
|
$audio_meta['enclosure_length'] = filesize($file_path);
|
||||||
|
|
||||||
|
$local_file = [
|
||||||
|
'name' => $local['select'],
|
||||||
|
'type' => $audio_meta['type'],
|
||||||
|
'size' => $audio_meta['enclosure_length'],
|
||||||
|
'path' => $file_url,
|
||||||
|
];
|
||||||
|
$local[$file_path] = $local_file;
|
||||||
|
$header->offsetSet('podcast.audio.local', $local);
|
||||||
}
|
}
|
||||||
if (isset($header->podcast['audio']['remote']) && !isset($audio_meta)) {
|
if (isset($header->podcast['audio']['remote']) && !isset($audio_meta)) {
|
||||||
// Download fle from external url to temporary location.
|
// Download fle from external url to temporary location.
|
||||||
@@ -117,27 +136,24 @@ class PodcastPlugin extends Plugin
|
|||||||
unset($header->podcast['audio']['meta']);
|
unset($header->podcast['audio']['meta']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the guid if using an external file source.
|
// Reset the guid if using an external file source.
|
||||||
if (isset($header->podcast['audio']['remote']) && isset($header->podcast['audio']['meta'])) {
|
if (isset($header->podcast['audio']['remote']) && isset($header->podcast['audio']['meta'])) {
|
||||||
$audio_meta['guid'] = $header->podcast['audio']['remote'];
|
$audio_meta['guid'] = $header->podcast['audio']['remote'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare $obj to return new header data.
|
// Prepare $obj to return new header data.
|
||||||
|
$new_header = $header->toArray();
|
||||||
if (isset($audio_meta)) {
|
if (isset($audio_meta)) {
|
||||||
$header->podcast['audio']['meta'] = $audio_meta;
|
$new_header['podcast']['audio']['meta'] = $audio_meta;
|
||||||
} else {
|
} else {
|
||||||
// Cleanup any leftover data if neither local or remote file are set.
|
// Cleanup any leftover data if neither local or remote file are set.
|
||||||
if (isset($header->podcast['audio']['meta'])) {
|
unset($new_header['podcast']['audio']);
|
||||||
unset($header->podcast['audio']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$obj->header($header);
|
$obj->header($new_header);
|
||||||
|
|
||||||
return $obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve audio metadata filesize.
|
* Retrieve audio metadata filesize.
|
||||||
*
|
*
|
||||||
@@ -165,7 +181,7 @@ class PodcastPlugin extends Plugin
|
|||||||
$id3 = GetID3Plugin::analyzeFile($file);
|
$id3 = GetID3Plugin::analyzeFile($file);
|
||||||
return ($id3['mime_type']);
|
return ($id3['mime_type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve audio metadata duration.
|
* Retrieve audio metadata duration.
|
||||||
*
|
*
|
||||||
@@ -197,7 +213,7 @@ class PodcastPlugin extends Plugin
|
|||||||
curl_exec($ch);
|
curl_exec($ch);
|
||||||
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
// $retcode >= 400 -> not found; 200 -> found; 0 -> server not found.
|
// $retcode >= 400 -> not found; 200 -> found; 0 -> server not found.
|
||||||
if ($retcode >= 400 || $retcode == 0) {
|
if ($retcode >= 400 || $retcode == 0) {
|
||||||
$grav_messages = $this->grav['messages'];
|
$grav_messages = $this->grav['messages'];
|
||||||
@@ -205,21 +221,21 @@ class PodcastPlugin extends Plugin
|
|||||||
$grav_messages->add("Audio File metadata calculation failed!", 'error');
|
$grav_messages->add("Audio File metadata calculation failed!", 'error');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download file to temp location.
|
// Download file to temp location.
|
||||||
if ($remote_file = fopen($url, 'rb')) {
|
if ($remote_file = fopen($url, 'rb')) {
|
||||||
$local_file = tempnam('/tmp', 'podcast');
|
$local_file = tempnam('/tmp', 'podcast');
|
||||||
$handle = fopen($local_file, "w");
|
$handle = fopen($local_file, "w");
|
||||||
$contents = stream_get_contents($remote_file);
|
$contents = stream_get_contents($remote_file);
|
||||||
|
|
||||||
fwrite($handle, $contents);
|
fwrite($handle, $contents);
|
||||||
fclose($remote_file);
|
fclose($remote_file);
|
||||||
fclose($handle);
|
fclose($handle);
|
||||||
|
|
||||||
return $local_file;
|
return $local_file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds list of available iTunes categories.
|
* Finds list of available iTunes categories.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
enabled: true
|
enabled: true
|
||||||
max_upload: 50
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<itunes:name>{{ channel.header.podcast.itunes.owner.name }}</itunes:name>
|
<itunes:name>{{ channel.header.podcast.itunes.owner.name }}</itunes:name>
|
||||||
<itunes:email>{{ channel.header.podcast.itunes.owner.email }}</itunes:email>
|
<itunes:email>{{ channel.header.podcast.itunes.owner.email }}</itunes:email>
|
||||||
</itunes:owner>
|
</itunes:owner>
|
||||||
<itunes:image href="{{ base_url_absolute}}/{{ ((channel.header.podcast.itunes.image)|first.path) }}"/>
|
<itunes:image href="{{ uri.base }}{{ channel.media[page.header.podcast.itunes.image].url(true) }}"/>
|
||||||
<itunes:category text="{{ channel.header.podcast.itunes.category }}">
|
<itunes:category text="{{ channel.header.podcast.itunes.category }}">
|
||||||
<itunes:category text="{{ channel.header.podcast.itunes.subcategory }}"/>
|
<itunes:category text="{{ channel.header.podcast.itunes.subcategory }}"/>
|
||||||
</itunes:category>
|
</itunes:category>
|
||||||
@@ -31,23 +31,23 @@
|
|||||||
<item>
|
<item>
|
||||||
<title>{{ episode.title }}</title>
|
<title>{{ episode.title }}</title>
|
||||||
<link>{{ episode.url(true) }}</link>
|
<link>{{ episode.url(true) }}</link>
|
||||||
{% if episode.header.podcast.episode_number %}
|
{% if episode.header.podcast.episode_number -%}
|
||||||
<itunes:episode>{{ episode.header.podcast.episode_number }}</itunes:episode>
|
<itunes:episode>{{ episode.header.podcast.episode_number }}</itunes:episode>
|
||||||
{% endif %}
|
{% endif -%}
|
||||||
<itunes:author>{{ episode.header.podcast.itunes.author }}</itunes:author>
|
<itunes:author>{{ episode.header.podcast.itunes.author }}</itunes:author>
|
||||||
<itunes:subtitle>{{ episdoe.header.podcast.subtitle }}</itunes:subtitle>
|
<itunes:subtitle>{{ episode.header.podcast.itunes.subtitle }}</itunes:subtitle>
|
||||||
<itunes:summary>{{episode.content|striptags|truncate(120, true, " ", "…")}}</itunes:summary>
|
<itunes:summary>{{ episode.content|striptags|truncate(120, true, " ", "…")}}</itunes:summary>
|
||||||
<itunes:image href="{{base_url_absolute}}/{{ (episode.header.podcast.itunes.image)|first.path|absolute_url }}"/>
|
<itunes:image href="{{ uri.base }}/{{ episode.media[episode.header.podcast.itunes.image].url(true) }}"/>
|
||||||
{% if (episode.header.podcast.audio.remote) %}
|
{% if ( episode.header.podcast.audio.remote ) -%}
|
||||||
<enclosure length="{{episode.header.podcast.audio.meta.enclosure_length}}" type="{{episode.header.podcast.audio.meta.type}}" url="{{episode.header.podcast.audio.remote}}"/>
|
<enclosure length="{{ episode.header.podcast.audio.meta.enclosure_length }}" type="{{ episode.header.podcast.audio.meta.type }}" url="{{ episode.header.podcast.audio.remote }}"/>
|
||||||
<guid>{{episode.header.podcast.audio.remote}}</guid>
|
<guid>{{ episode.header.podcast.audio.remote }}</guid>
|
||||||
{% else %}
|
{% else -%}
|
||||||
<enclosure length="{{episode.header.podcast.audio.meta.enclosure_length}}" type="{{episode.header.podcast.audio.meta.type}}" url="{{base_url_absolute}}/{{episode.header.podcast.audio.meta.guid|absolute_url}}"/>
|
<enclosure length="{{ episode.header.podcast.audio.meta.enclosure_length }}" type="{{ episode.header.podcast.audio.meta.type }}" url="{{ uri.base }}{{ episode.header.podcast.audio.meta.guid }}"/>
|
||||||
<guid>{{base_url_absolute}}/{{episode.header.podcast.audio.meta.guid|absolute_url}}</guid>
|
<guid>{{ uri.base }}{{ episode.header.podcast.audio.meta.guid }}</guid>
|
||||||
{% endif %}
|
{% endif -%}
|
||||||
<pubDate>{{ episode.header.publish_date ? episode.header.publish_date|date('r') : episode.date|date('r')}}</pubDate>
|
<pubDate>{{ episode.header.publish_date ? episode.header.publish_date|date('r') : episode.date|date('r') }}</pubDate>
|
||||||
<itunes:duration>{{episode.header.podcast.audio.meta.duration}}</itunes:duration>
|
<itunes:duration>{{ episode.header.podcast.audio.meta.duration }}</itunes:duration>
|
||||||
<itunes:explicit>{{episode.header.podcast.itunes.explicit}}</itunes:explicit>
|
<itunes:explicit>{{ episode.header.podcast.itunes.explicit }}</itunes:explicit>
|
||||||
</item>
|
</item>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div id = "episodes">
|
<div id = "episodes">
|
||||||
|
{% if (episodes|length > 0)%}
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
{% for episode in episodes %}
|
{% for episode in episodes %}
|
||||||
<li>
|
<li>
|
||||||
<div class="episode-image">
|
<div class="episode-image">
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p class = "episode-date">
|
<p class="episode-date">
|
||||||
{{ (episode.modified)|date('Y-m-d')|nicetime(false) }}
|
{{ (episode.modified)|date('Y-m-d')|nicetime(false) }}
|
||||||
</p>
|
</p>
|
||||||
<p class = "episode-description">
|
<p class="episode-description">
|
||||||
{% if episode.summary %}
|
{% if episode.summary %}
|
||||||
{{ (episode.summary)|striptags|truncate(120) }}
|
{{ (episode.summary)|striptags|truncate(120) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -31,16 +31,15 @@
|
|||||||
</p>
|
</p>
|
||||||
{% if episode.header.podcast.audio.meta %}
|
{% if episode.header.podcast.audio.meta %}
|
||||||
<p class = "podcast-episode-audio">
|
<p class = "podcast-episode-audio">
|
||||||
{% if episode.header.podcast.audio.remote is null or episode.header.podcast.audio.remote is empty %}
|
<audio controls="1" alt="episode.title"><source src="{{ episode.header.podcast.audio.meta.guid }}">Your browser does not support the audio tag.</audio>
|
||||||
{% set media_url = base_url ~ "/" ~ episode.header.podcast.audio.meta.guid %}
|
<br/><a href ="{{ episode.header.podcast.audio.meta.guid }}">Download Audio</a>
|
||||||
{% else %}
|
|
||||||
{% set media_url = episode.header.podcast.audio.meta.guid %}
|
|
||||||
{% endif %}
|
|
||||||
<audio controls="1" alt="episode.title"><source src="{{media_url}}">Your browser does not support the audio tag.</audio>
|
|
||||||
<br/><a href ="{{media_url}}">Download Audio</a>
|
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p> No episodes </p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
12
templates/partials/podcast_episodes_mini_list.html.twig
Normal file
12
templates/partials/podcast_episodes_mini_list.html.twig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{% set mini_episodes = page.parent.children() %}
|
||||||
|
<div class="episodes-mini-list">
|
||||||
|
<h3>{{ 'PLUGIN_PODCAST.EPISODE_CONTENT.OTHER'|t|e }} '{{ page.parent.title }}'</h3>
|
||||||
|
<ul>
|
||||||
|
{% for e in mini_episodes|slice(0, 5) %}
|
||||||
|
<li><a href="{{ e.url() }}">{{ e.title }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
{% if (mini_episodes|length > 1) %}
|
||||||
|
<li><a href="{{page.parent.url()}}">More >></a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
{% for s in series %}
|
{% for s in series %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{base_url_simple}}{{ s.route }}">{{ s.title }}</a>
|
<a href="{{ base_url }}{{ s.route }}">{{ s.title }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,23 +1,46 @@
|
|||||||
{% extends 'partials/base.html.twig' %}
|
{% extends 'partials/base.html.twig' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{{ header.title }}</h1>
|
|
||||||
{% if page.parent.name == 'podcast-series.md' %}
|
{% if page.parent.template == 'podcast-channel' %}
|
||||||
<h2>An episode in the series {{page.parent.title}}</h2>
|
{% set episodes = page.siblings %}
|
||||||
{% endif %}
|
{% elseif page.template == 'podcast-series' %}
|
||||||
<h3>Posted {{ header.date|date('Y-m-d')|nicetime(false) }}</h3>
|
{% set channel = page.parent %}
|
||||||
{{ page.content }}
|
{% endif %}
|
||||||
{% if page.header.podcast.audio.meta %}
|
|
||||||
<p class = "podcast-episode-audio">
|
<div class="episode-container">
|
||||||
{% if page.header.podcast.audio.remote is null or page.header.podcast.audio.remote is empty %}
|
|
||||||
{% set media_url = base_url ~ "/" ~ page.header.podcast.audio.meta.guid %}
|
<div class="episode-nav">
|
||||||
{% else %}
|
{% include 'partials/breadcrumbs.html.twig'%}
|
||||||
{% set media_url = page.header.podcast.audio.meta.guid %}
|
</div>
|
||||||
{% endif %}
|
|
||||||
<audio controls="1" alt="{{ episode.title }}"><source src="{{ media_url }}">Your browser does not support the audio tag.</audio>
|
<div class="episode-flex-wrapper">
|
||||||
<br/><a href ="{{ media_url }}">Download Audio</a>
|
<div class="episode-flex-child episode-top">
|
||||||
</p>
|
<h1>{{ page.title }} {% if (header.podcast.audio.meta.guid) %}<small>({{ header.podcast.audio.meta.duration }})</small>{% endif %}</h1>
|
||||||
{% endif %}
|
{% if (header.podcast.itunes.subtitle) -%}
|
||||||
|
<h2>{{ header.podcast.itunes.subtitle }}</h2
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="episode-content-wrapper">
|
||||||
|
{% if (header.podcast.audio.meta.guid) %}
|
||||||
|
<div class="podcast-episode-audio">
|
||||||
|
<audio controls="1" alt="{{ episode.title }}"><source src="{{ page.header.podcast.audio.meta.guid }}">{{ 'PLUGIN_PODCAST.EPISODE_CONTENT.WARNING'|t|e }}</audio></br>
|
||||||
|
<a href ="{{ header.podcast.audio.meta.guid }}">{{ 'PLUGIN_PODCAST.EPISODE_CONTENT.DOWNLOAD'|t|e }}</a> | Posted {{ header.date|date('Y-m-d')|nicetime(false) }}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p>No audio for this episode</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="episode-flex-child episode-content">
|
||||||
|
<h3>{{ 'PLUGIN_PODCAST.EPISODE_CONTENT.HEADER'|t|e }}</h3>
|
||||||
|
{{ page.content|raw }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="episode-flex-child">
|
||||||
|
{% include 'partials/podcast_episodes_mini_list.html.twig'%}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -3,15 +3,12 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% set series = page.parent.collection({ 'items': '@self.descendants', 'order': {'by': 'date', 'dir': 'desc'}} ).ofType('podcast-series') %}
|
{% set series = page.parent.collection({ 'items': '@self.descendants', 'order': {'by': 'date', 'dir': 'desc'}} ).ofType('podcast-series') %}
|
||||||
{% set episodes = page.collection({ 'items': '@self.descendants', 'order': {'by': 'date', 'dir': 'desc'}} ).ofType('podcast-episode') %}
|
{% set episodes = page.collection({ 'items': '@self.descendants', 'order': {'by': 'date', 'dir': 'desc'}} ).ofType('podcast-episode') %}
|
||||||
|
|
||||||
<div class="podcast-channel-header">
|
<div class="podcast-channel-header">
|
||||||
<div class = "podcast-channel-image">
|
<div class = "podcast-channel-image">
|
||||||
{% if not (page.header.series.image) %}
|
{% if not (header.series.image) and (page.parent.header.podcast.itunes.image)%}
|
||||||
{% set featured_image = ((page.parent.header.podcast.itunes.image)|first) %}
|
{{ page.parent.media[page.parent.header.podcast.itunes.image].resize(200, 200).html()|raw }}
|
||||||
{{ page.parent.media[featured_image.name].resize(200, 200).html() }}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set featured_image = ((page.header.series.image)|first) %}
|
{{ page.media[header.series.image].resize(200, 200).html()|raw }}
|
||||||
{{ page.media[featured_image.name].resize(200, 200).html() }}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -21,9 +18,9 @@
|
|||||||
{% if not page.content %}
|
{% if not page.content %}
|
||||||
{% set description = page.parent.header.podcast.description %}
|
{% set description = page.parent.header.podcast.description %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set description = page.content %}
|
{% set description = page.content() %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p class = "description">{{ description }}</p>
|
<p class = "description">{{ description|raw }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="channel-links">
|
<div class="channel-links">
|
||||||
<a href="{{ base_url }}{{ page.route }}.rss"><i class="fa fa-rss" aria-hidden="true"></i>{{ 'PLUGIN_PODCAST.SERIES'|t }} | {{ page.title }}</a>
|
<a href="{{ base_url }}{{ page.route }}.rss"><i class="fa fa-rss" aria-hidden="true"></i>{{ 'PLUGIN_PODCAST.SERIES'|t }} | {{ page.title }}</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user