<?php
/**
* Genesis Framework.
*
* WARNING: This file is part of the core Genesis Framework. DO NOT edit this file under any circumstances.
* Please do all modifications in the form of a child theme.
*
* @package Genesis\Loops
* @author StudioPress
* @license GPL-2.0-or-later
* @link https://my.studiopress.com/themes/genesis/
*/
add_action( 'genesis_loop', 'genesis_do_loop' );
/**
* Attach a loop to the `genesis_loop` output hook so we can get some front-end output.
*
* @since 1.1.0
*/
function genesis_do_loop() {
if ( is_page_template( 'page_blog.php' ) ) {
$include = genesis_get_option( 'blog_cat' );
$exclude = genesis_get_option( 'blog_cat_exclude' ) ? explode( ',', str_replace( ' ', '', genesis_get_option( 'blog_cat_exclude' ) ) ) : '';
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// Easter Egg.
$query_args = wp_parse_args(
genesis_get_custom_field( 'query_args' ),
array(
'cat' => $include,
'category__not_in' => $exclude,
'showposts' => genesis_get_option( 'blog_cat_num' ),
'paged' => $paged,
)
);
genesis_custom_loop( $query_args );
} else {
genesis_standard_loop();
}
}
/**
* Standard loop, meant to be executed without modification in most circumstances where content needs to be displayed.
*
* It outputs basic wrapping HTML, but uses hooks to do most of its content output like title, content, post information
* and comments.
*
* The action hooks called are:
*
* - `genesis_before_entry`
* - `genesis_entry_header`
* - `genesis_before_entry_content`
* - `genesis_entry_content`
* - `genesis_after_entry_content`
* - `genesis_entry_footer`
* - `genesis_after_endwhile`
* - `genesis_loop_else` (only if no posts were found)
*
* @since 1.1.0
*
* @return void Return early after legacy loop if not supporting HTML5.
*/
function genesis_standard_loop() {
// Use old loop hook structure if not supporting HTML5.
if ( ! genesis_html5() ) {
genesis_legacy_loop();
return;
}
if ( have_posts() ) {
/**
* Fires inside the standard loop, before the while() block.
*
* @since 2.1.0
*/
do_action( 'genesis_before_while' );
while ( have_posts() ) {
the_post();
/**
* Fires inside the standard loop, before the entry opening markup.
*
* @since 2.0.0
*/
do_action( 'genesis_before_entry' );
genesis_markup( array(
'open' => '<article %s>',
'context' => 'entry',
) );
/**
* Fires inside the standard loop, to display the entry header.
*
* @since 2.0.0
*/
do_action( 'genesis_entry_header' );
/**
* Fires inside the standard loop, after the entry header action hook, before the entry content.
* opening markup.
*
* @since 2.0.0
*/
do_action( 'genesis_before_entry_content' );
genesis_markup( array(
'open' => '<div %s>',
'context' => 'entry-content',
) );
/**
* Fires inside the standard loop, inside the entry content markup.
*
* @since 2.0.0
*/
do_action( 'genesis_entry_content' );
genesis_markup( array(
'close' => '</div>',
'context' => 'entry-content',
) );
/**
* Fires inside the standard loop, before the entry footer action hook, after the entry content.
* opening markup.
*
* @since 2.0.0
*/
do_action( 'genesis_after_entry_content' );
/**
* Fires inside the standard loop, to display the entry footer.
*
* @since 2.0.0
*/
do_action( 'genesis_entry_footer' );
genesis_markup( array(
'close' => '</article>',
'context' => 'entry',
) );
/**
* Fires inside the standard loop, after the entry closing markup.
*
* @since 2.0.0
*/
do_action( 'genesis_after_entry' );
} // End of one post.
/**
* Fires inside the standard loop, after the while() block.
*
* @since 1.0.0
*/
do_action( 'genesis_after_endwhile' );
} else { // If no posts exist.
/**
* Fires inside the standard loop when they are no posts to show.
*
* @since 1.0.0
*/
do_action( 'genesis_loop_else' );
} // End loop.
}
/**
* XHTML loop.
*
* This is called by {@link genesis_standard_loop()} if the child theme does not support HTML5.
*
* It is a standard loop, and is meant to be executed, without modification, in most circumstances where content needs
* to be displayed.
*
* It outputs basic wrapping HTML, but uses hooks to do most of its content output like title, content, post information
* and comments.
*
* The action hooks called are:
*
* - `genesis_before_post`
* - `genesis_before_post_title`
* - `genesis_post_title`
* - `genesis_after_post_title`
* - `genesis_before_post_content`
* - `genesis_post_content`
* - `genesis_after_post_content`
* - `genesis_after_post`
* - `genesis_after_endwhile`
* - `genesis_loop_else` (only if no posts were found)
*
* @since 2.0.0
*
* @global int $loop_counter Increments on each loop pass.
*/
function genesis_legacy_loop() {
global $loop_counter;
$loop_counter = 0;
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
/**
* Fires inside the legacy loop, before the post opening markup.
*
* @since 1.0.0
*/
do_action( 'genesis_before_post' );
printf( '<div class="%s">', implode( ' ', get_post_class() ) );
/**
* Fires inside the legacy loop, before the post title hook, after the post opening markup.
*
* @since 1.0.1
*/
do_action( 'genesis_before_post_title' );
/**
* Fires inside the legacy loop, to display the post title.
*
* @since 1.1.0
*/
do_action( 'genesis_post_title' );
/**
* Fires inside the legacy loop, after the post title hook.
*
* @since 1.0.1
*/
do_action( 'genesis_after_post_title' );
/**
* Fires inside the legacy loop, before the post content hook, before the post content opening markup.
*
* @since 1.0.0
*/
do_action( 'genesis_before_post_content' );
echo '<div class="entry-content">';
/**
* Fires inside the legacy loop, inside the post content markup.
*
* @since 1.1.0
*/
do_action( 'genesis_post_content' );
echo '</div>'; // End .entry-content.
/**
* Fires inside the legacy loop, after the post content hook, before the post content closing markup.
*
* @since 1.0.0
*/
do_action( 'genesis_after_post_content' );
echo '</div>'; // End .entry.
/**
* Fires inside the legacy loop, after the post closing markup.
*
* @since 1.0.0
*/
do_action( 'genesis_after_post' );
$loop_counter++;
} // End of one post.
/** This action is documented in lib/structure/loops.php */
do_action( 'genesis_after_endwhile' );
} else { // If no posts exist.
/** This action is documented in lib/structure/loops.php */
do_action( 'genesis_loop_else' );
} // End loop.
}
/**
* Custom loop, meant to be executed when a custom query is needed.
*
* It accepts arguments in query_posts style format to modify the custom `WP_Query` object.
*
* It outputs basic wrapping HTML, but uses hooks to do most of its content output like title, content, post information,
* and comments.
*
* The arguments can be passed in via the `genesis_custom_loop_args` filter.
*
* The action hooks called are the same as {@link genesis_standard_loop()}.
*
* @since 1.1.0
*
* @global WP_Query $wp_query Query object.
* @global int $more
*
* @param array $args Loop configuration.
*/
function genesis_custom_loop( $args = array() ) {
global $wp_query, $more;
$defaults = array(); // For forward compatibility.
$args = apply_filters( 'genesis_custom_loop_args', wp_parse_args( $args, $defaults ), $args, $defaults );
$wp_query = new WP_Query( $args );
// Only set $more to 0 if we're on an archive.
$more = is_singular() ? $more : 0;
genesis_standard_loop();
// Restore original query.
wp_reset_query();
}
/**
* The grid loop - a specific implementation of a custom loop.
*
* Outputs markup compatible with a Feature + Grid style layout.
* All normal loop hooks present, except for `genesis_post_content`.
*
* The arguments can be filtered by the `genesis_grid_loop_args` filter.
*
* @since 1.5.0
*
* @global array $_genesis_loop_args Associative array for grid loop configuration.
*
* @param array $args Associative array for grid loop configuration.
*/
function genesis_grid_loop( $args = array() ) {
// Global vars.
global $_genesis_loop_args;
// Parse args.
$args = apply_filters(
'genesis_grid_loop_args',
wp_parse_args(
$args,
array(
'features' => 2,
'features_on_all' => false,
'feature_image_size' => 0,
'feature_image_class' => 'alignleft',
'feature_content_limit' => 0,
'grid_image_size' => 'thumbnail',
'grid_image_class' => 'alignleft',
'grid_content_limit' => 0,
'more' => __( 'Read more', 'genesis' ) . '…',
)
)
);
// If user chose more features than posts per page, adjust features.
if ( get_option( 'posts_per_page' ) < $args['features'] ) {
$args['features'] = get_option( 'posts_per_page' );
}
// What page are we on?
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// Potentially remove features on page 2+.
if ( $paged > 1 && ! $args['features_on_all'] ) {
$args['features'] = 0;
}
// Set global loop args.
$_genesis_loop_args = $args;
// Remove some unnecessary stuff from the grid loop.
remove_action( 'genesis_before_post_title', 'genesis_do_post_format_image' );
remove_action( 'genesis_post_content', 'genesis_do_post_image' );
remove_action( 'genesis_post_content', 'genesis_do_post_content' );
remove_action( 'genesis_post_content', 'genesis_do_post_content_nav' );
remove_action( 'genesis_entry_header', 'genesis_do_post_format_image', 4 );
remove_action( 'genesis_entry_content', 'genesis_do_post_image', 8 );
remove_action( 'genesis_entry_content', 'genesis_do_post_content' );
remove_action( 'genesis_entry_content', 'genesis_do_post_content_nav', 12 );
remove_action( 'genesis_entry_content', 'genesis_do_post_permalink', 14 );
// Custom loop output.
add_filter( 'post_class', 'genesis_grid_loop_post_class' );
add_action( 'genesis_post_content', 'genesis_grid_loop_content' );
add_action( 'genesis_entry_content', 'genesis_grid_loop_content' );
// The loop.
genesis_standard_loop();
// Reset loops.
genesis_reset_loops();
remove_filter( 'post_class', 'genesis_grid_loop_post_class' );
remove_action( 'genesis_post_content', 'genesis_grid_loop_content' );
remove_action( 'genesis_entry_content', 'genesis_grid_loop_content' );
}
/**
* Filter the post classes to output custom classes for the feature and grid layout.
*
* Based on the grid loop args and the loop counter.
*
* Applies the `genesis_grid_loop_post_class` filter.
*
* The `&1` is a test to see if it is odd. `2&1 = 0` (even), `3&1 = 1` (odd).
*
* @since 1.5.0
*
* @global array $_genesis_loop_args Associative array for grid loop config.
* @global WP_Query $wp_query Query object.
*
* @param array $classes Existing post classes.
* @return array Amended post classes.
*/
function genesis_grid_loop_post_class( array $classes ) {
global $_genesis_loop_args, $wp_query;
$grid_classes = array();
if ( $_genesis_loop_args['features'] && $wp_query->current_post < $_genesis_loop_args['features'] ) {
$grid_classes[] = 'genesis-feature';
$grid_classes[] = sprintf( 'genesis-feature-%s', $wp_query->current_post + 1 );
$grid_classes[] = $wp_query->current_post&1 ? 'genesis-feature-even' : 'genesis-feature-odd';
} elseif ( $_genesis_loop_args['features']&1 ) {
$grid_classes[] = 'genesis-grid';
$grid_classes[] = sprintf( 'genesis-grid-%s', $wp_query->current_post - $_genesis_loop_args['features'] + 1 );
$grid_classes[] = $wp_query->current_post&1 ? 'genesis-grid-odd' : 'genesis-grid-even';
} else {
$grid_classes[] = 'genesis-grid';
$grid_classes[] = sprintf( 'genesis-grid-%s', $wp_query->current_post - $_genesis_loop_args['features'] + 1 );
$grid_classes[] = $wp_query->current_post&1 ? 'genesis-grid-even' : 'genesis-grid-odd';
}
return array_merge( $classes, apply_filters( 'genesis_grid_loop_post_class', $grid_classes ) );
}
/**
* Output specially formatted content, based on the grid loop args.
*
* @since 1.5.0
*
* @global array $_genesis_loop_args Associative array for grid loop configuration.
*/
function genesis_grid_loop_content() {
global $_genesis_loop_args;
if ( in_array( 'genesis-feature', get_post_class() ) ) {
if ( $_genesis_loop_args['feature_image_size'] ) {
$image = genesis_get_image( array(
'size' => $_genesis_loop_args['feature_image_size'],
'context' => 'grid-loop-featured',
'attr' => genesis_parse_attr( 'entry-image-grid-loop', array(
'class' => $_genesis_loop_args['feature_image_class'],
) ),
) );
printf( '<a href="%s">%s</a>', get_permalink(), $image );
}
if ( $_genesis_loop_args['feature_content_limit'] ) {
the_content_limit( (int) $_genesis_loop_args['feature_content_limit'], genesis_a11y_more_link( esc_html( $_genesis_loop_args['more'] ) ) );
} else {
the_content( genesis_a11y_more_link( esc_html( $_genesis_loop_args['more'] ) ) );
}
} else {
if ( $_genesis_loop_args['grid_image_size'] ) {
$image = genesis_get_image( array(
'size' => $_genesis_loop_args['grid_image_size'],
'context' => 'grid-loop',
'attr' => genesis_parse_attr( 'entry-image-grid-loop', array(
'class' => $_genesis_loop_args['grid_image_class'],
) ),
) );
printf( '<a href="%s">%s</a>', get_permalink(), $image );
}
if ( $_genesis_loop_args['grid_content_limit'] ) {
the_content_limit( (int) $_genesis_loop_args['grid_content_limit'], genesis_a11y_more_link( esc_html( $_genesis_loop_args['more'] ) ) );
} else {
the_excerpt();
printf( '<a href="%s" class="more-link">%s</a>', get_permalink(), genesis_a11y_more_link( esc_html( $_genesis_loop_args['more'] ) ) );
}
}
}
add_action( 'genesis_after_post', 'genesis_add_id_to_global_exclude', 9 );
add_action( 'genesis_after_entry', 'genesis_add_id_to_global_exclude', 9 );
/**
* Modify the global $_genesis_displayed_ids each time a loop iterates.
*
* Keep track of what posts have been shown on any given page by adding each ID to a global array, which can be used any
* time by other loops to prevent posts from being displayed twice on a page.
*
* @since 2.0.0
*
* @global array $_genesis_displayed_ids Array of displayed post IDs.
*/
function genesis_add_id_to_global_exclude() {
global $_genesis_displayed_ids;
$_genesis_displayed_ids[] = get_the_ID();
}