WP Discourse: advanced custom filter for discourse_publish_format_html

I’m having trouble with a custom filter for posting content to Discourse. My installation is the exact same website mentioned by Marco in the topic below (resolved):

Also, because this is a multisite where we want the same WP Discourse customizations across all, instead of using each individual theme’s functions.php file, I created a single file plugin exclusively for WP Discourse template customizations inside the /wp-contents/mu-plugins/ folder. This file includes custom output for discourse_replies_html, discourse_no_replies_html, and discourse_publish_format_html, in that order. I don’t think this my issue, but this is where the code l want to talk about lives.

At the moment, I’m attempting to publish 2 different CPTs and WP native posts to discourse. Before incorporating the CPTs into the mix, I was using the following with expected results:

Now I am experiencing a couple of issues in getting my custom filter to work as I’d like with the CPTs. After referencing [link 1] and [link 2], I successfully added a check for if the post type was ‘event’ (generated by Events Manager) and outputting custom fields associated with that CPT. However, I wanted the default to remain oneboxed, but the aforementioned onebox code snippet returns nothing but a “See Full Post” link. (Clicking to see full post does load the content of the post, fwiw.)

If I replace the onebox code snippet with something else, like

// else return
    ob_start();
    ?>

    <small>Originally published at: {blogurl}</small><br><br>
    <?php echo $image ?>
    {excerpt}

    <?php
    $output = ob_get_clean();
    
    return $output; 

I’ll get the “Originally published at…” + the excerpt, but not $image (based on [link 3] for checking whether a post in fact has a featured image). I want to have the onebox back if the post type doesn’t match my CPTs, but this curious lack of picking up the featured image in this experiment has me thinking I have a mistake in my logic. I will post the full code I am using at the end of this overview.

My second issue is that my Toolset-generated CPT ‘groups’ doesn’t publish with it’s associated if post-type customizations. I have the correct post type name, as I’m using it in the theme’s functions.php for a different purpose but with expected results in that context. I based this if section on my successful if ( 'event' === $post->post_type) section, but referencing fields that pertain to the ‘groups’ CPT. Even if I have the custom field names wrong in this section, I expect to see at least the featured image and excerpt, etc, as I did when I was working out how to get the right fields for the ‘event’ CPT. Instead, this ‘groups’ CPT is using the // else return output. So, for example, when I was attempting to use the onebox code snippet, it also only returned the “See Full Post” button (and would also successfully load the post content when clicked).

In conclusion, I’ll reiterate that the if ( 'event' === $post->post_type) section totally works as intended and I’ve tested many different events with different date settings, with and without the Video Conference URL event attribute. It renders the $image as expected. Given those hidden fields, it was all sorts of fun to work out, and I hope my code helps someone else struggling to integrate Events Manager with Discourse. However, something seems to be amiss in the combination of that with the rest of what I’m trying to do here, and I hope someone can see where I’m going wrong. Here’s the full function with the non-onebox default:

// when publishing a post to Discourse
function cosmos_custom_publish_format_html() {
	global $post;
	
	// if featured image is present, use it
	if ( has_post_thumbnail() ) {
		$image = "{thumbnail}<br><br>";
	} else {
		$image = "";
	}

    // if post is an event, get the custom field information
    if ( 'event' === $post->post_type) {
    	$startdate = get_post_meta($post->ID, '_event_start_date', true);
    	$starttime = get_post_meta($post->ID, '_event_start_time', true);
    	$enddate = get_post_meta($post->ID, '_event_end_date', true);
    	$endtime = get_post_meta($post->ID, '_event_end_time', true);
        $startdateformatted = date('j M Y', strtotime($startdate));
        $starttimeformatted = date('g:i a', strtotime($starttime));
        $enddateformatted = date('j M Y', strtotime($enddate));
        $endtimeformatted = date('g:i a', strtotime($endtime));
        $eventallday = get_post_meta($post->ID, '_event_all_day', true);
        $eventtimezone = get_post_meta($post->ID, '_event_timezone', true);
        $videoconferenceurl = get_post_meta($post->ID, 'Video Conference URL', true);
        
        if ($startdate == $enddate && $eventallday !== '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} @ {$starttimeformatted} - {$endtimeformatted} {$eventtimezone}";
        }
        
        if ($startdate !== $enddate && $eventallday !== '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} @ {$starttimeformatted} - {$enddateformatted} {$endtimeformatted} {$eventtimezone}";
        }
        
        if ($startdate == $enddate && $eventallday == '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} <i>All Day</i>";
        }
        
        if ($startdate !== $enddate && $eventallday == '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} - {$enddateformatted}";
        }
        
        if ($videoconferenceurl !== '') {
          $videoconferenceurlformatted = "<strong>Video Conference Link:</strong> {$videoconferenceurl}<br><br>";
        }
        
        if ($videoconferenceurl == '') {
          $videoconferenceurlformatted = "";
        }
                
        ob_start();
        ?>
	  
        <small>Originally published at: {blogurl}</small><br><br>
        <?php echo $image ?>
        <?php echo $eventinfo ?><br>
        <?php echo $videoconferenceurlformatted ?>
        {excerpt}
	  
        <?php 
        $output = ob_get_clean();
        
        return $output;
    }
    
    // if post is a group, get the custom field information
    if ( 'groups' === $post->post_type) {
    	$groupstartdate = get_post_meta($post->ID, 'wpcf-start-date', true);
    	$groupenddate = get_post_meta($post->ID, 'wpcf-end-date', true);
        $groupstartdateformatted = date('j M Y', strtotime($groupstartdate));
        $groupenddateformatted = date('j M Y', strtotime($groupenddate));
        $groupvideoconferenceurl = get_post_meta($post->ID, 'wpcf-video-conference-url', true);
        
        if ($groupenddate !== '') {
          $groupinfo = "<strong>Start Date:</strong> {$groupstartdateformatted}<br /><strong>End Date:</strong> {$groupenddateformatted}";
        }
        
        if ($groupenddate == '') {
          $groupinfo = "<strong>Start Date:</strong> {$groupstartdateformatted}<br /><strong>End Date:</strong> TBD";
        }
        
        if ($groupvideoconferenceurl !== '') {
          $groupvideoconferenceurlformatted = "<strong>Video Conference Link:</strong> {$groupvideoconferenceurl}<br><br>";
        }
        
        if ($groupvideoconferenceurl == '') {
          $groupvideoconferenceurlformatted = "";
        }
        	
        ob_start();
        ?>
	  
        <small>Originally published at: {blogurl}</small><br><br>
        <?php echo $image ?>
        <?php echo $groupinfo ?><br>
        <?php echo $groupvideoconferenceurlformatted ?>
        {excerpt}
	  
        <?php
        $output = ob_get_clean();
	  
        return $output;
    }   
      
    // else return
    ob_start();
    ?>

    <small>Originally published at: {blogurl}</small><br><br>
    <?php echo $image ?>
    {excerpt}

    <?php
    $output = ob_get_clean();
    
    return $output; 

}
add_filter( 'discourse_publish_format_html', 'cosmos_custom_publish_format_html' );
4 Likes

