Home > OS >  Output certain product page on homepage / WooCommerce shortcode not working properly
Output certain product page on homepage / WooCommerce shortcode not working properly

Time:10-12

I need to output a certain product page on the homepage. add_rewrite_rule doesn't work for homepage for any reason ( there are actually no rewrite rules for the homepage in the database, WordPress seems to use some other functions to query the homepage):

//works fine
add_rewrite_rule( 'certainproductpage/?$',
    'index.php?post_type=product&name=certainproduct',
    'top'
);
//does not work 
add_rewrite_rule( '', //tried everything like "/", "/?$" etc
    'index.php?post_type=product&name=certainproduct',
    'top'
);

After spending way too much time looking through wp / wc core code and stackoverflow I came across an alternative. I can simply add a shortcode in the content of the page I need to be the homepage and a product page at the same time: [product_page id=815]. Indeed it works great, but only if the shortcode is added in the admin editor or is stored in the database (post_content). If I try to call the shortcode manually on the page template ( page-certainproductpage.php) then it outputs the product page without some necessary stuff (PayPal, PhotoSwipe and Gallery js). Weirdly enough, if I keep the shortcode in the content (via Gutenberg / Code Editor) but don't call the_content and only echo the shortcode then everything works fine:

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

get_header( 'shop' );

//works fine only if the same shortcode is within the certainproductpage's content
echo do_shortcode("[product_page id='815']");
//the_content();

get_footer( 'shop' );

Also when I try to add the shortcode via the_content filter hook before the do_shortcode function is applied in core's default-filters.php ($priority < 11), then I get only the error:

NOTICE: PHP message: PHP Fatal error:  Maximum execution time of 30 seconds exceeded in /var/www/html/wp-includes/functions.php on line 5106

Unfortunately there is no stack trace logged. And the function around line 5107 is wp_ob_end_flush_all which is called on shutdown from default-filters.php

echo do_shortcode(apply_filters('the_content', "[product_page id=815]")); did not help either (same incomplete output as with echo do_shortcode("[product_page id=815]");)

Also totally weird: When I compare the string of the content from the editor and the string of the shortcode added programmatically it is equal!:

add_filter( "the_content", function ( $content ){
            $wtf = "<!-- wp:paragraph -->
<p>[product_page id=815]</p>
<!-- /wp:paragraph -->";
            $result = $wtf === $content;
            ?><pre><?php var_dump($result)?></pre><?php
            return $content;
}, 1 );

But if I replace return $content with return $wtf - I get the maximimum exucution time exceeded error.

So how can I properly output a product page on the homepage ("/") or how can I get the same result with the shortcode when applied within the the_content filter as when just adding the shortcode in the (Gutenberg) editor?

CodePudding user response:

Ok, found a bit of a hacky solution. I just check on every page load whether the homepage is currently queried or not. Then I get the page content and check if it already contains the shortcode. If not then the page content gets updated in the database with the shortcode appended.

//it has to be a hook which loads everything needed for the wp_update_post function 
//but at the same time has not global $post set yet
//if global $post is already set, the "certainproductpage"  will load content not modified by the following code
add_action( "wp_loaded", function () {
    //check if homepage
    //there seems to be no other simple method to check which page is currently queried at this point
    if ( $_SERVER["REQUEST_URI"] === "/" ) {
        $page    = get_post(get_option('page_on_front'));
        $product = get_page_by_path( "certainproduct", OBJECT, "product" );

        if ( $page && $product ) {
            $page_content       = $page->post_content;
            $product_id         = $product->ID;
            $shortcode          = "[product_page id=$product_id]";
                    
            //add shortcode to the database's post_content if not already done
            $contains_shortcode = strpos( $page_content, $shortcode ) > - 1;
            if ( ! $contains_shortcode ) {
                $shortcode_block = <<<EOT
<!-- wp:shortcode -->
{$shortcode}
<!-- /wp:shortcode -->
EOT;
                $new_content     = $page_content . $shortcode_block;

                wp_update_post( array(
                    'ID'           => $page->ID,
                    'post_content' => $new_content,
                    'post_status'  => "publish"
                ) );
            }
        }
    }
} );

CodePudding user response:

I'd recommend one step at a time. First of all, does this work?

add_filter( "the_content", function ( $content ) {
   $content .= do_shortcode( '[product_page id=815]' );
   return $content;
}, 1 );

This should append a product page to every WordPress page/post.

If it works, then you need to limit it to the homepage only, by using is_front_page() conditional in case it's a static page:

add_filter( "the_content", function ( $content ) {
   if ( is_front_page() ) {
      $content .= do_shortcode( '[product_page id=815]' );
   }
   return $content;
}, 1 );

If this works too, then we'll see how to return a Gutenberg paragraph block, but not sure why you'd need that, so maybe give us more context

  • Related