Customize the structure of WP Discourse templates

The WP Discourse plugin uses HTML templates to add markup to Discourse comments for publishing on WordPress and to WordPress posts for publishing on Discourse. The text content of these templates can be customized on the plugin’s options page. To change the structure of a templates requires you to add a function to your theme’s functions.php file This howto will explain how to do that.

The templates

In the plugin’s code, the templates are static functions that return a mixture of html and template tags.

Available templates:

  • replies_html - the outer wrapper for the comments section
  • no_replies_html - creates a ‘start the discussion’ link that links back to the Discourse forum
  • bad_response_html - displayed when there is a configuration error with Discourse
  • comment_html - formats each comment as a list item
  • participant_html - displays the user avatars for the participants in the topic
  • publish_format_html - used to format the WordPress post for publishing on Discourse

The template code can be found in the html-templates.php file in the the plugin’s github repo

The filters

At the end of each template function, the markup that is about to be output by the function is filtered through a WordPress hook. This makes it possible for a WordPress theme to grab the HTML and alter or replace it, and then return it to the function.

Available filters

  • discourse_replies_html - filters replies_html
  • discourse_no_replies_html - filters no_replies_html
  • discourse_no_connection_html - filters bad_response_html
  • discourse_comment_html - filters comment_html
  • discourse_participant_html - filters participant_html
  • discourse_publish_format_html - filters publish_format_html

How to use the filters to customize a template

Customizing each of the templates follows the exact same pattern. First, create a function in your theme’s functions.php file to generate the new or altered template:

// Customizes the no_replies_html template.

function my_namespace_no_replies_html( $input ) {
    ob_start();

    ?>

    // The content you want to output goes here.
    // This function just echoes its input, it will be returned unchanged.
    echo $input;

    <?php
    $output = ob_get_clean();

    return $output;
}
// Hook into the function from the plugin's code.
add_filter(  'discourse_no_replies_html', 'my_namespace_no_replies_html' );

In the above function, $input is that value that is passed to your function from the wp-discourse no_replies_html() function. The calls to ob_start() and ob_get_clean() are used for output buffering. What output buffering does is store the HTML that is generated by the function in a variable that is then passed to $output with the call to ob_get_clean. Output buffering has to be used for these functions so that the markup’s template tags are returned in a way that allows them to be processed later.

The call to add_filter( 'discourse_no_replies_html', 'my_namespace_no_replies_html' ); is used to hook the plugin’s no_replies_html() function. What ‘hook’ means is that your function will be called from inside the plugin’s no_replies_html() function when it is run. The $input argument that your function takes is passed to it from inside the plugin’s no_replies_html() function.

You can hook into any of plugin’s template functions by adding a call to:

add_filter( 'discourse_filter_name', 'your_function_name' );

Note: replace my_namespace in the example functions with your namespace. It’s a convention used in WordPress to avoid function name collisions.

Template tags

The templates use ‘tags’ to insert information from the database into the markup. You can use these tags in your custom templates.

Examples

Add the featured_image to the publish template

The default publish_format_html template returns the markup for the post that is to be published to Discourse. The template has the following template tags available to it: {excerpt}, {blogurl}, {author}, {thumbnail}, {featuredimage}.

The post’s featured image can be added to the template with the {featuredimage} template tag. This can be done in a custom template by copy and pasting the publish_format_html() function from it’s github page, renaming the function by adding a namespace, adding the {featuredimage} template tag, removing the call to apply_filters from the function’s return statement, and then hooking into the new function. Note: you also need to remove the self::get_text_options() statement from the original function.

// Adds the featured image to the post that is published to Discourse.
function my_namespace_publish_format( $input, $post_id ) {
	$post = get_post( $post_id );
	ob_start();
	?>
    <small>Originally published at: {blogurl}</small><br>
	<?php
	$featured_image = get_the_post_thumbnail( $post );
	if ( ! empty( $featured_image ) ) {
		echo $featured_image;
	}
	?>
    {excerpt}

	<?php
	$output = ob_get_clean();

	return $output;
}

add_filter( 'discourse_publish_format_html', 'my_namespace_publish_format', 10, 2 );

Publish the WordPress post as a onebox on Discourse

This customization will cause the WordPress post to be published as a onebox on your forum.

Before making this customization, check that oneboxes are created on your forum when you add the URL of one of your WordPress posts to Discourse.

function wpdc_custom_publish_format_html( $input, $post_id ) {
	$permalink = get_the_permalink( $post_id );
	ob_start();
	echo $permalink;
	$output = ob_get_clean();

	return $output;
}
add_filter( 'discourse_publish_format_html', 'wpdc_custom_publish_format_html', 10, 2 );

Remove the avatar image from the comments_html template

The default comments_html template displays a user avatar for each comment that is published. If you are publishing many comments on your WordPress site, this will result in many http requests to Discourse to retrieve the avatar images. To remove the avatar image from the template, first copy and paste the code from the github repo into your theme’s functions.php file and rename it. Then, remove the img tag that displays the avatar. Then add a filter hook for your new function by making a call to add_filter() that references the 'discourse_comment_html' hook and your function name. In your new function’s return statement, remove the call to apply_filter that is in the plugin’s comment_html() function.

