Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
[WordPress] Removes sticky posts from WordPress default loop, sets up a custom sticky posts query. Sticky posts query can be implemented with one single template tag. Markup completely filterable. — http://glck.be/5916/
<?php
/**
* Separate sticky posts from the main loop into their own query.
*
* Display a query of sticky posts anywhere in your templates
* using a simple echo glckprss_sticky_posts().
* Query template output is stored in a transient for performance win,
* updated any time the 'sticky_posts' option get updated.
*
* Require in theme’s functions.php like:
* require get_template_directory() . '/inc/sticky-posts.php';
*
* @author @glueckpress
* @author_url http://glueckpress.com
*/
if( ! class_exists( 'GlckPrss__Sticky_Posts' ) ):
/**
* GlckPrss__Sticky_Posts class.
*/
class GlckPrss__Sticky_Posts {
/**
* Removes sticky posts from main query.
* Updates sticky transient simultaniously with sticky_posts option.
*
* @access public
* @return void
*/
function __construct() {
add_action( 'pre_get_posts', array( $this, 'is_home_ignore_sticky_posts' ) );
add_action( 'updated_option', array( $this, 'sticky_posts_query__update_transient' ), 10, 3 );
}
/**
* Remove sticky posts from main query.
*
* @access public
* @static
* @param mixed $query
* @return obj $query
*/
public static function is_home_ignore_sticky_posts( $query ) {
if( ! is_home() )
return $query;
$query->set( 'ignore_sticky_posts', true );
}
/**
* The sticky posts query template.
*
* @access public
* @static
* @filtered glckprss_sticky_posts_query__post_template
* @return string
*/
public static function sticky_posts_query__query_template() {
if( ! get_option( 'sticky_posts' ) )
return false;
$args = array(
'ignore_sticky_posts' => false,
'post__in' => get_option( 'sticky_posts' ),
'posts_per_page' => -1
);
$sticky_posts = new WP_Query( $args );
/*
* Stikcy posts loop.
*/
while ( $sticky_posts->have_posts() ) : $sticky_posts->the_post();
$entry_img = has_post_thumbnail() ? wp_get_attachment_image( ( get_post_thumbnail_id() ) ) : '';
/*
* To inject your own markup, use a custom function leveraging
* add_filter( 'glckprss_sticky_posts_query__post_template', 'foo' ).
*/
echo apply_filters( 'glckprss_sticky_posts_query__post_template',
sprintf('
<article class="sticky">
<figure class="sticky-image"><a href="%1$s">%2$s</a></figure>
<a href="%1$s">
<h3 class="sticky-title">%3$s</h3>
<div class="sticky-excerpt">
%4$s
</div>
</a>
</article>
', get_permalink(), $entry_img, get_the_title(), get_the_excerpt() ),
$sticky_posts, $sticky_posts, get_permalink(), $entry_img, get_the_title(), get_the_excerpt()
);
endwhile; // end loop
wp_reset_query();
}
/**
* Wrap query template in a transient for better performance.
*
* @access public
* @static
* @return void
*/
public static function sticky_posts_query__set_transient() {
ob_start();
self::sticky_posts_query__query_template();
$template = ob_get_contents();
ob_end_clean();
$transient = get_transient( 'glckprss_sticky_posts_query' );
if( $transient !== $template )
set_transient( 'glckprss_sticky_posts_query', $template ); // @todo make work for empty option sticky_posts
}
/**
* Update transient whenever option 'sticky_posts' gets updated,
* so we have a fresh query at all times.
*
* @access public
* @static
* @param mixed $option
* @param mixed $old_value
* @param mixed $value
* @return void
*/
public static function sticky_posts_query__update_transient( $option, $old_value, $value ) {
if( 'sticky_posts' === $option ) {
if( get_option( 'sticky_posts' ) )
self::sticky_posts_query__set_transient();
else
delete_transient( 'glckprss_sticky_posts_query' );
}
}
/**
* Retrieve transient, set when not present.
*
* @access public
* @static
* @return string
*/
public static function sticky_posts_query__get_transient() {
$transient = get_transient( 'glckprss_sticky_posts_query' );
if( $transient )
return $transient;
// Transient not set, so let’s set it now.
self::sticky_posts_query__set_transient();
return get_transient( 'glckprss_sticky_posts_query' );
}
}
if( ! function_exists( 'glckprss_sticky_posts' ) ) :
/**
* Template tag to retrieve sticky posts query template.
*
* @access public
* @param array $args (default: array())
* @return void
*/
function glckprss_sticky_posts( $args = array() ) {
$default_args = array(
'before' => '<section class="site-featured-content">',
'after' => '</section>'
);
$args = wp_parse_args( $args, $default_args );
$sticky_posts = GlckPrss__Sticky_Posts::sticky_posts_query__get_transient();
if ( ! $sticky_posts )
return;
/*
* Again, injecting your own markup is very easy utilizing a custom function
* hooking in like add_filter( 'glckprss_sticky_posts_query__post_template', 'foo' ).
*/
return apply_filters( 'glckprss_sticky_posts',
$args['before'] . $sticky_posts . $args['after'],
$args, $sticky_posts
);
}
endif;
endif;
/*
* Let there be stick.
*/
new GlckPrss__Sticky_Posts;
<?php
/* Customize wrapping element for query template */
echo glckprss_sticky_posts( 'before' => '<section class="your-class">', 'after' => '</section>' );
// Or filter from functions.php:
function your_custom_sticky_posts( $sticky_posts ) {
if( ! is_home() )
echo $sticky_posts;
}
add_filter( 'glckprss_sticky_posts', 'your_custom_sticky_posts', 10, 2 );
<?php
/* Customize sticky posts markup. */
function your_sticky_posts_query__post_template( $template, $query, $permalink, $entry_img, $title, $excerpt ) {
if( is_home() )
return $template;
printf('
<aside class="sticky post">
<figure class="sticky-image"><a href="%1$s">%2$s</a></figure>
<a href="%1$s">
<h3 class="sticky-title">%3$s</h3>
<div class="sticky-excerpt">
%4$s
</div>
</a>
</aside>
', get_permalink(), $entry_img, get_the_title(), get_the_excerpt() );
}
echo add_filter( 'glckprss_sticky_posts_query__post_template', 'your_sticky_posts_query__post_template', 10, 6 );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment