Support » Developing with WordPress » Customizing preview for custom post type

  • Hello,

    I created a custom post type (“comparator”), it has some acf fields, I use it as a shortcode, and I fetch some so extra data from an api and save them as meta when saving the post.
    Everything works very well.

    This post type will never be displayed alone, only through a shortcode.
    But I want to make the “review” works, so the editor can see his works before saving or updating.
    I made this, but it has several flaws I think:

    Public function comparator_filter_content( $content ) {
        if ( ! is_singular( 'comparator' ) ) {
            return $content;
        // Get the preview id
        $preview_post_list = get_posts( [
            'post_status'    => 'any',
            'post_parent'    => intval( $_GET['preview_id'] ),
            'post_type'      => 'revision',
            'sort_column'    => 'ID',
    	'sort_order'     => 'desc',
    	'posts_per_page' => 1
        $preview_post = $preview_post_list[ array_key_last( $preview_post_list ) ];
        $preview_post_id  = $preview_post->ID;
        // Preview doesn't get the google sheet, so we do it ourselves :
        import_sheet( $preview_post_id );
        // Get the data and launch the display of the comparator, as I do in the function comparator_shortcode

    1. I’m not sure this function will be called only when previewing. Since I use my comparators only in shortcode it should be ok. But for instance, what about revisions? Or other things? Is there no better hooks that I could use to deal with in this “preview case”?
    2. Using array_key_last is a big asumption. I have no idea if my preview will always be the last of this preview_post_list.
    3. As said, I would like the revision to work, so it may interfere at some point

    That’s it, maybe I’m totally in the wrong direction, any help appreciated!

    • This topic was modified 3 weeks, 6 days ago by f34nc015.
    • This topic was modified 3 weeks, 6 days ago by bcworkz. Reason: code fixed
Viewing 7 replies - 1 through 7 (of 7 total)
  • Moderator bcworkz


    I’m not sure I follow. I think you wish your CPT’s preview page to look like the shortcode output, even though in practice no visitor will ever see this post as a stand alone page like we might see in the preview. If I’m right, your CPT needs a custom template page that will be used to generate the preview. Pretty much all the template needs to do is call the shortcode directly with echo do_shortcode('[your-shortcode]');, though you might want to include theme header and footer as well.

    To get WP to use this template instead of the default single post template, name your template file with the format "single-{$post_type}.php" and keep it in your theme’s folder with the other templates. Unless you have a custom theme, it’s recommended that you create a child theme in which to save custom code and templates so your work is not overwritten when the theme updates.

    BTW, when you post code in these forums, please demarcate with backticks or use the “code” button. If you fail to do so, the forum parser will corrupt your code. I fixed your OP code for you.

    Hi bcworkz
    Thank you very much for your answer, and for fixing my post 🙂

    It works, and resolve my problem 1. Nice!

    There are still 2 problems:
    – this solution makes a file of my plugin out of the plugin folder, so it’s less easy for git, and less easy to distribute. I can live with it though.
    – it doesn’t solve my problem 2., I still have to get the id of the post preview in a quite cumbersome way.
    (I can easily get the post id of the “real” post, but not the one of this preview. I need this id to save in the meta data of the preview post (not the “real” post) the up-to-date values of the api)

    If you have ideas for these 2 problems?

    In all case thanks a lot again for your help!

    Moderator bcworkz


    Yeah, a custom template from plugins is not that easy to accomplish. You are correct in that placing files in other user’s theme folders is a terrible practice. For one’s own site you can do whatever you want. Not so on other’s sites. The solution is to use the “template_include” filter and watch for template calls involving your CPT. Alter the template path to lead to the template in your plugin instead of the theme folder. When using this filter, it doesn’t matter much what you name your template file. The problem is the template path WP passes is ambiguous about post type. However, you should be able to get the post type from the global $wp_query->get() or get_queried_object().

    Templates still work the same way whether for preview or published page. The current post ID is available in “The Loop”. While it seems silly to run The Loop for a single post, it has the side effect of populating several useful globals. Then you can get the desired ID from the global $post object. If you prefer to not run The Loop for any reason, the current post ID can be obtained with get_queried_object_id(). This may not be a post ID with some requests, but it surely is for a single post request or preview.

    Thanks to this object, $wp_query, I have flag ‘is_preview’ which looks reliable in the filter_content hook. So I used that and didn’t used your template solution.

    In some other place in the code, this flag is not reliable…
    Actually, it depends if you load the preview from the button, or if you reload the page (took me some time to figure this out..!)
    It’s a problem because I need to do some data validation in another place, for updating and for previewing. But I managed by just doing extra useless validation, and duplicate code..

    At the end it works like that.

    For the preview id: nope, I never got it, except with my solution. I ran the loop, checked all the variable you mentionned: it’s just never here, only the parent id.

    At the end it’s a bit frustrating, ugly, not robust… But ok
    I think we are missing a simple way to do that, or wordpress misses a mecanism to deal with preview..?

    • This reply was modified 3 weeks, 4 days ago by f34nc015.
    Moderator bcworkz


    I don’t know enough about your setup to be sure there is a better way or not. WP clearly knows the information you are looking for, or previews wouldn’t be possible at all. But where we could find that information, I don’t know. Since I cannot replicate your setup, I can’t investigate to find out for sure, I can only speculate. If all else fails, I’d think it could be extracted from the requested URL that is in $_SERVER.

    But if you have a solution that’s working, I’d say it’s not worth pursuing further, even if the solution is rather ugly.

    Well I dumped everything I could, this id is nowhere 🙂

    Actually I missed that there are informations in the url parameters, in particular a reliable ‘preview=true’

    In the end I’m sure these previews are not made to be customized at all, there a lot of scenarios, they load sometiems in different ways, …

    Yes, “just working” is good enoguh sometimes, but here it makes my system a bit unpredictable. I just spent one day on a bug which was in part related to this preview things. So…

    Anyway, thanks a lot for your help, it is hopefully finished now, and thanks to you.

    Best, good week-end

    • This reply was modified 3 weeks, 2 days ago by f34nc015.
    Moderator bcworkz


    You’re welcome. Causing unpredictable behavior would not generally be considered “just working”, but I suppose it depends on how objectionable the behavior is 🙂

Viewing 7 replies - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.