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