10

I have a custom filed called xxxx_url. xxxx_url should be unique.

So, before publishing the post, I want to make sure that xxxx_url is unique or not? If it isn't unique, publishing the post should be reject.

I tried publish_post. But that isn't the correct one, since it triggers when we publish the post. I want to run my code just before the publish.

  • 1
    Why not setting the current post ID as the unique value. Like: 132_url where 132 is the post ID. Than you always have a unique value here. Besides from that: Custom fields should be saved in the save_post action. In this action you could check the custom field (if its not empty and has a unique value for example), and based on this update_post_meta or not. I guess you could also check the custom field and if it has no unique value, set the post-status to draft or something else, to disable publishing. Otherwise I think you need jQuery to do this. – LWS-Mo Aug 31 '18 at 13:02
5
+25

At the beginning of wp_insert_post, the function that saves/updates a post, there is a filter called wp_insert_post_empty_content. By default this filter checks whether the title, editor, and excerpt fields are all empty, in which case the save process will be halted.

However, since all the fields to be saved are passed to this filter, you can expand this filter to include any other test to determine whether the post should be considered empty. It would be something like this:

add_filter ('wp_insert_post_empty_content','wpse312975_check_unique_url',10,2);
function wpse312975_check_unique_url ($maybe_empty, $postarr) {

  // extract custom field from $postarr, check uniqueness

  if ($unique) return false else return true;
  }

Note: the function must return 'true' to halt the saving process.

If the custom field is not unique you may also want to echo a warning.

  • 2
    This'll probably work, but looks a bit more like a hack, than being a solution. I've considered this as well, but later decided not to post as wp_insert_post_empty_content is semantically meant for empty content. Having said that, I didn't find any hook that's semantically right for this either. – Scott Sep 9 '18 at 14:34
  • Well, if it was only for empty title & content there wouldn't be a filter for developers. – cjbj Sep 9 '18 at 14:54
  • 1
    If you focus less on the mere word 'empty' I'd say this filter is meant to check whether the post meets the minimum requirements for saving. OP wants to broaden the minimum requirements. Perhaps the filter should be named wp_insert_post_valid_content to express that, but for the rest it is in exactly the right place. – cjbj Sep 9 '18 at 16:08
  • @cjbj When you have a question like this, how do you find the correct filter? I mean, how did you find wp_insert_post_empty_content filter? – I am the Most Stupid Person Sep 13 '18 at 4:19
  • 1
    Well, when you've been working with WP for some time, you kind of know which part of the code generates which parts of the admin. So you look up the file and check the source code for available filters. – cjbj Sep 14 '18 at 8:06
1

How about using AJAX to check the uniqueness before even submitting the post for publishing?

$( '#post' ).on( 'submit', function( event ) {
  event.preventDefault(); // Prevent publishing

  //Now do some AJAX Checks
  $.post( ajaxurl, data, function(response) {
    if ( response === 'success' ) {
        $( this ).off( event ).submit();
    } else {
        alert( 'The custom field must be unique' );
    }
  });
});  

Though the code isn't tested, but it should work. You might need to play with it to get your desired result.

0

I would hook into wp_insert_post_data filter and handle this as less intrusive as possible because as I understand you don't want to block the insertion of a post, you just want to avoid publishing a post with duplicate meta values.

I cannot spare too much in this case because you didn't share any code but here is some pseudo-code of a filter that would work:

function wp8193131_check_if_meta_value_is_unique ( $data, $postarr ) {
    // setup an uniqueness flag.
    $meta_is_unique = true;

    // check if the meta is unique and modify the `$meta_is_unique` flag accordingly.
    // {...} <- your code

    // if the meta is NOT unique keep the post status in draft.
    if ( ! $meta_is_unique ) {
        // you can force the current post to be draft until the meta value will became unique.
        $data['post_status'] = 'draft';
        // maybe, update the meta value with a hint of the fact that it's not unique.
        // or display a dashboard notice about it.
    }

    return $data;
}
add_filter( 'wp_insert_post_data', 'wp8193131_check_if_meta_value_is_unique' );

Another great thing about this filter is that it's separated from the attachments one wp_insert_attachment_data.

I hope it helps, and whatever you do, it sounds awesome!

  • 2
    That may not be a good idea. What if $data['post_status'] is publish and user is updating it? Wouldn't making the post as draft create a 404 issue for that post? – Scott Sep 3 '18 at 17:12
  • @Scott In other words, if a published post detects on save that its meta value is not unique, the post publishing should be rejected, and the post should be drafted. Again, I don't know how important that meta value is, but if it's a sorting data type or something essential, then the post status should be draft (which doesn't mean a 404 issue, it just says that the post has been retired from the public view) – Andrei Sep 4 '18 at 10:18
-1

The check should go to wp_insert_post. This hook is fired whenever post is published or edited.

There, you can do a custom query to check, if there is any post already has the same xxxx_url value or not.

add_action('wp_insert_post', function($post_id) {
    $meta_key = 'xxxx_url';
    $meta_value = get_post_meta($post_id, $meta_key, true);
    $query = new WP_Query([
        'post_type' => get_post_type($post_id),     // This might be unnecessary, if you check `post` post type only. Or use `any`.
        'meta_query' => [
            [
                'meta_key' => $meta_key,
                'meta_value' => $meta_value,
            ]
        ]
    ]);
    if ($query->have_posts()) {
        // invalid key, post with the same value already exists
    } else {
        // valid, key was not found anywhere
    }
});
  • 3
    As I know, whatever you write inside if/else statement post will be published since the wp_insert_post action fires once a post has been saved, it can't blocked publishing or inserting post. – I am the Most Stupid Person Sep 3 '18 at 12:00
  • So you want to block publishing, if the post fails validation? You havent' wrote that in your question. – Petr Cibulka Sep 3 '18 at 13:33
  • I have clearly mentioned that If it isn't unique it should reject publishing post. in my question. – I am the Most Stupid Person Sep 7 '18 at 3:41

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.