• Hi,

    For some post i have some metadata array with names like:
    foo[0][extra][title]
    foo[1][extra][title]
    foo[2][extra][title]

    When the post is saved, data is serialized to JSON.
    It’s work well, except for preview with “foo” in revision field.

    i get the error:

    
    Warning: trim() expects parameter 1 to be string, array given in /.../wp-includes/formatting.php on line 4627
    Call Stack
    #	Time	Memory	Function	Location
    1	0.0015	447728	{main}( )	.../post.php:0
    2	0.1322	8584392	post_preview( )	.../post.php:272
    3	0.1326	8589312	wp_create_post_autosave( )	.../post.php:1741
    4	0.1356	8640896	normalize_whitespace( )	.../post.php:1680
    5	0.1356	8640896	trim ( )	.../formatting.php:4627
    

    I have this warning and a new revision is always created because the last saved “foo” data is in JSON and the “foo” data for preview is not filtered and stay an array. I have reading the code but i see no way to apply the same filter “save_post” like i do for the insert and update post.
    I have missed something or i submit a patch for doing this thing ?

Viewing 4 replies - 1 through 4 (of 4 total)
  • Moderator bcworkz

    (@bcworkz)

    Maybe try hooking ‘wp_creating_autosave’ and serializing your metadata in $_POST?

    Thread Starter mkdgs

    (@mkdgs)

    Unfortunaly ‘wp_creating_autosave’ is triggered few line after normalize_whitespace().

    // Store one autosave per author. If there is already an autosave, overwrite it.
    	if ( $old_autosave = wp_get_post_autosave( $post_id, $post_author ) ) {
    		$new_autosave = _wp_post_revision_data( $post_data, true );
                    
    		$new_autosave['ID'] = $old_autosave->ID;
    		$new_autosave['post_author'] = $post_author;
    
    		// If the new autosave has the same content as the post, delete the autosave.
    		$post = get_post( $post_id );
    		$autosave_is_different = false;
                   
    		foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) {
    			if ( normalize_whitespace( $new_autosave[ $field ] ) != normalize_whitespace( $post->$field ) ) {
                              
    				$autosave_is_different = true;
    				break;
    			}
    		}
    
    		if ( ! $autosave_is_different ) {
    			wp_delete_post_revision( $old_autosave->ID );
    			return 0;
    		}
    
    		/**
    		 * Fires before an autosave is stored.
    		 *
    		 * @since 4.1.0
    		 *
    		 * @param array $new_autosave Post array - the autosave that is about to be saved.
    		 */
    		do_action( 'wp_creating_autosave', $new_autosave );
    
    		return wp_update_post( $new_autosave );
    	}
    Thread Starter mkdgs

    (@mkdgs)

    I think to try something ugly like:

    in /my_themes/function.php

    if (isset($_POST['wp-preview']) && $_POST['wp-preview'] == 'dopreview') {
      //   filter and serialise my meta  
      foreach ( $_POST['meta'] as $k => $v ) {    
             if( $k === 'my_meta') {
                $_POST['meta'][$k] = json_encode($v);
             }
      }
    }

    And serialize in json only if it’s not already a string in my save_post filter.

    Moderator bcworkz

    (@bcworkz)

    Is there a particular reason you use json_encode() at all? When you pass an array to update_post_meta(), it is automatically serialized with serialize(). Then when you retrieve it it is automatically restored as an array. You don’t need to worry about it, it just works.

    If you must have JSON, perhaps using a different hook that works in all cases would be the solution. “update_post_meta” perhaps? Unverified, but worth looking into I think.

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘For post preview, a way to filter metadata value (like save_post hook)’ is closed to new replies.