Gutenberg custom blocks php render issue - wordpress

I'm creating some custom dynamic blocks for WordPress Gutenberg editor (following this link ).
I use the PHP render for these blocks, meaning I have this code on save:
save: function( props ) {
// Rendering in PHP
return;
},
The render function is called via this callback:
register_block_type( 'my-plugin/latest-post', array(
'render_callback' => 'my_plugin_render_block_latest_post',
) );
I'm not gonna post the function code since is irrelevant in this case. (I do
a WP_Query and display some custom post data and return a html code),
My problem is that WP Gutenberg takes the output from the function and adds
<p> and <br> tags (classic wpautop behaviour).
My question is: How can I disable that only for custom blocks? I could use this:
remove_filter( 'the_content', 'wpautop' );
but I don't want to alter the default behaviour.
Some additional findings. The php function use for block rendering use get_the_excerpt(). Once this function is used (and i assume is happening for get_the_content() ) the wpautop filter is applied and the html markup of the block gets messed up.
I don't know if this is a bug or the expected behavior but is there any simple solution to this that does not involve removing the filter ? ( For ex on themeforest removing this filter is not allowed.)

We have by default:
add_filter( 'the_content', 'do_blocks', 9 );
add_filter( 'the_content', 'wpautop' );
add_filter( 'the_excerpt', 'wpautop' );
...
I skimmed through the do_blocks() (src) and if I understand correctly it removes the wpautop filtering if the content contains any blocks, but restores the filter for any subsequent the_content() usage.
I wonder if your render block callback contains any such subsequent usage, as you mentioned a WP_Query loop.
One could e.g. try:
$block_content = '';
remove_filter( 'the_content', 'wpautop' ); // Remove the filter on the content.
remove_filter( 'the_excerpt', 'wpautop' ); // Remove the filter on the excerpt.
... code in callback ...
add_filter( 'the_content', 'wpautop' ); // Restore the filter on the content.
add_filter( 'the_excerpt', 'wpautop' ); // Restore the filter on the excerpt.
return $block_content;
within your my_plugin_render_block_latest_post() callback code.

Related

How to disable <p> tags without disable <br> tags in wordpress

I want to remove only <p> tags without remove <br> tags in pages wordpress, i only found remove <br> tags and keep <p>, every i use remove_filter still remove <br> tags.
You can use strip_tags php function which removes php and html tags from a string.
This is for displaying the content: the_content()
https://developer.wordpress.org/reference/functions/the_content/
And this to retrieve the post content: get_the_content()
https://developer.wordpress.org/reference/functions/get_the_content/
(1) First way doing this: Change the page template of your theme
So in your page template, you normally will find the function call the_content().
But we need to retrieve the post content, remove the paragraph tags, and then display the "cleaned" content.
For that we will not use the_content() but use get_the_content().
<?php
$my_content = get_the_content();
$clean_content = strip_tags($my_content , '<p>');
echo $clean_content;
?>
We saved the post content in a variable (get_the_content is returning a string) and then used strip_tags to remove the tags. We just need to echo the "cleaned" content.
(2) Alternative way doing this: Change the output of the_content() function
If you want to use the_content() function or do not have the possibility to change the theme files, you can make use of the_content filter in wordpress.
function remove_tags_from_the_content( $content ) {
return strip_tags( $content, '<p>' );
}
add_filter( 'the_content', 'remove_tags_from_content' );
This way everytime your the_content() function is called, the filter will be applied so the function returns your cleaned version.
(3) Another way: Remove auto paragraphs in wordpress content
Wordpress adds paragraph tags to the content by default. You can disable this behaviour (remove the filter) by putting the follwing code in the functions.php file of your theme:
// Prevent wordpress from adding paragraph tags on pages
function disable_pages_wpautop( $content ) {
if ( is_singular( 'page' ) ) {
remove_filter( 'the_content', 'wpautop' );
}
return $content;
}
add_filter( 'the_content', 'disable_pages_wpautop', 0 );
You can replace the if condition with the post type you like:
if ( is_singular( 'your-post-type' ) )
If you want to remove the paragraphs in the content and excerpt in pages, posts and other post-types, you can get rid of the if-clause:
function disable_wpautop_all( $content ) {
remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );
return $content;
}
add_filter( 'the_content', 'disable_wpautop_all', 0 );

WordPress shortcode with multiline parameters

How to insert shortcode with more parameters and multiline into WordPress page?
Backslash used to work as a line separator:
[my_shorcode parameter_1=10 \
parameter_2=20 \
parameter_3="test"]
But it doesn't work in the latest WordPress version. I want to use more lines for better readability of the code.
Thanks for #Arvind K. for advice
This is not good idea since it breaks normal post editing behavior.
Rather you should try to keep shortcodes "short
I've been solving this problem by the way
1. I have used shortcode this way [my-shortcode id="1"]
2. I have created post type My Shortcodes
3. The id for step 1. is the My Shortcodes post id
4. In ACF (Custom fields) I have created fields for My Shortcodes
(Field - is shortcode param)
5. Then you could use your My Shortcodes post for getting fields.
add_shortcode( 'my-shortcode', function ( $atts, $content ) {
$custom_shortcode_id = $atts['id'];
$parameter_1 = get_field( 'parameter_1', $custom_shortcode_id );
$parameter_2 = get_field( 'parameter_2', $custom_shortcode_id );
return "Your shortcode content $parameter_1, $parameter_2";
} );
I removed 2 WordPress filters and it works fine now.
remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );

How to stop wrapping comments in p tag

After I update a comment in wordpress, the comment is wrapped with p tag.
remove_filter( 'pre_comment_content', 'wp_filter_kses');
return wp_update_comment( $data );
I searched for this problem and I found that I should remove the wpautop filter, and so I did.
remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );
remove_filter( 'pre_comment_content', 'wp_filter_kses');
return wp_update_comment( $data );
but the problem didn't disappear. comments are still wrapped in <p> tags after update. Does anyone know how to solve this problem?
Another way to do this is by manipulating the comment content once saved.
// you can modify the execution order of this hook
add_action( 'comment_post', 'comment_manipulation', 10, 2 );
function comment_manipulation( $comment_ID, $comment_approved ) {
// you can check for comment approved here
// get the comment data based on ID
$comment = get_comment( $comment_ID, ARRAY_A );
// $comment['comment_content'] is accessible here.
}
Then you can just do a search and replace for the paragraph tags, and update the comment with the new content in the database.
Edit
Updated code that does all of the steps, however this will only remove p tags from future comments, not existing ones. This is also untested so you'd have to double check yourself.
add_action( 'comment_post', 'comment_manipulation', 10, 2 );
function comment_manipulation( $comment_ID, $comment_approved ) {
// get the comment data based on ID
$comment = get_comment( $comment_ID, ARRAY_A );
// remove only the first <p> you can find
$new_comment = str_replace( "<p>", '', $comment['comment_content'], 1);
// reverse the string
$reversed = strrev($new_comment);
// remove only the first >p/< you can find (</p> in reverse)
$new_reversed_comment = str_replace( ">p/<", '', $reversed, 1);
// reverse back
$new_comment = strrev($new_reversed_comment);
// let's update comment in database with new content
global $wpdb;
$comment_table = $wpdb->prefix . 'comments';
$wpdb->get_results(
"UPDATE $comment_table
SET comment_content = $new_comment
WHERE comment_ID = $comment_ID"
);
}
Comments are not wrapped while saving comments. Please make sure that the wpautop filter is not active when you output comments on page. remove_filter( 'the_content', 'wpautop' ); should be placed directly in functions.php if you want to disable wpautop filter everywhere otherwise it should be placed somewhere before the code relevant to comments output in template and that added again after the relevant code is finished.

How can I get the default content of WordPress post?

Is there a way where I can get the default output of the_content in WordPress post? Some of the plugin is using add_filter to the content to add their desired result like related post plugins where they add the result at the end of the content of a post. What I want to happen is to get the default formatting functions of WordPress core without any additional filters from other plugins.
You can use remove filter function.
remove_filter( $tag, $function_to_remove, $priority );
For more please refer below link
https://codex.wordpress.org/Function_Reference/remove_filter
You can use the_content filter itself to get the post object or the content , you can modify it or you can unhook it and again hook it as per your requirement .
If I have understood your requirement this link will help you, if you need something different please ask me.
Guys thanks for responding to my question I think I got it somehow but need to run more test. What I did was I replicate the process on how the_content() function of WordPress work. Base from my research there are 10 default filters coming from WordPress core you can see on this link: read here
I just created my own function like the_content() from WordPress and apply the default filters to my own function. Put this code in your functions.php
if(!function_exists(default_post_content)){
function default_post_content( $more_link_text = null, $strip_teaser = false) {
$content = get_the_content( $more_link_text, $strip_teaser );
$content = apply_filters( 'default_post_content', $content );
$content = str_replace( ']]>', ']]>', $content );
echo do_shortcode($content);
}
add_filter( 'default_post_content', array( $wp_embed, 'run_shortcode' ), 8 );
add_filter( 'default_post_content', array( $wp_embed, 'autoembed'), 8 );
add_filter ( 'default_post_content', 'wptexturize');
add_filter ( 'default_post_content', 'convert_smilies');
add_filter ( 'default_post_content', 'convert_chars');
add_filter ( 'default_post_content', 'wpautop');
add_filter ( 'default_post_content', 'shortcode_unautop');
add_filter ( 'default_post_content', 'prepend_attachment');
}
Then for example in your single page template(single.php) instead of using the usual the_content I can use my function default_post_content();. Now I don't need to worry about any of the plugins that create additional data to the_content() function.

WordPress How to Keep the_content filter for my cpt from affecting other posts on the same page

I am using a custom post type for the slide in my theme. I'm trying to remove wpautop from the cpt using the_content filter hook, and it works using the following code, but it also removes it wpautop from the other queries on the same page. Here is the code:
add_filter( 'the_content', 'remove_autop_for_post_type', 0 );
function remove_autop_for_post_type( $content )
{
if('par2_slide' === get_post_type(get_the_ID())){
remove_filter( 'the_content', 'wpautop' );
return $content;
};
return $content;
};
Adding a second condition to include "! is_main_query() like so:
if('par2_slide' === get_post_type(get_the_ID()) && ! is_main_query()){
causes the script to stop working. The query for my cpt to which this is supposed to apply is as follows:
function par2_slides_query () {
$args = array( 'post_type' => 'par2_slide');
$slides_loop = new WP_Query( $args );
while ( $slides_loop->have_posts() ) : $slides_loop->the_post();
echo '<li class="slide">';
the_content();
echo '</li>';
endwhile;
};
wpauto messes with the slide layout so I really need to filter the content for that particular post type to turn it off without turning it off for the instances of the_content on the rest of the page. It doesn't affect other pages, on the_content on the same page.
Re add the filter after your IF statement.
add_filter('the_content', 'wpautoop');
It removes it and returns the content IF par2_slide is the post type, and if it's not it adds the filter if it doesn't exist.

Resources