diff --git a/php/classes/controllers/class-admin-controller.php b/php/classes/controllers/class-admin-controller.php index 4cc707bc..b9535dcf 100644 --- a/php/classes/controllers/class-admin-controller.php +++ b/php/classes/controllers/class-admin-controller.php @@ -26,13 +26,21 @@ class Admin_Controller extends Controller { */ protected $ajax_handler; + /** + * @var object instance of Upgrade_Handler + */ protected $upgrade_handler; + /** + * @var object instance of Feed_Controller + */ + protected $feed_controller; + /** * Admin_Controller constructor. * - * @param $file main plugin file - * @param $version plugin version + * @param $file string main plugin file + * @param $version string plugin version */ public function __construct( $file, $version ) { parent::__construct( $file, $version ); @@ -48,6 +56,8 @@ public function bootstrap() { $this->upgrade_handler = new Upgrade_Handler(); + $this->feed_controller = new Feed_Controller( $this->file, $this->version ); + // Handle localisation. $this->load_plugin_textdomain(); @@ -56,12 +66,6 @@ public function bootstrap() { // Regsiter podcast post type, taxonomies and meta fields. add_action( 'init', array( $this, 'register_post_type' ), 11 ); - // Register podcast feed. - add_action( 'init', array( $this, 'add_feed' ), 11 ); - - // Handle v1.x feed URL as well as feed URLs for default permalinks. - add_action( 'init', array( $this, 'redirect_old_feed' ), 11 ); - // Setup custom permalink structures. add_action( 'init', array( $this, 'setup_permastruct' ), 10 ); @@ -1233,15 +1237,6 @@ public function load_plugin_textdomain() { load_plugin_textdomain( $domain, false, dirname( plugin_basename( $this->file ) ) . '/lang/' ); } - /** - * Register podcast feed - * @return void - */ - public function add_feed() { - $feed_slug = apply_filters( 'ssp_feed_slug', $this->token ); - add_feed( $feed_slug, array( $this, 'feed_template' ) ); - } - /** * Hide RSS footer created by WordPress SEO from podcast RSS feed * @@ -1259,72 +1254,22 @@ public function hide_wp_seo_rss_footer( $include_footer = true ) { } /** - * Load feed template - * @return void - */ - public function feed_template() { - global $wp_query; - - // Prevent 404 on feed - $wp_query->is_404 = false; - - /** - * Fix the is_feed attribute on the old feed url structure - */ - if ( ! $wp_query->is_feed ) { - $wp_query->is_feed = true; - } - - status_header( 200 ); - - $file_name = 'feed-podcast.php'; - - $user_template_file = apply_filters( 'ssp_feed_template_file', trailingslashit( get_stylesheet_directory() ) . $file_name ); - - // Any functions hooked in here must NOT output any data or else feed will break - do_action( 'ssp_before_feed' ); - - // Load user feed template if it exists, otherwise use plugin template - if ( file_exists( $user_template_file ) ) { - require( $user_template_file ); - } else { - require( $this->template_path . $file_name ); - } - - // Any functions hooked in here must NOT output any data or else feed will break - do_action( 'ssp_after_feed' ); - - exit; - } - - /** - * Redirect feed URLs created prior to v1.8 to ensure backwards compatibility - * @return void - */ - public function redirect_old_feed() { - if ( isset( $_GET['feed'] ) && in_array( $_GET['feed'], array( $this->token, 'itunes' ) ) ) { - $this->feed_template(); - exit; - } - } - - /** - * Flush rewrite rules on plugin acivation + * All plugin activation functionality * @return void */ public function activate() { - // Setup all custom URL rules $this->register_post_type(); - $this->add_feed(); + // Setup feed + $this->feed_controller->add_feed(); + // Setup permalink structure $this->setup_permastruct(); - // Flush permalinks flush_rewrite_rules( true ); } /** - * Flush rewrite rules on plugin deacivation + * All plugin deactivation functionality * @return void */ public function deactivate() { diff --git a/php/classes/controllers/class-controller.php b/php/classes/controllers/class-controller.php index 9030a23e..2482ef69 100644 --- a/php/classes/controllers/class-controller.php +++ b/php/classes/controllers/class-controller.php @@ -7,6 +7,8 @@ exit; } +// @todo maybe this should be a trait ? + /** * Main controller class * diff --git a/php/classes/controllers/class-feed-controller.php b/php/classes/controllers/class-feed-controller.php new file mode 100644 index 00000000..245dffab --- /dev/null +++ b/php/classes/controllers/class-feed-controller.php @@ -0,0 +1,110 @@ +bootstrap(); + } + + /** + * Set up all hooks and filters for this class + */ + public function bootstrap() { + // Register podcast feed. + add_action( 'init', array( $this, 'add_feed' ), 11 ); + + // Handle v1.x feed URL as well as feed URLs for default permalinks. + add_action( 'init', array( $this, 'redirect_old_feed' ), 11 ); + } + + /** + * Register podcast feed + * @return void + */ + public function add_feed() { + $feed_slug = apply_filters( 'ssp_feed_slug', $this->token ); + add_feed( $feed_slug, array( $this, 'render_podcast_feed' ) ); + } + + /** + * Redirect feed URLs created prior to v1.8 to ensure backwards compatibility + * @return void + */ + public function redirect_old_feed() { + if ( isset( $_GET['feed'] ) && in_array( $_GET['feed'], array( $this->token, 'itunes' ) ) ) { + $this->render_podcast_feed(); + exit; + } + } + + /** + * Render the podcast feed + * // @todo move all logic from feed template file to this method, at the very least + * @return void + */ + public function render_podcast_feed() { + global $wp_query; + + // Prevent 404 on feed + $wp_query->is_404 = false; + + /** + * Fix the is_feed attribute on the old feed url structure + */ + if ( ! $wp_query->is_feed ) { + $wp_query->is_feed = true; + } + + $this->load_feed_template(); + + exit; + + } + + /** + * Loads the feed template file + */ + public function load_feed_template() { + status_header( 200 ); + + $user_template_file = apply_filters( 'ssp_feed_template_file', trailingslashit( get_stylesheet_directory() ) . $this->feed_file_name ); + + // Any functions hooked in here must NOT output any data or else feed will break + do_action( 'ssp_before_feed' ); + + // Load user feed template if it exists, otherwise use plugin template + if ( file_exists( $user_template_file ) ) { + require $user_template_file; + } else { + require $this->template_path . $this->feed_file_name; + } + + // Any functions hooked in here must NOT output any data or else feed will break + do_action( 'ssp_after_feed' ); + } +} diff --git a/php/classes/handlers/class-settings-handler.php b/php/classes/handlers/class-settings-handler.php index c85f3726..a2b7b19f 100644 --- a/php/classes/handlers/class-settings-handler.php +++ b/php/classes/handlers/class-settings-handler.php @@ -714,15 +714,27 @@ public function settings_fields() { array( 'id' => 'consume_order', 'label' => __( 'Show Type', 'seriously-simple-podcasting' ), + // translators: placeholders are for help document link 'description' => sprintf( __( 'The order your podcast episodes will be listed. %1$sMore details here.%2$s', 'seriously-simple-podcasting' ), '', '' ), 'type' => 'select', 'options' => array( '' => __( 'Please Select', 'seriously-simple-podcasting' ), 'episodic' => __( 'Episodic', 'seriously-simple-podcasting' ), - 'serial' => __( 'Serial', 'seriously-simple-podcasting' ) + 'serial' => __( 'Serial', 'seriously-simple-podcasting' ), ), 'default' => '', ), + array( + 'id' => 'media_prefix', + 'label' => __( 'Media File Prefix', 'seriously-simple-podcasting' ), + // translators: placeholders are for help document link + 'description' => sprintf( __( 'Enter your Podtrac, Chartable, or other media file prefix here. %1$sMore details here.%2$s', 'seriously-simple-podcasting' ), '', '' ), + 'type' => 'text', + 'default' => '', + 'placeholder' => __( 'https://dts.podtrac.com/redirect/mp3/', 'seriously-simple-podcasting' ), + 'callback' => 'esc_url_raw', + 'class' => 'regular-text', + ), array( 'id' => 'episode_description', 'label' => __( 'Episode description', 'seriously-simple-podcasting' ), diff --git a/php/includes/ssp-functions.php b/php/includes/ssp-functions.php index ef02519c..d890e512 100644 --- a/php/includes/ssp-functions.php +++ b/php/includes/ssp-functions.php @@ -1051,3 +1051,25 @@ function get_series_data_for_castos( $series_id ) { } } + +if ( ! function_exists( 'parse_episode_url_with_media_prefix' ) ) { + /** + * Takes an episode url and appends the media prefix in front of it + * + * @param string $audio_file_url + * @param string $media_prefix + * + * @return string + */ + function parse_episode_url_with_media_prefix( $audio_file_url = '', $media_prefix = '' ) { + if ( empty( $media_prefix ) ) { + return $audio_file_url; + } + if ( empty( $audio_file_url ) ) { + return $audio_file_url; + } + $url_parts = wp_parse_url( $audio_file_url ); + + return $media_prefix . $url_parts['host'] . $url_parts['path']; + } +} diff --git a/readme.txt b/readme.txt index 6381d6dc..e4fb7eca 100644 --- a/readme.txt +++ b/readme.txt @@ -2,9 +2,9 @@ Contributors: PodcastMotor, psykro, simondowdles, hlashbrooke, whyisjake Tags: podcast, audio, video, vodcast, rss, mp3, mp4, feed, itunes, podcasting, media, stitcher, google play, playlist Requires at least: 4.4 -Tested up to: 5.2 +Tested up to: 5.2.2 Requires PHP: 5.6 -Stable tag: 1.20.7 +Stable tag: 1.20.8 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -102,6 +102,10 @@ You can find complete user and developer documentation (along with the FAQs) on == Changelog == += 1.20.8 = +* 2019-08-13 +* [NEW] Added support for RSS Feed media file prefixing, to enable measuring services like Podtrac and Chartable + = 1.20.7 = * 2019-07-31 * [UPDATE] Updated podcast categories to reflect Apple's [podcast category changes](https://podnews.net/press-release/apple-wwdc-2019-anno) diff --git a/seriously-simple-podcasting.php b/seriously-simple-podcasting.php index 9e9670b0..1a3b8f01 100644 --- a/seriously-simple-podcasting.php +++ b/seriously-simple-podcasting.php @@ -1,14 +1,14 @@ 0 ) { + $series_media_prefix = get_option( 'ss_podcasting_media_prefix_' . $series_id ); + if ( false !== $series_media_prefix ) { + $media_prefix = $series_media_prefix; + } +} + // Get episode description setting $episode_description = get_option( 'ss_podcasting_episode_description', 'excerpt' ); if ( $series_id && $series_id > 0 ) { @@ -391,6 +401,10 @@ $enclosure = apply_filters( 'ssp_feed_item_enclosure', $enclosure, get_the_ID() ); + if ( ! empty( $media_prefix ) ) { + $enclosure = parse_episode_url_with_media_prefix( $enclosure, $media_prefix ); + } + // If there is no enclosure then go no further if ( ! isset( $enclosure ) || ! $enclosure ) { continue; diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 8d51210f..9326a967 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -11,6 +11,7 @@ 'SeriouslySimplePodcasting\\Controllers\\Controller' => $baseDir . '/php/classes/controllers/class-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Episode_Controller' => $baseDir . '/php/classes/controllers/class-episode-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Extensions_Controller' => $baseDir . '/php/classes/controllers/class-extensions-controller.php', + 'SeriouslySimplePodcasting\\Controllers\\Feed_Controller' => $baseDir . '/php/classes/controllers/class-feed-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Frontend_Controller' => $baseDir . '/php/classes/controllers/class-frontend-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Import_Controller' => $baseDir . '/php/classes/controllers/class-import-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Options_Controller' => $baseDir . '/php/classes/controllers/class-options-controller.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 561fa380..0dcbca58 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -12,6 +12,7 @@ class ComposerStaticInit34e210bfa8d7151620d7fa4510f053c5 'SeriouslySimplePodcasting\\Controllers\\Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Episode_Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-episode-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Extensions_Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-extensions-controller.php', + 'SeriouslySimplePodcasting\\Controllers\\Feed_Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-feed-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Frontend_Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-frontend-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Import_Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-import-controller.php', 'SeriouslySimplePodcasting\\Controllers\\Options_Controller' => __DIR__ . '/../..' . '/php/classes/controllers/class-options-controller.php',