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.

  • anybody can help? – 吉 宁 Feb 9 '17 at 10:26

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:


if ( ! current_user_can( 'unfiltered_html' ) ) {

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;
  • Amazing work.Thank you !! By using the 'wp_kses_allowed_html' now I can add that custom attribute.One thing that's good about worpdress is they don't close all the doors.Thank you again ,fellow developer. – 吉 宁 Feb 10 '17 at 3:46
  • One more thing,'post_author' => 1 in my args indeed is the super admin. – 吉 宁 Feb 10 '17 at 4:25
  • You're welcome, glad to hear it helped @NingJi – birgire Feb 10 '17 at 8:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.