0

I'm trying to change the post visibility for my custom post type. On the edit.php screen the user can use a custom field to set the post type to normal or extended. That field shall work as abstraction for the post_status. However, running the following code inside the save_post action terminates as 500 Internal Server Error:

add_action( 'save_post', array( $this, 'save_meta_box' ), 10, 2 );
[...]
public function save_meta_box( $post_id, $post ) {
    [...]
    if( isset( $_POST['options'] ) ) {
        myplugin_set_options( $post_id, $_POST['options'] );

        // switch post visibility
        switch ( $_POST['options']['type'] ) {
            case 'normal':
                wp_update_post( array( 'ID' => $post_id, 'post_status' => 'private' ));
                break;
            case 'extended':
                wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ));
                break;
        }
    }

Running this code in the load-post.php does work fine. But I just want to set the visibility on saving not every time the post is opened. Any suggestions how to achieve this?

Thanks in Advance!

  • 1
    Watch out for recursive loops! That can happen when you call wp_update_post() inside the save_post hook. The remove_action() function will help you here. – birgire Jan 29 '15 at 11:02
  • Sounds plausibly. So just calling remove_action( 'save_post', 'save_meta_box' ); at the end of my save_meta_box function should work? Does not seem like. – Rubberducker Jan 29 '15 at 11:23
  • 1
    Try remove_action( 'save_post', array( $this, 'save_meta_box' ) ); since the callback is a class method. – birgire Jan 29 '15 at 11:26
  • -.- Thanks for to pick up the lost path for me! Please write a answer so I can accept it :) – Rubberducker Jan 29 '15 at 11:45
2

There is some information about this problem in the Action Reference for save post:

If you are calling a function such as wp_update_post that includes the save_post hook, your hooked function will create an infinite loop. To avoid this, unhook your function before calling the function you need, then re-hook it afterward.

So something like this should work:

[...]
add_action( 'save_post', array( $this, 'save_meta_box' ), 13, 2 );
[...]
public function save_meta_box( $post_id, $post ) {
    if ( isset( $_POST['options'] ) ) {
        myplugin_set_options( $post_id, $_POST['options'] );

        remove_action( 'save_post',  array( $this, 'save_meta_box' ), 13, 2 );

        // switch post visibility
        switch ( $_POST['options']['type'] ) {
            case 'normal':
                wp_update_post( array( 'ID' => $post_id, 'post_status' => 'private' ));
                break;
            case 'extended':
                wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ));
                break;
        }

        add_action( 'save_post', array( $this, 'save_meta_box' ), 13, 2 );
    }
}
  • Also worth noting that you need to pay attention to the priority you are using to hook and unhook your 'save_post' action. Here is a great resource on this by Tom McFarlin – Matt Royal Aug 20 '15 at 12:54

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.