I’m a new user, so I got a message I had too many links in my post, so

Link 1:

Link 2:

Link 3:
https://meta.discourse.org/t/wp-discourse-template-customization/50754/13

I’m running into the same trouble right now (inconsistently), but I’m not using a custom post type or anything else odd in my setup. I think it’s only with scheduled posts that it happens for me.

Same, we just published a normal blog post, with ‘discourse_publish_format_html’ filtered as follows:

function ccmm_discourse_publish_format_html()
{
	ob_start();
	echo "<h2>View on the Cracking the Code Platform:</h2><br />\n\n";
	the_permalink(); // The post's WordPress permalink
	$output = ob_get_clean();
	return $output;
}
add_filter('discourse_publish_format_html', 'ccmm_discourse_publish_format_html');

And only the “view on platform” part worked, not the_permalink().

@simon I believe this is the first blog post we’ve published since upgrading to WP 5.0 (w/ Gutenberg editor), I wonder if that could have something to do with this?

1 Like

Yes, when I try to use the_permalink() or get_permalink() with a post published using the Block Editor it’s returning an empty string. When I publish the same post with the Classic Editor plugin, the permalink is retrieved. I’ll look into this.

Edit: it looks like the post_id needs to be passed to the custom template function for this to work with the Block Editor. I’ll need to make a small update to the plugin for this to be possible. When that’s been done, you’ll have to update your custom template if you want to use the permalink.

I’ll try to get this done by tomorrow. In the meantime, installing the Classic Editor plugin and publishing your posts with it should solve the problem.

4 Likes

I think the Block Editor might be the source of the issues I’m having, then. I kept playing around and even if I reduce my entire function to the same output regardless of post type, I realized I can get the featured image to show if I use {thumbnail} but not if I try the global $post; with either if ( has_post_thumbnail() ) or if (has_post_thumbnail( $post->ID ) ). I couldn’t understand why the ‘event’ CPT was picking up the featured image just fine either way, but I have realized the difference is indeed: the events are still using the Classic Editor, while the posts and groups I’ve been testing with are using the Block Editor. This must be also why the entire if ( 'groups' === $post->post_type) wasn’t working for me either.

1 Like

Yes, when the Block Editor is used, posts are published through the WordPress REST API. This means that global $post doesn’t return anything.

When I update the template so that it accepts a $post_id parameter, what you are trying to do should work. I’ll update it tomorrow, and provide some example code.

3 Likes

We have the block editor disabled. Not sure why this has happened occasionally, but all I can figure out that’s different from the other posts is that it is scheduled. Would that possibly mean it’s done via REST API?

Yes, if permalinks are failing to appear for scheduled posts, this is most likely the problem. The next update should make it possible for you to fix the issue.

3 Likes

If you update to WP Discourse Version 1.8.2, you can now pass a $post_id parameter to the publish_format_html template. Doing this will make it possible to access the current post when the post is published with the Block Editor, or through the REST API.

Here’s a quick example of how to use it. I’ll add more detailed examples and update WP Discourse template customization very soon.

