Created
July 30, 2024 20:02
-
-
Save JiveDig/f6ea19a80b569da390c6294c544bb6df to your computer and use it in GitHub Desktop.
Custom WP feed for MSN News
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Prevent direct file access. | |
defined( 'ABSPATH' ) || die; | |
/** | |
* Add MSN News feed. | |
* Flush permalinks after adding this feed. | |
* | |
* @return void | |
*/ | |
// add_action( 'after_setup_theme', function() { | |
// if ( ! class_exists( 'Mai_MSN_Feed' ) ) { | |
// return; | |
// } | |
// | |
// new Mai_MSN_Feed( | |
// [ | |
// 'slug' => 'msn-news', // The feed name. | |
// 'credits' => true, // Show "This post originally appeared on" credits. | |
// 'query_args' => [ | |
// 'posts_per_page' => 36, | |
// 'meta_query' => [ | |
// [ | |
// 'relation' => 'OR', | |
// [ | |
// 'key' => 'tvn_source_url', | |
// 'compare' => 'NOT EXISTS', | |
// ], | |
// [ | |
// 'key' => 'tvn_source_url', | |
// 'value' => '', | |
// 'compare' => '=', | |
// ], | |
// ], | |
// ], | |
// ], | |
// ] | |
// ); | |
// }); | |
/** | |
* Custom MSN RSS feed class. | |
* | |
* @version 1.0.0 | |
* | |
* @link (specs) https://helpcenter.microsoftstart.com/kb/feed-specifications | |
* @link (old validator) https://feeds.msn.com/evaluation | |
* @link (new validator) https://www.msn.com/en-us/partnerhub/management/feed/list | |
*/ | |
class Mai_MSN_Feed { | |
protected $args; | |
/** | |
* Construct the class. | |
*/ | |
function __construct( $args ) { | |
$this->args = wp_parse_args( $args, | |
[ | |
'slug' => 'msn-news', // The feed name. | |
'credits' => true, // Add credits to the feed. | |
'duration' => 'hourly', // Default 'hourly'. Accepts 'hourly', 'daily', 'weekly', 'monthly', 'yearly'. | |
'frequency' => 1, // Default '1'. The frequency of RSS updates within the update period. | |
'ttl' => 15, // Time to live in minutes. | |
] | |
); | |
$this->args['query_args'] = wp_parse_args( $this->args['query_args'], | |
[ | |
'post_type' => 'post', | |
'post_status' => 'publish', | |
'no_found_rows' => true, | |
'update_post_meta_cache' => false, | |
'update_post_term_cache' => false, | |
] | |
); | |
// Run hooks. | |
$this->hooks(); | |
} | |
/** | |
* Add hooks. | |
* | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
function hooks() { | |
add_feed( $this->args['slug'], [ $this, 'render_feed' ] ); | |
} | |
/** | |
* Custom RSS feed callback. | |
* | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
function render_feed() { | |
/** | |
* Feed header. | |
*/ | |
header( 'Content-Type: ' . feed_content_type( 'rss-http' ) . '; charset=' . get_option( 'blog_charset' ), true ); | |
/** | |
* Start RSS feed. | |
*/ | |
echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>'; | |
?> | |
<rss version="2.0" | |
xmlns:atom="http://www.w3.org/2005/Atom" | |
xmlns:content="http://purl.org/rss/1.0/modules/content/" | |
xmlns:dc="http://purl.org/dc/elements/1.1/" | |
xmlns:dcterms="http://purl.org/dc/terms/" | |
xmlns:media="http://search.yahoo.com/mrss/" | |
xmlns:slash="http://purl.org/rss/1.0/modules/slash/" | |
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" | |
xmlns:wfw="http://wellformedweb.org/CommentAPI/" | |
> | |
<channel> | |
<title><?php bloginfo_rss( 'name' ); ?></title> | |
<link><?php bloginfo_rss( 'url' ); ?></link> | |
<description><?php bloginfo_rss( 'description' ); ?></description> | |
<lastBuildDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_lastpostmodified( 'GMT' ), false ); ?></lastBuildDate> | |
<language><?php bloginfo_rss( 'language' ); ?></language> | |
<copyright><?php echo get_bloginfo( 'name' ); ?></copyright> | |
<ttl><?php echo $this->args['ttl']; ?></ttl> | |
<sy:updatePeriod><?php echo apply_filters( 'rss_update_period', $this->args['duration'] ); ?></sy:updatePeriod> | |
<sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', $this->args['frequency'] ); ?></sy:updateFrequency> | |
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" /> | |
<?php do_action( 'rss2_head' ); ?> | |
<?php | |
$query = new WP_Query( $this->args['query_args'] ); | |
if ( $query->have_posts() ) { | |
while ( $query->have_posts() ) : $query->the_post(); | |
?> | |
<item> | |
<title><?php the_title_rss(); ?></title> | |
<link><?php the_permalink_rss(); ?></link> | |
<guid isPermaLink="false"><?php the_guid(); ?></guid> | |
<dc:creator><?php the_author(); ?></dc:creator> | |
<pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true, get_the_ID() ), false ); ?></pubDate> | |
<dcterms:modified><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_modified_time( 'Y-m-d H:i:s', true, get_the_ID() ), false ); ?></dcterms:modified> | |
<?php | |
echo $this->get_categories(); | |
echo $this->get_thumbnail(); | |
?> | |
<description><![CDATA[ | |
<?php | |
ob_start(); | |
the_excerpt_rss(); | |
$excerpt = ob_get_clean(); | |
echo $this->get_content( $excerpt ); | |
echo $this->get_credits(); | |
?> | |
]]></description> | |
<content:encoded><![CDATA[ | |
<?php | |
echo $this->get_content( get_the_content_feed( 'msn-news' ) ); | |
echo $this->get_credits(); | |
?> | |
]]></content:encoded> | |
</item> | |
<?php | |
endwhile; | |
} | |
wp_reset_postdata(); | |
?> | |
</channel> | |
</rss> | |
<?php | |
} | |
/** | |
* Get categories for the feed. | |
* Comma-separated list of categories. | |
* | |
* @since 1.0.0 | |
* | |
* @return string | |
*/ | |
function get_categories() { | |
$categories = []; | |
$cats = get_the_terms( get_the_ID(), 'category' ); | |
// Add categories. | |
if ( $cats && ! is_wp_error( $cats ) ) { | |
foreach ( $cats as $cat ) { | |
$categories[] = $cat->name; | |
} | |
} | |
return $categories ? sprintf( '<category>%s</category>', implode( ',', $categories ) ) : ''; | |
} | |
/** | |
* Get the post thumbnail for the feed. | |
* | |
* @since 1.0.0 | |
* | |
* @return string | |
*/ | |
function get_thumbnail() { | |
$thumbnail = ''; | |
$image_id = get_post_thumbnail_id(); | |
$image = $image_id ? image_get_intermediate_size( $image_id, 'landscape-md' ) : ''; | |
$thumbnail = $image ? sprintf( '<p><img src="%s" class="type:primaryImage" /></p>', $image['url'] ) : ''; | |
return $thumbnail; | |
} | |
/** | |
* Handles content cleanup for MSN feeds. | |
* | |
* @since 1.0.0 | |
* | |
* @param string $content The HTML content. | |
* @param string $feed The feed name. | |
* | |
* @return string | |
*/ | |
function get_content( $content ) { | |
if ( ! $content || ! function_exists( 'mai_get_dom_document' ) || ! function_exists( 'mai_get_dom_html' ) ) { | |
return $content; | |
} | |
// Set up DOMDocument. | |
$dom = mai_get_dom_document( $content ); | |
$xpath = new DOMXPath( $dom ); | |
// Get all paragraphs. | |
$elements = $xpath->query( '/p' ); | |
// If we have paragraphs. | |
if ( $elements->length ) { | |
// Loop through each paragraph. | |
foreach ( $elements as $node ) { | |
// Loop through each child node. | |
foreach ( $node->childNodes as $child ) { | |
// Skip if not a link. | |
if ( 'a' !== $child->nodeName ) { | |
continue; | |
} | |
// Replace link with span. | |
$new = $dom->createElement( 'span', $child->textContent ); | |
$new->setAttribute( 'class', 'link-removed' ); | |
$child->parentNode->replaceChild( $new, $child ); | |
} | |
} | |
} | |
// Get figure/div wrappers to remove from twitter embeds. | |
$elements = $xpath->query( '//figure[contains(concat(" ", normalize-space(@class), " "), " wp-block-embed-twitter ")]' ); | |
// If we have elements. | |
if ( $elements->length ) { | |
// Loop through each element. | |
foreach ( $elements as $node ) { | |
// Get the blockquote. | |
$blockquote = $node->getElementsByTagName( 'blockquote' )->item(0); | |
// If we have a blockquote, replace the node with it. | |
if ( $blockquote ) { | |
$node->parentNode->replaceChild( $blockquote, $node ); | |
} | |
} | |
} | |
// Get the HTML content. | |
$content = mai_get_dom_html( $dom ); | |
return $content; | |
} | |
/** | |
* Get the credits for the feed. | |
* | |
* @since 1.0.0 | |
* | |
* @return string | |
*/ | |
function get_credits() { | |
// Bail if credits are disabled. | |
if ( ! $this->args['credits'] ) { | |
return ''; | |
} | |
return sprintf( '<p>The post <a href="%s">%s</a> originally published on <a href="%s">%s</a>.</p>', get_permalink(), get_the_title(), home_url(), get_bloginfo( 'name' ) ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment