wp_insert_post is automatically modifying my post content

Say I have a post content with a img tag like this:

<img alt="wikipic" class="aligncenter lazy" width="728" height="546" src="http://www.12reads.cn/wiki/wp-content/themes/baike/images/loading.gif"  data-original="http://news.12reads.cn/wp-content/uploads/2017/02/928_2.jpg" >

wp_insert_post will automatically change it to:

<img alt="wikipic" class="aligncenter lazy" width="728" height="546" src="http://www.12reads.cn/wiki/wp-content/themes/baike/images/loading.gif">

The data-original=”http://news.12reads.cn/wp-content/uploads/2017/02/928_2.jpg” part is gone.

The args I used in wp_insert_post is as below:

$post_info = array(
'post_status' => 'draft', 
'post_type' => 'knowhow', 
'post_author' => 1,
'ping_status' => get_option( 'default_ping_status' ), 
'comment_status' => get_option( 'default_comment_status' ),
'post_pingback' => get_option( 'default_pingback_flag' ),
'post_parent' => 0,
'menu_order' => 0, 
'to_ping' => '', 
'pinged' => '', 
'post_password' => '',
'guid' => '', 
'post_content_filtered' => '', 
'post_excerpt' => $post_excerpt, 
'import_id' => 0,
'post_content' => $post_content, 
'post_title' => $post_title, 
'post_category' => array($post_category_id),
'post_name' => trim($post_name),
//'post_date_gmt' => get_gmt_from_date(gmdate('Y-m-d H:i:s', $post_time + ( get_option( 'gmt_offset' ) * 3600 ))),
//'post_date' => gmdate('Y-m-d H:i:s', $post_time + ( get_option( 'gmt_offset' ) * 3600 )), 
'tags_input' => array_unique(array_filter(explode(',', $tags))),
//'tags_input' => $tags,
);
$pid = wp_insert_post($post_info); 

I checked out https://codex.wordpress.org/Writing_Code_in_Your_Posts and also https://stackoverflow.com/questions/10942170/how-to-prevent-tinymce-editor-within-wordpress-from-changing-the-html-markup with no luck.

And also I have confirmed below:

1.It’s not a browser thing.

2.None of these three work.

remove_filter('the_content', 'wpautop');
remove_filter("the_content", "wptexturize");
remove_filter("the_content", "convert_chars");

3.This only happens when using wp_insert_post to add a post instead of the mannual way.

In the end of the day ,I know I can always achieve this by using js and the content filter.

But I just want to figure out why wordpress strips out the custom img attributes.

Does anyone knows why,I looked everywhere.pls.

1
1

The documentation for wp_insert_post() says:

wp_insert_post() passes data through sanitize_post(), which itself
handles all necessary sanitization and validation (kses, etc.).

If we dig through it, we can find the responsible filter as:

add_filter('content_save_pre', 'wp_filter_post_kses');

within the kses_init_filters() function.

When the kses is initialized with kses_init() it runs:

kses_remove_filters();

if ( ! current_user_can( 'unfiltered_html' ) ) {
    kses_init_filters();
}

where we can see that it’s only activated if the current user doesn’t have the unfiltered_html capability. So most likely you’re running your post inserts that way.

Instead of removing the corresponding content_save_pre filter, during this post insert, we should consider allowing the data-original image attribute. At least that sounds a little bit more secure.

The kses default allowed <img> attributes are:

'img' => array(
    'alt'      => true,
    'align'    => true,
    'border'   => true,
    'height'   => true,
    'hspace'   => true,
    'longdesc' => true,
    'vspace'   => true,
    'src'      => true,
    'usemap'   => true,
    'width'    => true,
),

We can modify it to support the data-original attribute, through the wp_kses_allowed_html filter:

// Modify allowed HTML through custom filter
add_filter( 'wp_kses_allowed_html', 'wpse_kses_allowed_html', 10, 2 );

// Insert
$pid = wp_insert_post($post_info); 

// Remove custom filter
remove_filter( 'wp_kses_allowed_html', 'wpse_kses_allowed_html', 10 );

where our custom callback is:

function wpse_kses_allowed_html( $allowed, $context )
{
    if( 'post' !== $context )
        return $allowed;

    $allowed['img']['data-original'] = true;

    return $allowed;
}

Leave a Comment