private function html() { if (!count($this->args['data']['feeds'])) { return ''; } $dataAccessor = 'podcastData' . self::get_random_string(); $dom = new \Podlove\DomDocumentFragment(); $script_data_tag = $dom->createElement('script'); $script_data_tag->appendChild($dom->createTextNode(sprintf("window.{$dataAccessor} = %s;", json_encode($this->args['data'])))); $script_button_tag = $dom->createElement('script'); $script_button_tag->setAttribute('class', 'podlove-subscribe-button'); $script_button_tag->setAttribute('src', 'https://cdn.podlove.org/subscribe-button/javascripts/app.js'); $script_button_tag->setAttribute('data-json-data', $dataAccessor); $script_button_tag->setAttribute('data-language', self::language($this->args['language'])); $script_button_tag->setAttribute('data-size', self::size($this->args['size'], $this->args['width'])); if ($this->args['colors']) { $script_button_tag->setAttribute('data-colors', $this->args['colors']); } if ($this->args['buttonid']) { $script_button_tag->setAttribute('data-buttonid', $this->args['buttonid']); } if ($this->args['hide'] && in_array($args['hide'], [1, '1', true, 'true', 'on'])) { $script_button_tag->setAttribute('data-hide', true); } // ensure there is a closing script tag $script_button_tag->appendChild($dom->createTextNode(' ')); $dom->appendChild($script_data_tag); $dom->appendChild($script_button_tag); return (string) $dom; }
/** * Get HTML image tag for resized image. * * Examples * * $image->image(); // returns image tag * * @param array $args List of arguments * - id: Set image tag "id" attribute. * - class: Set image tag "class" attribute. * - style: Set image tag "style" attribute. * - alt: Set image tag "alt" attribute. * - title: Set image tag "title" attribute. * - width: Image width. Set width and leave height blank to keep the orinal aspect ratio. * - height: Image height. Set height and leave width blank to keep the orinal aspect ratio. * - attributes: List of other HTML attributes, for example: ['data-foo' => 'bar'] * @return string HTML image tag */ public function image($args = []) { $defaults = ['id' => '', 'class' => '', 'style' => '', 'alt' => '', 'title' => '', 'width' => $this->width, 'height' => $this->height, 'attributes' => []]; $args = wp_parse_args($args, $defaults); // put everything in 'attributes' for easy iteration foreach (['id', 'class', 'style', 'alt', 'title', 'width', 'height'] as $attr) { if ($args[$attr]) { $args['attributes'][$attr] = $args[$attr]; } } $dom = new \Podlove\DomDocumentFragment(); $img = $dom->createElement('img'); foreach ($args['attributes'] as $key => $value) { $img->setAttribute($key, $value); } $img->setAttribute('src', $this->url()); if ($this->retina && ($srcset = $this->srcset())) { $img->setAttribute('srcset', $srcset); } $dom->appendChild($img); return (string) $dom; }
function override_feed_head($hook, $podcast, $feed, $format) { $filter_hooks = array('podlove_feed_itunes_author', 'podlove_feed_itunes_owner', 'podlove_feed_itunes_subtitle', 'podlove_feed_itunes_keywords', 'podlove_feed_itunes_summary', 'podlove_feed_itunes_complete', 'podlove_feed_itunes_explicit'); foreach ($filter_hooks as $filter) { add_filter($filter, 'convert_chars'); } add_filter('podlove_feed_content', '\\Podlove\\Feeds\\prepare_for_feed'); remove_action($hook, 'the_generator'); add_action($hook, function () use($hook) { switch ($hook) { case 'rss2_head': $gen = '<generator>' . \Podlove\get_plugin_header('Name') . ' v' . \Podlove\get_plugin_header('Version') . '</generator>'; break; case 'atom_head': $gen = '<generator uri="' . \Podlove\get_plugin_header('PluginURI') . '" version="' . \Podlove\get_plugin_header('Version') . '">' . \Podlove\get_plugin_header('Name') . '</generator>'; break; } echo $gen; }); add_action($hook, function () use($feed) { echo $feed->get_self_link(); echo $feed->get_alternate_links(); }, 9); // add rss image add_action($hook, function () use($podcast, $hook) { $image = ['url' => $podcast->cover_art()->url(), 'title' => $podcast->title, 'link' => apply_filters('podlove_feed_link', \Podlove\get_landing_page_url())]; $image = apply_filters('podlove_feed_image', $image); if (!$image['url']) { return; } // remove WordPress provided favicon remove_action($hook, 'rss2_site_icon'); // generate our own image tag $dom = new \Podlove\DomDocumentFragment(); $image_tag = $dom->createElement('image'); foreach ($image as $tag_name => $tag_text) { if ($tag_text) { $tag = $dom->createElement($tag_name); $tag_text = $dom->createTextNode($tag_text); $tag->appendChild($tag_text); $image_tag->appendChild($tag); } } $dom->appendChild($image_tag); echo (string) $dom; }, 5); // let it run early so we can stop the `rss2_site_icon` call add_action($hook, function () use($podcast, $feed, $format) { echo PHP_EOL; $author = "\t" . sprintf('<itunes:author>%s</itunes:author>', $podcast->author_name); echo apply_filters('podlove_feed_itunes_author', $author); echo PHP_EOL; $summary = "\t" . sprintf('<itunes:summary>%s</itunes:summary>', $podcast->summary); echo apply_filters('podlove_feed_itunes_summary', $summary); echo PHP_EOL; $categories = \Podlove\Itunes\categories(false); $category_html = ''; for ($i = 1; $i <= 3; $i++) { $category_id = $podcast->{'category_' . $i}; if (!$category_id) { continue; } list($cat, $subcat) = explode('-', $category_id); if ($subcat == '00') { $category_html .= sprintf('<itunes:category text="%s"></itunes:category>', htmlspecialchars($categories[$category_id])); } else { $category_html .= sprintf('<itunes:category text="%s"><itunes:category text="%s"></itunes:category></itunes:category>', htmlspecialchars($categories[$cat . '-00']), htmlspecialchars($categories[$category_id])); } } echo apply_filters('podlove_feed_itunes_categories', $category_html); echo PHP_EOL; $owner = sprintf(' <itunes:owner> <itunes:name>%s</itunes:name> <itunes:email>%s</itunes:email> </itunes:owner>', $podcast->owner_name, $podcast->owner_email); echo "\t" . apply_filters('podlove_feed_itunes_owner', $owner); echo PHP_EOL; if ($podcast->cover_art()->url()) { $coverimage = sprintf('<itunes:image href="%s" />', $podcast->cover_art()->url()); } else { $coverimage = ''; } echo "\t" . apply_filters('podlove_feed_itunes_image', $coverimage); echo PHP_EOL; $subtitle = sprintf('<itunes:subtitle>%s</itunes:subtitle>', $podcast->subtitle); echo "\t" . apply_filters('podlove_feed_itunes_subtitle', $subtitle); echo PHP_EOL; $keywords = sprintf('<itunes:keywords>%s</itunes:keywords>', $podcast->keywords); echo "\t" . apply_filters('podlove_feed_itunes_keywords', $keywords); echo PHP_EOL; $block = sprintf('<itunes:block>%s</itunes:block>', $feed->enable ? 'no' : 'yes'); echo "\t" . apply_filters('podlove_feed_itunes_block', $block); echo PHP_EOL; $explicit = sprintf('<itunes:explicit>%s</itunes:explicit>', $podcast->explicit == 2 ? 'clean' : ($podcast->explicit ? 'yes' : 'no')); echo "\t" . apply_filters('podlove_feed_itunes_explicit', $explicit); echo PHP_EOL; $complete = sprintf('<itunes:complete>%s</itunes:complete>', $podcast->complete ? 'yes' : 'no'); echo apply_filters('podlove_feed_itunes_complete', $podcast->complete ? "\t{$complete}" : ''); echo PHP_EOL; do_action('podlove_append_to_feed_head', $podcast, $feed, $format); }); }
public static function prepare_feed($feed_slug) { global $wp_query; add_action('rss2_ns', function () { echo 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" '; echo 'xmlns:psc="http://podlove.org/simple-chapters" '; echo 'xmlns:content="http://purl.org/rss/1.0/modules/content/" '; echo 'xmlns:fh="http://purl.org/syndication/history/1.0" '; }); $podcast = Model\Podcast::get(); if (!($feed = Model\Feed::find_one_by_slug($feed_slug))) { self::wp_404(); } if (!($episode_asset = $feed->episode_asset())) { self::wp_404(); } $file_type = $episode_asset->file_type(); add_filter('podlove_feed_enclosure', function ($enclosure, $enclosure_url, $enclosure_file_size, $mime_type, $media_file) { if ($enclosure_file_size < 0) { $enclosure_file_size = 0; } $dom = new \Podlove\DomDocumentFragment(); $element = $dom->createElement('enclosure'); $attributes = ['url' => $enclosure_url, 'length' => $enclosure_file_size, 'type' => $mime_type]; $attributes = apply_filters('podlove_feed_enclosure_attributes', $attributes, $media_file); foreach ($attributes as $k => $v) { $element->setAttribute($k, $v); } $dom->appendChild($element); return (string) $dom; }, 10, 5); override_feed_title($feed); override_feed_description($feed); override_feed_language($feed); override_feed_head('rss2_head', $podcast, $feed, $file_type); override_feed_entry('rss2_item', $podcast, $feed, $file_type); add_action('rss2_item', function () { if (apply_filters('podlove_feed_show_summary', true)) { echo "<description><![CDATA["; \Podlove\Feeds\the_description(); echo "]]></description>"; } }, 9); add_action('rss2_head', function () use($podcast, $feed) { global $wp_query; $current_page = get_query_var('paged') ? get_query_var('paged') : 1; $feed_url_for_page = function ($page) use($feed) { $url = $feed->get_subscribe_url(); if ($page > 0) { $url .= '?paged=' . $page; } return $url; }; if ($current_page < $wp_query->max_num_pages) { echo "\n\t" . sprintf('<atom:link rel="next" href="%s" />', $feed_url_for_page($current_page + 1)); } if ($current_page > 2) { echo "\n\t" . sprintf('<atom:link rel="prev" href="%s" />', $feed_url_for_page($current_page - 1)); } elseif ($current_page == 2) { echo "\n\t" . sprintf('<atom:link rel="prev" href="%s" />', $feed_url_for_page(0)); } echo "\n\t" . sprintf('<atom:link rel="first" href="%s" />', $feed_url_for_page(0)); if ($wp_query->max_num_pages > 1) { echo "\n\t" . sprintf('<atom:link rel="last" href="%s" />', $feed_url_for_page($wp_query->max_num_pages)); } if ($podcast->language) { echo "\n\t" . '<language>' . $podcast->language . '</language>'; } do_action('podlove_rss2_head', $feed); }, 9); $posts_per_page = $feed->limit_items == 0 ? get_option('posts_per_rss') : $feed->limit_items; if ($posts_per_page == Model\Feed::ITEMS_GLOBAL_LIMIT) { $posts_per_page = $podcast->limit_items; } // now override the option so WP core functions accessing the option get the "correct" value add_filter('pre_option_posts_per_rss', function ($_) use($posts_per_page) { return $posts_per_page; }); $args = array('post_type' => 'podcast', 'post__in' => $feed->post_ids(), 'posts_per_page' => $posts_per_page); # The theme "getnoticed" globally overrides post_types in pre_get_posts. # Fix: hook in after the theme and override it again. # It's not bad practice because I *really* only want episodes in this feed. add_action('pre_get_posts', function ($query) { $query->set('post_type', 'podcast'); }, 20); /** * In feeds, WordPress ignores the 'posts_per_page' parameter * and overrides it with the 'posts_per_rss' option. So we need to * override that option. */ add_filter('post_limits', function ($limits) use($feed) { $page = get_query_var('paged') ? (int) get_query_var('paged') : 1; $max = $feed->get_post_limit_sql(); $start = $max * ($page - 1); if ($max > 0) { return 'LIMIT ' . $start . ', ' . $max; } else { return ''; } }); $args = array_merge($wp_query->query_vars, $args); query_posts($args); }