Disallow Same Post Title

I am looking for some code where member can’t use the same title as another post already having or used.

e.g if there is a post with title “Amazing Australia Tour” than it should not allow to use the same title to same or other user.

Related posts

Leave a Reply

2 comments

  1. Main Code

    Please check the auxiliary code after this block

    /*
     * Prevent Duplicated Titles
     *
     */
    
    if( is_admin() ) // check if we are in the administrative area
    {
        add_action( 'save_post', 'wpse_54258_check_for_duplicate_title', 11, 2 );
        add_action( 'admin_head-post.php', 'wpse_54258_check_for_notice' );
    }
    
    /*
     * Checks for more than one post with the same title
     *
     * Adds filter redirect_post_location if duplicate title found
     *
     */
    
    function wpse_54258_check_for_duplicate_title( $post_id, $post )
    {
        // HERE, FURTHER FILTERING CAN BE DONE, RESTRICT USERS, POST_TYPES, ETC
        if ( 
            ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
            or ! current_user_can( 'edit_post', $post_id )
            or wp_is_post_revision( $post )
            // ADD OTHER FILTERS, LIKE post_type
        )
        { // Noting to do.
            return;
        }
    
        $termid = get_post_meta($post_id, '_is_dup', true);
        if ( '' != $termid ) 
        {
            // it's a new record
            $count_dups = 0;
            update_post_meta($post_id, '_is_dup', 'new-post-check');
        } 
        else 
        {
            $count_dups = 1;
        }
        
        // NO CHECKING IS BEING DONE REGARDING UPPER AND LOWERCASES, NOR FOR HTML TAGS
        global $wpdb;
        $title_exists = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = '$post->post_title' AND post_status = 'publish'") );
    
        if( count($title_exists) > $count_dups ) 
            add_filter('redirect_post_location','wpse_54258_add_error_query_var');
    }
    
    
    /*
     * Removes the previous applied filter and adds error var to the redirect
     *
     */
    
    function wpse_54258_add_error_query_var( $loc ) 
    {
        remove_filter( 'redirect_post_location','wpse_54258_add_error_query_var' );
        return add_query_arg( 'duplicated_title', 123, $loc );
    }
    
    
    /*
     * Error checking after saving the post
     *
     */
    
    function wpse_54258_check_for_notice()
    {
        if( isset( $_GET['duplicated_title'] ) )
            add_action( 'admin_notices', 'wpse_54258_display_error_message' );
    }
    
    /*
     * Actual error message for duplicated post titles
     *
     */
    function wpse_54258_display_error_message()
    { ?>
        <div class="error fade">ERROR</div>
        <?php
        remove_action( 'admin_notices', 'wpse_54258_display_error_message' );
    }
    

    Auxiliary Code

    The method used to check if a new post/page is being created or not requires a post_meta that has to be applied to all previous posts/pages.

    /*
     * Update ALL PUBLISHED posts and pages with the controller post_meta required by the main code
     *
     * Important: Run Only Once 
     * -> Paste in functions.php
     * -> Remove the comment to add_action
     * -> Visit any administrative page
     * -> Delete or disable this code
     * 
     */
    //add_action('admin_init','wpse_54258_run_only_once');
    function wpse_54258_run_only_once()
    {   
        global $wpdb;
        $allposts = $wpdb->get_results( "SELECT ID FROM $wpdb->posts WHERE post_status = 'published'" );
        foreach( $allposts as $pt )
        {
            update_post_meta( $pt->ID, '_is_dup', 'new-post-check');
        }
    }
    

    This answer was assembled using:

  2. I’ve been able to prevent same post Titles with Ajax. Here’s what I did:

    on functions.php

    // 1. Enqueue my admin script
    function add_my_admin_script(){
        wp_enqueue_script('admin_script', get_template_directory_uri() . '/js/admin_script.js', array('jquery'));
        //
        wp_localize_script( 'admin_script', 'ajax_object',
            array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'we_value' => 1234 ) );
    }
    add_action('admin_enqueue_scripts', 'add_my_admin_script');   
    
    // 2. The Function to check Post Titles
    /************/
    // Check Titles
    /************/
    add_action( 'wp_ajax_my_action', 'my_action_callback' );
    
    function my_action_callback() {
        global $wpdb;
        $title_exists = $wpdb->get_results( 
            "
            SELECT ID
            FROM $wpdb->posts
            WHERE  
                post_title LIKE '" . $_POST['this_convidado_title'] . "'
            AND
                post_type = '" . $_POST['post_type'] .  "'    
            "
        );
        if($_POST['post_ID'] != ""){
            foreach ($title_exists as $key => $this_id) {
                if($_POST['post_ID'] == $this_id->ID){
                    $this_is_the_post = $this_id->ID;
                }
            }
        }
        if($this_is_the_post){
            echo (count($title_exists)-1);
        } else {
            echo count($title_exists);
        }
        die();
    }
    

    on my admin_script.js

    jQuery(document).ready(function($) {
        "use strict";
        $( "#title" ).change(function() {
            if($(this).val() !== ""){
                var this_post_id;
                this_post_id = "";
                if($("#post_ID").val()){
                    this_post_id = $("#post_ID").val();
                }
                var data = {
                    'action': 'my_action',
                    'this_convidado_title': $(this).val(),
                    'post_type': 'your_post_type',
                    'post_ID' : this_post_id
                };
                // We can also pass the url value separately from ajaxurl for front end AJAX implementations
                jQuery.post(ajax_object.ajax_url, data, function(response) {
                    if(response > 0){
                        alert('There is a post with this same Title!');
                        $("#title").val("");
                        $("#post").submit();
                        // I do the form#post submission because I could not find the trigger to use the autosave - would be better with the auto save
                        // This is needed to avoid save post drafts with the unwanted title
                    }
                });
            }
        });
    });