Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

For an indie rock agenda I created event posts. With the help of javascript, the custom fields values (bands, places and date info picked in select boxes) are copied as the post title when publishing or updating the post.There is also a custom function which update the slug every time the title changes. Problem: if an other user create a new post picking exactly the same custom fields values, then an other post with exactly the same slug is created. And if two posts with the same slug are created, both of them lead to a 404 error page until one of them is manually deleted. My question: is there a way to "validate" the post slug comparing it to the older posts in the database ? Thanks for your help !

share|improve this question
add comment

4 Answers

The Ajax way (a little bit dirty, but you can easily enhance it)

In your functions.php (or in a plugin, or every where else) :

function my_ajax_update(){
    if (isset($_POST['title'])){
        global $wpdb;
        $title = esc_sql($_POST['title']);
        if(!$title) return;
        $page = $wpdb->get_results("
            SELECT *
            FROM $wpdb->posts
            WHERE post_title LIKE '$title'
            AND post_type = 'event'
            AND post_status = 'publish'
            LIMIT 1
        ");
        if ($page) echo "This title already exists !";
    }
}
add_action("wp_ajax_check_double_post", "my_ajax_update");

And somewhere in your metabox template (or loaded via an action) :

jQuery(document).ready(function($){
    var the_title = $('#title').val();
    $('#publish').click(function(e){
        e.preventDefault();
        $.post(
            ajaxurl,
            {
                action:"check_double_post",
                title: the_title
            },
            function(data){
                if ((data) != 0) {
                    message = $('<div id="message" class="error below-h2" />').html('<p>Warning, this title already exists!</p>')
                    $('h2').after(message);
                    $('#ajax-loading').hide();
                    $('#publish').removeClass('button-primary-disabled');
                }
                else {
                    $(this).submit();
                }
            }
        );
    });
});
share|improve this answer
    
Thanks Volpeo... but I couldn't get it working. In the case of a yet published post which have the same title than an other, the error message is correctly displayed, but after I changed some custom field's content and republish the same error message is displayed. In the case of a new post, clicking the "publish" button does nothing (ajax-loading image runs endlessly), regardless the title of this post is unique or not. –  Pierre Nov 5 '11 at 19:58
add comment

You'd be surprised at how tricky this one turns out to be. Closest I'm getting is hooking into the save_post action. There appears to be no action to hook to that will stop the post from saving, all the actions for update_post() and write_post() don't appear to allow any direct interference; so the very simple and quick option I've come up with involves dying inside the hook. Even so, the post is saved with the duplicate name regardless of our dying.

function check_post_title( $pid ) {
    $post = get_post( $pid );
    $events = get_posts( 's='.$post->post_title.'&post_type=event' );

    foreach( (array)$events as $event ) {
        if ( $event->ID == $post->ID ) continue;
        if ( $event->post_title == $post->post_title ) die('Oh noes! A post with this title already exits, go back and change it, please.');
    }
}

add_action( 'save_post', 'check_post_title' );

The save_post action supplies the hook with the post ID of the saved post. Then events are searched for using the 's' argument, just like you would search for using the regular WordPress search on your pages. The events are then iterated through and if a post with an ID other than the checked-upon post is found with a title that matches this checked-upon post then it dies.

Something more helpful and less stripped down would involve a custom message when the post is published.

function check_post_title( $pid ) {
    $post = get_post( $pid );
    $events = get_posts( 's='.$post->post_title.'&post_type=event' );

    foreach( (array)$events as $event ) {
        if ( $event->ID == $post->ID ) continue;
        if ( $event->post_title == $post->post_title ) {
            add_filter( 'redirect_post_location', 'event_exists' );
        }
    }
}

/* Alter the message */
function event_exists( $redirect_url ) {
    $messages = array( 'message=1', 'message=2' );
    return str_replace( $messages, 'message=100', $redirect_url );
}

/* Add a custom event message */
function custom_event_message( $messages ) {
    $messages['post']['100'] = 'Oh noes! An event with this name already exists, so go ahead and pick another.';
    return $messages;
}

add_filter( 'post_updated_messages', 'custom_event_message' );

add_action( 'save_post', 'check_post_title' );

This is a quick solution, something even more involved would perhaps require that the saved post which has just infringed the no-duplicate-title rule has to have it's title modified and resaved by the function, turning it into something like 'DUPLICATE! [the title here]' and changing post status back to 'pending'.

The yellow message seems to be quite subtle and may not be noticed by publishers, dying seems to be more attention-grabbing.

Hope this helps and didn't confuse you too much. There may be better solutions to the problem, let's hope someone comes by and helps us improve the solution. Any ideas will be appreciated at this point.

share|improve this answer
    
Hi Soulseekah, and thanks a lot. The first solution looks interesting as I really want to avoid any duplicate post. Unfortunately it didn't work for me... –  Pierre Oct 17 '11 at 7:16
    
Pierre, what didn't work? Where did you put the function? Did you change the post type for the query? Errors? –  soulseekah Oct 17 '11 at 9:15
    
I changed the post type for "concerts" in place of "event". The code is in my functions.php file. But when I click the "publish" button of my new post (with custom fields filled exactly like an other one, to get the same title) the page is saved as usual... –  Pierre Oct 17 '11 at 10:20
    
Can you place var_dump( $events ); die(); after get_posts and see if anything is found matching the criteria. Or if it at least gets to your execution point? –  soulseekah Oct 17 '11 at 10:25
    
Like my answer says, be aware of the fact that the post is still saved regardless of whether the hook dies or not. My solution is the general one, one which allows you retrieve posts based and compare names; if your post is being hooked into by another plugin to generate the title then this new check_post_title function hook may come too early, when the title is still empty and hasn't been generated from the custom fields. –  soulseekah Oct 17 '11 at 10:39
show 2 more comments

Instead of making your own query, why not just using the function post_exists() ? It takes the post_title, content and date ( optionnal ). This function does not test the post_type but its rare that you have the same post_title on your content.

Regards, Rahe.

share|improve this answer
add comment

find if POST Slug already exists

method 1)

$title = 'mytitlee';

global $wpdb;
$id_ofpost_name = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_name = '$title'");
$id_ofpost_title = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_title = '$title'");
if ($id_ofpost_name || $id_ofpost_title) {echo 'Exists, here is the id:'.$id_ofpost_title.' or '.$id_ofpost_name;} 
else {echo 'post wasnt found';}

method 2) (without Mysql query, so it may be a bit slower):

$title = 'my_slug';
//you can use post_types too
$ptype='';

global $wpdb;
global $post;
$args = array( 'post_type' => $ptype);
$allPosts = get_posts($args);
$smthh='no';
foreach( $allPosts as $page )
{
    if( $smthh == 'no' && ($page->post_name == $title ||  $page->post_title == $title) )
    {$smthh='yes'; break; }
}


if ( $smthh == 'yes' )
{ 
    echo "yes, post was found";
}

else
{
    echo "no, not found";

    // You can insert the post too
    $my_post = array( 'post_type'    => $ptype, 'post_title'    => $title, 'post_content'  => 'This is my post content.', 'post_status'   => 'publish', );
    wp_insert_post( $my_post );
}
share|improve this answer
1  
Do not post the same answer multiple times. If you see a duplicate questions flag them as duplicates. And stick with one account. Thanks. –  toscho Apr 9 '13 at 10:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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