From 057c6cfac519074accd14f2519b3c96247799264 Mon Sep 17 00:00:00 2001 From: Herb Miller Date: Wed, 11 Nov 2020 18:12:25 +0000 Subject: [PATCH] Issue #166 - prevent infinite recursion processing post_content in [bw_pages] --- includes/bw_formatter.php | 12 +++++++--- includes/bw_posts.php | 47 ++++++++++++++++++++++++++++++++++----- shortcodes/oik-pages.php | 15 ++++++++----- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/includes/bw_formatter.php b/includes/bw_formatter.php index 65bd61a..ec463f1 100644 --- a/includes/bw_formatter.php +++ b/includes/bw_formatter.php @@ -177,9 +177,15 @@ function bw_field_function_featured_image( $post, &$atts, $f ) { * */ function bw_content( $post ) { - $content = $post->post_content; - bw_trace2(); - $content = bw_get_the_content( $content ); + if ( bw_process_this_post( $post->ID ) ) { + $content = $post->post_content; + bw_trace2(); + $content = bw_get_the_content($content); + bw_clear_processed_posts( $post->ID ); + } else { + $content = bw_report_recursion_error( $post ); + } + return( $content ); } diff --git a/includes/bw_posts.php b/includes/bw_posts.php index 82a4499..df13a9d 100644 --- a/includes/bw_posts.php +++ b/includes/bw_posts.php @@ -83,12 +83,44 @@ function bw_process_this_post( $id ) { /** * Clear the array of processed posts * - * + * This should only be done at the top level. + * When the current content is the first item in the array. + * Can we perform a pop to get the same result? + * + * @param integer|null $postID - if set then we pop the most recently added value else clear the lot */ -function bw_clear_processed_posts() { +function bw_clear_processed_posts( $postID=null) { global $processed_posts; - $processed_posts = array(); - bw_trace2( $processed_posts, "cleared", false, BW_TRACE_DEBUG ); + if ( $postID ) { + array_pop( $processed_posts ); + } else { + $processed_posts = array(); + } + bw_trace2( $processed_posts, "cleared", true, BW_TRACE_DEBUG ); + //bw_backtrace(); +} + +/** + * Reports a recursion error to the user. + * + * If WP_DEBUG is true then additional information is displayed. + * + * @param $post + * @return string + */ +function bw_report_recursion_error( $post, $type='post_content') { $content = array(); + $content[] = __( "Content not available; already processed.", "oik" ); + if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { + $content[] = ''; + $content[] = $type; + $content[] = $post->post_title; + $content[] = '(' . $post->ID . ')'; + global $processed_posts; + $content[] = implode( ',', $processed_posts ); + $content[] = ''; + } + $content = implode( ' ', $content); + return $content; } /** @@ -193,8 +225,11 @@ function bw_excerpt( $post ) { bw_more_text( $content['more_text'] ); $excerpt = bw_get_the_excerpt( $excerpt ); + bw_clear_processed_posts( $post->ID ); } else { - $excerpt = "post already processed: " . $post->ID; + $excerpt = bw_report_recursion_error( $post, 'post_excerpt' ); + //$excerpt = "Excerpt not available; already processed for: " . $post->post_title . ' ' . $post->ID; + } // bw_current_post_id(); return( $excerpt ); @@ -452,7 +487,7 @@ function bw_get_posts( $atts=null ) { // If you want to retrieve the current post use exclude=-1 // // Note: This supports multiple IDs, comma separated - $attr['exclude'] = bw_array_get_dcb( $attr, "exclude", NULL, "bw_global_post_id" ); + $attr['exclude'] = bw_array_get_dcb( $attr, "exclude", NULL, "bw_current_post_id" ); // set suppress_filters to false when global bw_filters is set global $bw_filter; diff --git a/shortcodes/oik-pages.php b/shortcodes/oik-pages.php index 677cade..b2fd7a9 100644 --- a/shortcodes/oik-pages.php +++ b/shortcodes/oik-pages.php @@ -66,20 +66,23 @@ function bw_query_post_formatter( $atts ) { */ function bw_pages( $atts = NULL ) { $atts['numberposts'] = bw_array_get( $atts, 'numberposts', 10 ); + $cp = bw_current_post_id(); $posts = bw_get_posts( $atts ); + // If we get into an infinite loop during development then you'll want to uncomment this line. + //return( "shortcircuit"); bw_trace( $posts, __FUNCTION__, __LINE__, __FILE__, "posts" ); if ( $posts ) { - $cp = bw_current_post_id(); + + // Don't process the current post inside the loop + bw_process_this_post( $cp ); $bw_post_formatter = bw_query_post_formatter( $atts ); foreach ( $posts as $post ) { bw_current_post_id( $post->ID ); $bw_post_formatter( $post, $atts ); } - bw_current_post_id( $cp ); - //bw_current_post_id(); - - bw_clear_processed_posts(); - } + + + } bw_current_post_id( $cp ); return( bw_ret() ); }