Skip to content

Instantly share code, notes, and snippets.

@cdils cdils/loops.php Secret
Created Aug 13, 2019

Embed
What would you like to do?
Genesis 3.0 "loops" page
<?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_singular( 'page' ) && genesis_get_custom_field( 'query_args' ) ) {
$paged = get_query_var( 'paged' ) ?: 1;
/*
* Convert custom field string to args array.
*/
$query_args = wp_parse_args(
genesis_get_custom_field( 'query_args' ),
[
'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() {
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(
[
'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(
[
'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(
[
'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(
[
'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.
}
/**
* 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 = [] ) {
global $wp_query, $more;
$defaults = []; // For forward compatibility.
$args = apply_filters( 'genesis_custom_loop_args', wp_parse_args( $args, $defaults ), $args, $defaults );
$wp_query = new WP_Query( $args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Reset later.
// Only set $more to 0 if we're on an archive.
$more = is_singular() ? $more : 0; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Handle archives.
genesis_standard_loop();
// Restore original query.
wp_reset_query(); // phpcs:ignore WordPress.WP.DiscouragedFunctions.wp_reset_query_wp_reset_query -- Making sure the query is really reset.
}
/**
* The grid loop - a specific implementation of a custom loop.
*
* Outputs markup compatible with a Feature + Grid style layout.
*
* 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 = [] ) {
// Global vars.
global $_genesis_loop_args;
// Parse args.
$args = apply_filters(
'genesis_grid_loop_args',
wp_parse_args(
$args,
[
'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' ) . '&#x02026;',
]
)
);
// 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' ) ?: 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_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_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_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 = [];
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(), true ) ) {
if ( $_genesis_loop_args['feature_image_size'] ) {
$image = genesis_get_image(
[
'size' => $_genesis_loop_args['feature_image_size'],
'context' => 'grid-loop-featured',
'attr' => genesis_parse_attr(
'entry-image-grid-loop',
[
'class' => $_genesis_loop_args['feature_image_class'],
]
),
]
);
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $image is html markup.
printf( '<a href="%s">%s</a>', esc_url( 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(
[
'size' => $_genesis_loop_args['grid_image_size'],
'context' => 'grid-loop',
'attr' => genesis_parse_attr(
'entry-image-grid-loop',
[
'class' => $_genesis_loop_args['grid_image_class'],
]
),
]
);
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $image is html markup.
printf( '<a href="%s">%s</a>', esc_url( 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();
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- genesis_a11y_more_link returns html markup.
printf( '<a href="%s" class="more-link">%s</a>', esc_url( get_permalink() ), genesis_a11y_more_link( esc_html( $_genesis_loop_args['more'] ) ) );
}
}
}
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();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.