function wpdc_custom_publish_format_html( $output, $post_id ) {
	ob_start();
    the_permalink( $post_id );
	$output = ob_get_clean();
	return $output;
}
add_filter( 'discourse_publish_format_html', 'wpdc_custom_publish_format_html', 10, 2 );

To have access to the $post_id parameter, you need to be sure to call add_filter with the priority and accepted_args parameters from the example.

For cases where you are trying to access properties of the current post, instead of using global $post use

$post = get_post( $post_id );
4 Likes

The updated plugin and modified function/filter have solved my original issues. I was playing some more with the output and decided to move the <small>Originally published at: {blogurl}</small> to below the excerpt. Even if I reduce it to {excerpt}{blogurl}, the url prints as plain text (no link). Works if changed to {blogurl}{excerpt}, why is that?

For others, here’s how you’d modify my original block of code to work with the updated plugin, but this time with the desired oneboxed default :slight_smile::

// when publishing a post to Discourse
function cosmos_custom_publish_format_html( $output, $post_id ) {
	$post = get_post( $post_id );
	
	// if featured image is present, use it
	if ( has_post_thumbnail( $post_id ) ) {
		$image = "{thumbnail}<br><br>";
	} else {
		$image = "";
	}

    // if post is an event, get the custom field information
    if ( 'event' === $post->post_type) {
    	$startdate = get_post_meta($post->ID, '_event_start_date', true);
    	$starttime = get_post_meta($post->ID, '_event_start_time', true);
    	$enddate = get_post_meta($post->ID, '_event_end_date', true);
    	$endtime = get_post_meta($post->ID, '_event_end_time', true);
        $startdateformatted = date('j M Y', strtotime($startdate));
        $starttimeformatted = date('g:i a', strtotime($starttime));
        $enddateformatted = date('j M Y', strtotime($enddate));
        $endtimeformatted = date('g:i a', strtotime($endtime));
        $eventallday = get_post_meta($post->ID, '_event_all_day', true);
        $eventtimezone = get_post_meta($post->ID, '_event_timezone', true);
        $videoconferenceurl = get_post_meta($post->ID, 'Video Conference URL', true);
        
        if ($startdate == $enddate && $eventallday !== '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} @ {$starttimeformatted} - {$endtimeformatted} {$eventtimezone}";
        }
        
        if ($startdate !== $enddate && $eventallday !== '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} @ {$starttimeformatted} - {$enddateformatted} {$endtimeformatted} {$eventtimezone}";
        }
        
        if ($startdate == $enddate && $eventallday == '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} <i>All Day</i>";
        }
        
        if ($startdate !== $enddate && $eventallday == '1') {
          $eventinfo = "<strong>Date/Time:</strong> {$startdateformatted} - {$enddateformatted}";
        }
        
        if ($videoconferenceurl !== '') {
          $videoconferenceurlformatted = "<strong>Video Conference Link:</strong> {$videoconferenceurl}<br><br>";
        }
        
        if ($videoconferenceurl == '') {
          $videoconferenceurlformatted = "";
        }
                
        ob_start();
        ?>
	  
        <small>Originally published at: {blogurl}</small><br><br>
        <?php echo $image ?>
        <?php echo $eventinfo ?><br>
        <?php echo $videoconferenceurlformatted ?>
        {excerpt}
	  
        <?php 
        $output = ob_get_clean();
        
        return $output;
    }
    
    // if post is a group, get the custom field information
    if ( 'groups' === $post->post_type) {
    	$groupstartdate = get_post_meta($post->ID, 'wpcf-start-date', true);
    	$groupenddate = get_post_meta($post->ID, 'wpcf-end-date', true);
        $groupstartdateformatted = date('j M Y', strtotime($groupstartdate));
        $groupenddateformatted = date('j M Y', strtotime($groupenddate));
        $groupvideoconferenceurl = get_post_meta($post->ID, 'wpcf-video-conference-url', true);
        
        if ($groupenddate !== '') {
          $groupinfo = "<strong>Start Date:</strong> {$groupstartdateformatted}<br /><strong>End Date:</strong> {$groupenddateformatted}";
        }
        
        if ($groupenddate == '') {
          $groupinfo = "<strong>Start Date:</strong> {$groupstartdateformatted}<br /><strong>End Date:</strong> TBD";
        }
        
        if ($groupvideoconferenceurl !== '') {
          $groupvideoconferenceurlformatted = "<strong>Video Conference Link:</strong> {$groupvideoconferenceurl}<br><br>";
        }
        
        if ($groupvideoconferenceurl == '') {
          $groupvideoconferenceurlformatted = "";
        }
        	
        ob_start();
        ?>
	  
        <small>Originally published at: {blogurl}</small><br><br>
        <?php echo $image ?>
        <?php echo $groupinfo ?><br>
        <?php echo $groupvideoconferenceurlformatted ?>
        {excerpt}
        	  
        <?php
        $output = ob_get_clean();
	  
        return $output;
    }   
      
    // else return
    ob_start();
    the_permalink( $post_id );
	$output = ob_get_clean();
	return $output;
    
}
add_filter( 'discourse_publish_format_html', 'cosmos_custom_publish_format_html', 10, 2  );
4 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.