2

I'm writing a plugin that every time you:

  • publish a post
  • edit an already published one
  • delete a published post

it makes several queries to the database, gets certain post data (title, excerpt, category, id, url, etc) and exports the in JSON file. This one I'm using it on the front end to draw all the elements.

I also have some custom metaboxes in the admin panel where you can add some custom meta data.

My problem now

Every time I'm creating a new post and publish it directly - without saving it first (otherwise the export works), the array in the JSON file containing the data from the custom meta data is empty. If I check though the database, through myPhpAdmin, the values are stored. The plugin for the custom meta data is hooked in the "save_post" action. The plugin for exporting to JSON is hooked in the "publish_post" action.

I even have this functions in the plugin to find the action with the highest priority number and put mine after it.

function get_latest_priority( $filter )
{
  if ( empty ( $GLOBALS['wp_filter'][ $filter ] ) ){
    return PHP_INT_MAX;
  }

  $priorities = array_keys( $GLOBALS['wp_filter'][ $filter ] );
  $last       = end( $priorities );

  return $last+1;
}
function export_posts_in_json (){



function register_plugin (){
  add_action( 'publish_post', 'export_posts_in_json', get_latest_priority( current_filter() ), 1);
}
add_action( 'publish_post', 'register_plugin', 0 );

That is what the var_dump( $GLOBALS['wp_filter'][ $filter ]); where $filter is current_filter() prints out:

array(2) {
  [0]=>
  array(1) {
    ["register_custom_save"]=>
    array(2) {
      ["function"]=>
      string(20) "register_custom_save"
      ["accepted_args"]=>
      int(1)
    }
  }
  [5]=>
  array(1) {
    ["_publish_post_hook"]=>
    array(2) {
      ["function"]=>
      string(18) "_publish_post_hook"
      ["accepted_args"]=>
      int(1)
    }
  }
}

So I'm putting 6 as priority.

Why on earth it doesn't work? Were should I hook it to work? Is the problem in the custom meta data plugin or in the export one?

If you need the whole plugin let me know, but I don't think is necessary since it works when the post is already saved in the database.

UPDATE

I've hooked the plugin at the 'save_post' with later priority and the export function runs only if the $post_status of the current post is 'publish'.

function check_status( $post ){
  $p = get_post( $post );
  $p_status = $p->post_status;
  if($p_status == 'publish'){
    export_posts_in_json();
  }
}
add_action( 'save_post', 'check_status', 20, 1 );

This doesn't solves the problem though. I can't capture if the current post changes status from publish to draft. The export_posts_in_json() functions queries only published posts. So if I will be able to run it for the above case, I will manage to delete this post form the JSON file.

3
  • I'm guessing you want to use the save_post action codex.wordpress.org/Plugin_API/Action_Reference/save_post.
    – jdm2112
    Commented Sep 19, 2016 at 14:47
  • If I use the save_post action it gets fired even if you save a draft and I don't want to export only published ones. I know I can query only published posts, but then I will be overwriting the JSON file multiple unnecessary time.
    – Achillx
    Commented Sep 19, 2016 at 16:34
  • Why not set the conditions of action in your function? You function will trigger on every save post action and you can if ( test = true ) { do stuff }. It is true that your condition code will run every save but it should only take a microsecond to test if on the server.
    – jdm2112
    Commented Sep 19, 2016 at 18:58

2 Answers 2

2

Something important - when you create a new post the first thing WordPress does is an auto-save, so yes the first time the values should be empty. Perhaps that is what you are experiencing - I don't see your full code, but I do see

The plugin for the custom meta data is hooked in the "save_post" action.

Also, while editing WordPress also does an auto-save every 60 seconds by default. So perhaps check for auto-saves in your code, or you could try disabling auto-save completely.

function disable_autosave() {
    wp_deregister_script('autosave');
}
add_action('wp_print_scripts','disable_autosave');
1

Well I'm answering my own question but, after a lot of research, trail and error, I found a solution.

I'm using the transition_post_status action hook to look for changes in the post's status.Because this action runs before the save_post one and my custom meta data are not yet saved in the database, I'm not calling the export function directly. Instead I'm calling the add_action, hooked in the save_post and give it a later priority so that everything first gets saved in the database.

function check_status( $new_status, $old_status, $post ){

  if ( $post->post_type == 'post'){

    //if the posts gets unpublished
    if ( $old_status == 'publish' && $new_status != 'publish' ){
      add_action( 'save_post', 'export_posts_in_json', 20, 1 );
    }

    //if the post gets published, regardless of the previous status
    elseif ( $new_status == 'publish' ){
      add_action( 'save_post', 'export_posts_in_json', 20, 1 );
    }
  }

}
add_action( 'transition_post_status', 'check_status', 10, 3);

I hope this will help some other people.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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