1

Block markup generally works in included PHP files. I prefer to use PHP includes in many cases as I can do more interesting things with it than I can with a template file (.html). I've just encountered an example where a macro works in a template file but not a PHP include: if I have the following content in a template file (let's call it templates/single-custom.html),

<!-- wp:shortcode -->[ai_playlist id="2276"]<!-- /wp:shortcode -->

the shortcode renders on the front end for the 'custom' post type. If, however, I have the following content in the template file,

<!-- wp:pattern {"slug":my-theme/hidden-my-include"} /-->

and then in patterns/hidden-my-include the same content,

<!-- wp:shortcode -->[ai_playlist id="2276"]<!-- /wp:shortcode -->

the output is the string,

[ai_playlist id="2276"]

I've fiddled with it a bit, and also tried,

<!-- wp:shortcode --><?php echo do_shortcode('[ai_playlist id="2276"]'); ?><!-- /wp:shortcode -->

in the include file, but it still just echoes the shortcode string (I've also tried do_shortcode without the wrapping echo).

Any ideas?


Edit:

I am going to leave the accepted answer, but others should know that the solution may or may not reintroduce a security vulnerability identified with rendering shortcodes in Block Themes: https://core.trac.wordpress.org/ticket/58333

Note that a workaround outlined by a user in the above-linked Trac issue is as follows (place in functions.php, or another included file in theme or plugin),

/*
Plugin Name: Fix shortcode
Plugin URI:
Description: Restore shortcode support on block templates https://core.trac.wordpress.org/ticket/58333
Author: Anderson Martins, Gabriel Mariani
Version: 0.2.0
*/

function parse_inner_blocks(&$parsed_block)
{
    if (isset($parsed_block['innerBlocks'])) {
        foreach ($parsed_block['innerBlocks'] as $key => &$inner_block) {
            if (!empty($inner_block['innerContent'])) {
                foreach ($inner_block['innerContent'] as &$inner_content) {
                    if (empty($inner_content)) {
                        continue;
                    }

                    $inner_content = do_shortcode($inner_content);
                }
            }
            if (isset($inner_block['innerBlocks'])) {
                $inner_block = parse_inner_blocks($inner_block);
            }
        }
    }

    return $parsed_block;
}

add_filter('render_block_data', function ($parsed_block) {

    if (isset($parsed_block['innerContent'])) {
        foreach ($parsed_block['innerContent'] as &$inner_content) {
            if (empty($inner_content)) {
                continue;
            }

            $inner_content = do_shortcode($inner_content);
        }
    }

    $parsed_block = parse_inner_blocks($parsed_block);

    return $parsed_block;
}, 10, 1);

2 Answers 2

1

Scenario: Gutenberg Blocks -> page.html has wp: include that includes a pattern file that has shortcode in it, the shortcode is not executed and comes back text only.

After reviewing and testing the above issue I realized the shorcode just does not run, I did find a workaround that allows the shortcode to run as expected.

Solution: Created my own tag that does the work and is formatted close to the original

replace this:

<!-- wp:pattern {"slug":my-theme/hidden-my-include"} /-->

With this:

<!-- wp:shortcode --> [wpb_run_pattern  pattern="hidden-my-include"] <!-- /wp:shortcode -->

Then create a file in your /patterns/ folder called hidden-my-include.php

Then add this code to it:

<!-- wp:shortcode --> [wpb_run_misc_shortcode] <!-- /wp:shortcode -->

Then, in your functions.php file put this code and run your files:



function run_pattern_shortcode_from_block_func($atts) {
    if (!isset($atts['pattern']) || !is_string($atts['pattern'])) {
        return 'Invalid input.';
    }

    // Sanitize the input
    $pattern_name = sanitize_text_field($atts['pattern']);

    // Construct the file path using WordPress functions
    $file_path = get_stylesheet_directory() . '/patterns/' . $pattern_name . '.php';

    // Check if file exists and is a PHP file
    if (file_exists($file_path) && pathinfo($file_path, PATHINFO_EXTENSION) === 'php') {
        $content = file_get_contents($file_path);

        $blocks = parse_blocks($content);
        $processed_content = '';

        foreach ($blocks as $block) {
            $block_content = render_block($block);
            $block_content = do_shortcode($block_content);
            $processed_content .= $block_content;
        }

        return $processed_content;
    } else {
        return 'File not found.';
    }
}
add_shortcode('wpb_run_pattern', 'run_pattern_shortcode_from_block_func');

function wpb_run_misc_shortcode_func() {
    // Example of escaping output
    return esc_html('Hello World !!!');
}
add_shortcode('wpb_run_misc_shortcode', 'wpb_run_misc_shortcode_func');


The shortcode in the patterns file ran as expected.

3
  • 1
    I appreciate the time you have put into this, but what you're effectively doing now is putting a shortcode in a file and feeding the contents of that file into do_shortcode. Maybe I haven't explained the situation well enough. My end goal is to parse the shortcode ID from the post meta and use that to render the appropriate shortcode. I cannot access post info from a template file, but I can from a .php include. Normally all the macros work when I do this, but doesn't for shortcode macro for some reason.
    – JDQ
    Jan 3 at 0:26
  • 2
    I understand what you are saying completely, but I did not see a solution to that problem, so I made it work just the same with proper security measures. ----- I am parsing the file using the proper method that the template system does not seem to do for some reason. Maybe it iwll be updated in a future update Jan 3 at 0:31
  • 2
    Okay, I've tinkered with it and get what you mean now. Excellent, thorough response. Thanks!
    – JDQ
    Jan 3 at 6:54
0

Did you try naming the html file .php templates/single-custom.php Also Remove the and comments from your PHP include file. Directly use the do_shortcode() function to render the shortcode. Here's the revised code for your PHP include:

<?php echo do_shortcode('[ai_playlist id="2276"]'); ?>
8
  • 1
    Thanks for your reply. Renaming the file .php defeats the file hierarchy of a block theme: everything in templates/ should be an .html file. Those aren't vanilla HTML comments: they're WordPress macros for a block theme. With or without the macros, if do_shortcode is called in a PHP include file that is included in a block template file, the shortcode does not render as expected.
    – JDQ
    Jan 2 at 19:17
  • Renaming it to php would be a good way to test if that is the issue, or if it is something else. If that is the issue then you can research that. Jan 2 at 19:40
  • The macro works in the template file (.html) but does not in the include file (.php). The do_shortcode function is also not working in the include file. If it did, I would happily use that instead of the macro.
    – JDQ
    Jan 2 at 19:51
  • I am looking in the theme files for the theme 2024 and all the files in the /patterns/ directory are using .php extensions. Am I missing something? Jan 2 at 20:25
  • 1
    Check out the templates/ directory. Create a new template file, and in that put the pattern macro (e.g. <!-- wp:pattern {"slug":my-theme/hidden-my-include"} /-->). Then, in my-theme/hidden-my-include.php, put the shortcode macro (you'll have to use a different shortcode that exists in your installation).
    – JDQ
    Jan 2 at 21:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.