I have a custom post type, with page capabilities, to create HTML newsletters via WordPress. I am using hierarchy with child posts to create a magazine type newsletter: parent post is the main post, children are media objects below.
See example: http://blog.utc.edu/today/newsletters/whats-the-latest-for-summer-semester-2014/
I need RSS feed for this CPT, but I want to exclude child posts. Is a simple URL parameter to achieve this? (I know I can create a custom RSS template.)
See example: http://blog.utc.edu/today/feed/?post_type=utcblogs_newsletter&include_children=false
The above URL is "optimistic", I know the parameter is not correct. You can see the child posts are included.
I also add the CPT to the general RSS feed by:
// Add newsletters to general RSS feed
function add_cpt_to_feed( $query ) {
if ( isset($query['feed']) && !isset($query['post_type']) )
$query['post_type'] = array('post', 'utcblogs_newsletter');
return $query;
}
add_filter( 'request', 'add_cpt_to_feed' );
So, is there a way to modify the $query to exclude child posts?, or do I need a different query or WP function to achieve this?
I solved this by creating a custom RSS template for the Custom Post Type.
To remove child posts (yes, posts can have hierarchy in a CPT), use post_parent:
$args = array(
'post_type' => 'utcblogs_newsletter',
'post_parent' => 0
);
query_posts( $args );
So, the complete custom RSS template (newsletter-customfeed.php in main theme folder) is:
<?php
/*
Template Name: Custom Newsletter Feed
*/
$numposts = 5;
function custom_rss_date( $timestamp = null ) {
$timestamp = ($timestamp==null) ? time() : $timestamp;
echo date(DATE_RSS, $timestamp);
}
function custom_rss_text_limit($string, $length, $replacer = '…') {
$string = strip_tags($string);
if(strlen($string) > $length)
return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;
return $string;
}
$args = array(
'post_type' => 'utcblogs_newsletter',
'post_parent' => 0
);
query_posts( $args );
$lastpost = $numposts - 1;
header('Content-Type: ' . feed_content_type('rss-http') . '; charset=' . get_option('blog_charset'), true);
$more = 1;
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
<?php do_action('rss2_ns'); ?>
>
<channel>
<title><?php bloginfo_rss('name'); wp_title_rss(); ?></title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<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>
<sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod>
<sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency>
<?php do_action('rss2_head'); ?>
<?php while( have_posts()) : the_post(); ?>
<item>
<title><?php the_title_rss() ?></title>
<link><?php the_permalink_rss() ?></link>
<comments><?php comments_link_feed(); ?></comments>
<pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate>
<dc:creator><?php the_author() ?></dc:creator>
<?php the_category_rss('rss2') ?>
<guid isPermaLink="false"><?php the_guid(); ?></guid>
<?php if (get_option('rss_use_excerpt')) : ?>
<description><![CDATA[<?php get_the_excerpt(); ?>]]></description>
<?php else : ?>
<description><?php echo '<![CDATA['.custom_rss_text_limit($post->post_content, 256).']]>'; ?></description>
<?php $content = get_the_content_feed('rss2'); ?>
<?php if ( strlen( $content ) > 0 ) : ?>
<content:encoded><![CDATA[<?php echo $content; ?>]]></content:encoded>
<?php else : ?>
<content:encoded><![CDATA[<?php the_excerpt(); ?>]]></content:encoded>
<?php endif; ?>
<?php endif; ?>
<wfw:commentRss><?php echo esc_url( get_post_comments_feed_link(null, 'rss2') ); ?></wfw:commentRss>
<slash:comments><?php echo get_comments_number(); ?></slash:comments>
<?php rss_enclosure(); ?>
<?php do_action('rss2_item'); ?>
</item>
<?php endwhile; ?>
</channel>
</rss>
...and the feed URL is set in functions.php and called as http://my.site.com/newsletter.xml
/* Custom RSS Feed for Newsletter CPT */
function create_my_customfeed_newsletter() {
load_template( get_stylesheet_directory() . '/newsletter-customfeed.php');
}
add_action('do_feed_newsletter', 'create_my_customfeed_newsletter', 10, 1);
// creates /feed/feedname and /feedname.xml for each custom CPT RSS
function custom_feed_rewrite($wp_rewrite) {
$feed_rules = array(
'feed/(.+)' => 'index.php?feed=' . $wp_rewrite->preg_index(1),
'(.+).xml' => 'index.php?feed='. $wp_rewrite->preg_index(1)
);
$wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
}
add_filter('generate_rewrite_rules', 'custom_feed_rewrite');
...and to include newsletters in general RSS:
// Add newsletters to general RSS feed
function add_cpt_to_feed( $query ) {
if ( isset($query['feed']) && !isset($query['post_type']) )
$query['post_type'] = array(
'post',
'utcblogs_newsletter',
'post_parent' => 0
);
return $query;
}
add_filter( 'request', 'add_cpt_to_feed' );
Related
My loop looks like this:
<!-- loop for the posts here -->
<?php
$args = array(
'post_type' => 'post',
'posts_per_page' => 3,
'category_name' => 'news'
);
$query = new WP_Query($args);
while($query->have_posts()) : $query->the_post();
?>
<div class="news_box_content">
<h5><?php the_title(); ?></h5>
<figure><?php the_post_thumbnail(); ?></figure>
<?php if($post->post_excerpt) { ?>
<p><?php echo get_the_excerpt(); ?></p>
Read more...
<?php } else {
the_content('Read More');
} ?>
</div>
<?php endwhile; wp_reset_postdata(); ?>
I used a function to count the excerpt length but it is not working.
function custom_excerpt_length(){
return 10;
}
add_filter('excerpt_length', 'custom_excerpt_length');
How can I limit the number of characters on any excerpt?
No need for an extra filter
echo substr(get_the_excerpt(), 0,10);
Try this one. I always use this one
<?php
$content = get_the_content();
$content = strip_tags($content);
$dots = strlen(substr($content,0,50)) < 50 ? " " : "...";
echo substr($content,0,50) . $dots;
?>
Add this to your functions.php file:
function trim_excerpt( $exc ) {
$exc_trimmed = substr( $exc, 0, 150 ) . '...';
return $exc_trimmed;
}
add_filter( 'the_excerpt', 'trim_excerpt', 999 );
I need a shortcode that lists all posts of a certain category.
I found this php code that works on page templates but as soon as I add it in shortcodes it doesn't work (and I really need it in shortcode format):
<ul>
<?php
$catPost = get_posts(get_cat_ID("31")); //change this
foreach ($catPost as $post) : setup_postdata($post); ?>
<li><?php the_title(); ?></li>
<?php endforeach;?>
</ul>
So how can I do it?
Here's an updated and tested version of Amin. T's code. Add to your functions.php file.
/*
* Output a simple unordered list of posts in a particular category id
* Usage e.g.: [posts_in_category cat="3"]
*/
function posts_in_category_func( $atts ) {
$category_id = $atts['cat'];
$args = array( 'category' => $category_id, 'post_type' => 'post' );
$cat_posts = get_posts($args);
$markup = "<ul>";
foreach ($cat_posts as $post) {
$markup .= "<li><a href='" . get_permalink($post->ID) . "'>" . $post->post_title . "</a></li>";
}
$markup .= "</ul>";
return $markup;
}
add_shortcode( 'posts_in_category', 'posts_in_category_func' );
It should be something like this (add this to your functions.php file)
function posts_in_category_func( $atts ) {
$category_id = $atts['cat'];
?>
<ul>
<?php
$args = array( 'category' => $category_id, 'post_type' => 'post' );
$catPost = get_posts($args);
foreach ($catPost as $post) : setup_postdata($post); ?>
<li><?php the_title(); ?></li>
<?php endforeach;?>
</ul>
<?
}
add_shortcode( 'posts_in_category', 'posts_in_category_func' );
You can call it like that [posts_in_category cat=1]
I have custom RSS template for news aggregator. Is it possible to exclude all media files like images/video from the_content_feed(); ?
I need to display a plain text.
Here is my template
header( 'Content-Type: ' . feed_content_type( 'rss-http' ) . '; charset=' . get_option( 'blog_charset' ), true );
$frequency = 1;
$duration = 'hourly';
$postimages = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), 'large' );
if ( $postimages ) {
$postimage = $postimages[0];
} else {
$postimage = get_stylesheet_directory_uri() . '/images/default.jpg';
}
echo '<?xml version="1.0" encoding="UTF-8"?>' ."\r\n"; ?>
<rss xmlns:yandex="http://news.yandex.ru" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title><?php bloginfo_rss( 'name' ); wp_title_rss(); ?></title>
<link><?php bloginfo_rss( 'url' ) ?></link>
<description><?php bloginfo_rss( 'description' ) ?></description>
<yandex:logo></yandex:logo>
<yandex:logo type="square"></yandex:logo>
<lastBuildDate><?php echo mysql2date( 'D, d M Y H:i:s +0200', get_lastpostmodified( 'GMT' ), false ); ?></lastBuildDate>
<language><?php bloginfo_rss( 'language' ); ?></language>
<?php do_action( 'rss2_head' ); ?>
<?php while( have_posts()) : the_post(); ?>
<item>
<title><?php the_title_rss(); ?></title>
<link><?php the_permalink_rss(); ?></link>
<guid isPermaLink="false"><?php the_guid(); ?></guid>
<author><?php the_author(); ?></author>
<enclosure url="<?php echo esc_url( $postimage ); ?>" type="image/jpeg" />
<pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0200', get_date_from_gmt(get_post_time('Y-m-d H:i:s', true)), false ); ?></pubDate>
<description>
<![CDATA[<?php the_excerpt_rss(); ?>]]>
</description>
<yandex:full-text>
<![CDATA[<?php the_content_feed(); ?>]]>
</yandex:full-text>
</item>
<?php endwhile; ?>
</channel>
</rss>
I've tried to use this filter, but had no luck :(
add_filter( "the_content_feed", "excludeimg" ) ;
function excludeimg($content) {
$content = preg_replace('#(<img.*?>).*?(/>)#', '$1$2', $content);
return $content;
}
?>
Here is the solution
To show plain text from the articles in your RSS feed just change the_content_feed(); to echo wp_strip_all_tags( get_the_content() ); in your feed template.
<?php echo get_the_post_thumbnail($post_id); ?>
Above is the code that i am using on page but nothing is showing on page,want to show thumbnail of recent post along with the content on blog page
Are you using the WP_Query method ? If not then use
$args = array(
'post_type' => 'post',
'posts_per_page'=> your_desired_number_of_post,
);
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
echo '<li>';
$the_query->the_post();
the_post_thumbnail();
the_content();
echo '</li>';
}
echo '</ul>';
}
else {
echo 'no posts found';
}
/* Restore original Post Data */
wp_reset_postdata();
I'm using already designed theme for wordpress, and now instead of regular blog posts I would like to display WooCommerce products (which are custom post types I persume).
This is the current query with display loop:
<?php
$args = array(
//'posts_per_page' => '2',
'paged' => get_query_var('paged')
);
$homepage_query = new WP_Query($args);
?>
<?php //query_posts('posts_per_page=4&paged='.get_query_var('paged')); ?>
<?php if ( have_posts() ) : ?>
<?php while ( $homepage_query->have_posts() ) : $homepage_query->the_post(); ?>
<?php if($style == 'blog_style') { ?>
<div id="blog-style" class="post-box">
<?php get_template_part('content', 'blog'); ?>
</div>
<?php } else { ?>
<div class="post-box grid_4 <?php aero_post_box_class(); ?>">
<?php get_template_part('content', ''); ?>
</div>
<?php } ?>
<?php endwhile; ?>
Is there a way to add options to $args so the loop displays WooCommerce products? I'm also using pagination with this loop, which is required on this project, so that's why it's important to use this loop.
You should be able to access products through the loop, setting the post_type arg to product:
<?php
// Setup your custom query
$args = array( 'post_type' => 'product', ... );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post(); ?>
<a href="<?php echo get_permalink( $loop->post->ID ) ?>">
<?php the_title(); ?>
</a>
<?php endwhile; wp_reset_query(); // Remember to reset ?>
This is the proper way to re-create and customize the WooCommerce product loop:
if(!function_exists('wc_get_products')) {
return;
}
$paged = (get_query_var('paged')) ? absint(get_query_var('paged')) : 1; // if your custom loop is on a static front page then check for the query var 'page' instead of 'paged', see https://developer.wordpress.org/reference/classes/wp_query/#pagination-parameters
$ordering = WC()->query->get_catalog_ordering_args();
$ordering['orderby'] = array_shift(explode(' ', $ordering['orderby']));
$ordering['orderby'] = stristr($ordering['orderby'], 'price') ? 'meta_value_num' : $ordering['orderby'];
$products_per_page = apply_filters('loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page());
$products_ids = wc_get_products(array(
'status' => 'publish',
'limit' => $products_per_page,
'page' => $paged,
'paginate' => true,
'return' => 'ids',
'orderby' => $ordering['orderby'],
'order' => $ordering['order'],
));
wc_set_loop_prop('current_page', $paged);
wc_set_loop_prop('is_paginated', wc_string_to_bool(true));
wc_set_loop_prop('page_template', get_page_template_slug());
wc_set_loop_prop('per_page', $products_per_page);
wc_set_loop_prop('total', $products_ids->total);
wc_set_loop_prop('total_pages', $products_ids->max_num_pages);
if($products_ids) {
do_action('woocommerce_before_shop_loop');
woocommerce_product_loop_start();
foreach($products_ids->products as $featured_product) {
$post_object = get_post($featured_product);
setup_postdata($GLOBALS['post'] =& $post_object);
wc_get_template_part('content', 'product');
}
wp_reset_postdata();
woocommerce_product_loop_end();
do_action('woocommerce_after_shop_loop');
} else {
do_action('woocommerce_no_products_found');
}
Using the code above, you would customize the wc_get_products() arguments to get the IDs of the products you want (if you have specific criteria). Once that code is in place, all the features of a native WooCommerce loop will be available to you—pagination, ordering, etc. This method is superior to WP_Query and get_posts() because those two methods can break.
I've written a more detailed blog post about custom WooCommerce loops here: https://cfxdesign.com/create-a-custom-woocommerce-product-loop-the-right-way/
You can Also get Category using thi code
$terms = get_terms('product_cat');
foreach ($terms as $term) {
$term_link = get_term_link( $term, 'product_cat' );
echo '<li>' . $term->name . '</li>';
}
If You want only parent category then
wp_list_categories('taxonomy=product_cat&orderby=order&title_li=&depth=1');