function my_namespace_comment_html_without_avatar( $input ) {
    ob_start();
    ?>
    <li class="comment even thread-even depth-1">
        <article class="comment-body">
            <footer class="comment-meta">
                <div class="comment-author vcard">
                    <b class="fn"><a href="{topic_url}" rel="external"
                                     class="url">{username}</a></b>
                    <span class="says">says:</span><!-- screen reader text -->
                </div>
                <!-- .comment-author -->
                <div class="comment-metadata">
                    <time pubdate="" datetime="{comment_created_at}">{comment_created_at}</time>
                </div>
                <!-- .comment-metadata -->
            </footer>
            <!-- .comment-meta -->
            <div class="comment-content">{comment_body}</div>
            <!-- .comment-content -->
        </article>
        <!-- .comment-body -->
    </li>
    <?php
    $output = ob_get_clean();

    return $output;
}

add_filter( 'discourse_comment_html', 'my_namespace_comment_html_without_avatar' );

Note: the plugin’s template functions are using a static function self::get_text_options() to get text options that have been configured on the plugin’s options page. This function is not available to you in your custom templates. If you are customizing the templates by copying the plugin’s code, be sure to remove these function calls from your templates. A simple approach would be to replace them with the text that you would like to appear in that section.

Remove the ‘participants’ section

This removes the ‘participants’ section from the replies_html template.

function my_namespace_remove_participants_html( $input ) {
    ob_start();
    ?>
    <div id="comments" class="comments-area discourse-comments-area">
        <h2 class="comments-title discourse-comments-title">Notable Replies</h2><!-- Your 'Notable Replies' heading -->
        <ol class="comment-list">{comments}</ol>
        <div class="respond comment-respond">
            <h3 id="reply-title" class="comment-reply-title">
                Continue the discussion at <!-- Your 'Continue the discussion' text -->
                <a href="{topic_url}">
                    {discourse_url_name}
                </a>
            </h3>
            <p class="more-replies">{more_replies}</p>
        </div>
    </div>
    <?php
    $output = ob_get_clean();

    return $output;
}
add_filter( 'discourse_replies_html', 'my_namespace_remove_participants_html' );

Look at the source code

To see the HTML that is in each template, and get a list of template tags that can be each template, please look at the html-templates.php source code on github.

For tips and tricks on customizing the plugin in your theme’s functions.php file see WP Discourse Plugin tips and tricks

「いいね!」 25

皆さん、こんにちは。フォーラム投稿の内容を <noindex>{content}</noindex> タグで囲む方法を教えてください。試したところ、致命的なエラーが発生しました。

function wpdc_custom_publish_format_html( $input, $post_id ) {
    ob_start();
    ?>
    <noindex>
    <small>
        <?php echo esc_html( self::Vget_text_options( 'published-at-text' ) ); ?>
        {blogurl}
    </small>
    <br>
    {excerpt}
    </noindex>
    <?php
    $output = ob_get_clean();
    return $output;
}
add_filter( 'discourse_publish_format_html', 'wpdc_custom_publish_format_html', 10, 2 );

この問題を解決するのを手伝っていただけますか?

テーマまたはプラグインに wpdc_custom_publish_format_html という名前の既存の関数はありますか?もしあれば、それがクリティカルエラーの原因となります。

「いいね!」 1

返信ありがとうございます。WP-discourse プラグインを使用しています。この場合、関数を forum_publish_format_html と異なる方法で呼び出しました。


これにより、次のエラーが発生しました。

クラススコープが無効な場合に「self」を使用することはできません

編集: 解決しました。同じ課題を持つ他の人のために、正しいコードを以下に貼り付けました。

@angus 少し調べたところ、WP Discourse のコメントで gravatar のサイズを上書きする場所を見つけました。

functions.php に以下を追加しましたが、エラーが発生しました(以下参照)。

// カスタマイズされた comment_html テンプレート。

function my_wpd_comment_html( $input ) {
	ob_start();
	?>
	<li class="comment <?php echo $even ? 'even' : 'odd'; ?> depth-1">
		<article class="comment-body">
			<footer class="comment-meta">
				<div class="comment-author vcard">
					<img alt="Avatar for {username}" src="{avatar_url}" class="avatar avatar-64 photo avatar-default"
						 height="24"
						 width="24">
					<b class="fn"><a href="{topic_url}" rel="external"
									 class="url">{username}</a></b>
					<span class="says screen-reader-text"><?php echo esc_html( 'says:', 'wp-discourse' ); ?></span><!-- screen reader text -->
				</div>
				<div class="comment-metadata">
					<time datetime="{comment_created_at}">{comment_created_at}</time>
				</div>
			</footer>
			<div class="comment-content">{comment_body}</div>
		</article>
	</li>
	<?php
	$output = ob_get_clean();
	return $output;
}

// プラグインのコードから関数にフックします。
add_filter( 'discourse_comment_html', 'my_wpd_comment_html' );

編集: うまくいきました!
しかし、500 エラーが発生します。エラー表示は有効にしていません。構文エラーを確認するために、サンドボックスで設定して有効にするところです。しかし、明白な修正があればと思い、ここにコードを投稿しました。

ありがとうございます。

「いいね!」 1

管理画面に「テンプレート」タブのようなものを設け、WP Discourse のテンプレートコードを編集する機能の追加を検討しています。これは、ローコードのクライアント向けであり、本番サイトでのバージョン管理の問題を回避するためです。もちろん、コードは適切にサニタイズ/検証し、データベースに保存し、安全に取得するなどを行います。

もしこの機能(レビューなどを条件とする)を開発してプルリクエストを提出した場合、プラグインとして検討されるでしょうか?

「いいね!」 1