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.

Say I created a custom post type called 'Private Posts' ($post_type = itsme_private_posts) and want all posts under the custom post type to be set to 'Private' automatically when published i.e. by default. How do I do it?

Based on @brasofilo's answer to a related question on StackOverflow, I tried this:

add_filter( 'wp_insert_post_data', 'itsme_cpt_private', '99', 2 );
function itsme_cpt_private( $data , $postarr ) {
    if( $postarr['post_type'] == 'itsme_private_posts' ) {
        $data['post_status'] = 'private';
    }
    return $data;
}

It doesn't work i.e. it doesn't do anything; everything's the way it was before adding the function. It's as though the function doesn't exist or simply does nothing.

Then, based on this article titled, "Force custom post type to be private", I tried this:

add_filter( 'wp_insert_post_data', 'itsme_cpt_private' );
function itsme_cpt_private( $post ) {
    if( $post['post_type'] == 'itsme_private_posts' ) {
        $post['post_status'] = 'private';
    }
    return $post;
}

It works, in that, when I publish or update a post it turns private. Good! But when I create a new post ('Add New') and leave without doing anything, it creates a 'private' (auto-)draft and saves it. Moreover I can't even trash that thing!

Essentially I can't figure out how to do it. So, how do I set posts of a custom post type to be private by default?

share|improve this question

1 Answer 1

up vote 4 down vote accepted
+50

The problem with the code in your question is it always intercepts. You completely lose the ability to not publish, no drafts possible. Why this leads to untrashable post is something I didn't inspect further. Anyway this isn't what one wants.

I'm glad the javascript solution is working for you, but personally I have two problems with it, first, you can save post as public, second, it makes it harder - because the script always sets the radio button to private - to handle working with drafts. In a way there are now two solutions to the answer.


1. Forcing post type to be private plus visual indication:

This is why I took another look at doing it with post status transitions and, like I said, it can be done with Post Status Transitions.

Code:

add_action( 'transition_post_status', 'wpse118970_post_status_new', 10, 3 );
function wpse118970_post_status_new( $new_status, $old_status, $post ) { 
    if ( $post->post_type == 'itsme_private_posts' && $new_status == 'publish' && $old_status  != $new_status ) {
        $post->post_status = 'private';
        wp_update_post( $post );
    }
} 

This forces published posts of your post type to be private. Without interfering with the ability to save drafts. This on it's own would be enough to solve the problem of having a private post type.
But of course it would be nice to have the private nature of the post type represented in the publishing metabox. For this I adjusted the javascript a little bit. Mainly by not setting the checkbox by default, but still changing the text shown, additionally I added a note.

Code:

add_action( 'post_submitbox_misc_actions' , 'wpse118970_change_visibility_metabox' );
function wpse118970_change_visibility_metabox(){
    global $post;
    if ($post->post_type != 'post')
        return;
        $message = __('<strong>Note:</strong> Published posts are always <strong>private</strong>.');
        $post->post_password = '';
        $visibility = 'private';
        $visibility_trans = __('Private');
    ?>
    <style type="text/css">
        .priv_pt_note {
            background-color: lightgreen;
            border: 1px solid green;
            border-radius: 2px;
            margin: 4px;
            padding: 4px;
        }
    </style>
    <script type="text/javascript">
        (function($){
            try {
                $('#post-visibility-display').text('<?php echo $visibility_trans; ?>');
                $('#hidden-post-visibility').val('<?php echo $visibility; ?>');
            } catch(err){}
        }) (jQuery);
    </script>
    <div class="priv_pt_note">
        <?php echo $message; ?>
    </div>
    <?php
}

Source: How to set new posts visibility to private by default?
Note: Compared to the code below I removed the checking of the radio button and additionally added code for the message.

Of course you don't need the javascript to make your post type private, but it's always nice to have things visually indicated. For that reason it's a nice addition.


2. Making private the standard option in the publishing meta box:

I'm keeping this because @its_me accepted the answer for this as solution. Like I said in the comment I found a helpful piece of code, it takes care of setting the visibility at the meta box to private by hooking into post_submitbox_misc_actions. Like I said in the beginning »I have two problems with it, first, you can save post as public, second, it makes it harder - because the script always sets the radio button to private - to handle working with drafts«. It's still possible to have and work with drafts, just not as intuitive as before, but the private publishing status is in no way enforced.

Code:

add_action( 'post_submitbox_misc_actions' , 'wpse118970_change_visibility_metabox_value' );
function wpse118970_change_visibility_metabox_value(){
    global $post;
    if ($post->post_type != 'itsme_private_posts')
        return;
    $post->post_password = '';
    $visibility = 'private';
    $visibility_trans = __('Private');
    ?>
    <script type="text/javascript">
        (function($){
            try {
                $('#post-visibility-display').text('<?php echo $visibility_trans; ?>');
                $('#hidden-post-visibility').val('<?php echo $visibility; ?>');
                $('#visibility-radio-<?php echo $visibility; ?>').attr('checked', true);
            } catch(err){}
        }) (jQuery);
    </script>
    <?php
}

Source: How to set new posts visibility to private by default?
Note: I shortened the code to fit the needs here.

share|improve this answer
    
Can you please give an example as to how I'd use to do what I want? I am unsure about it. –  its_me Oct 15 '13 at 18:45
    
You got me curious now :) testing it myself. @its_me –  ialocin Oct 15 '13 at 19:23
    
I realized that the $new_status is auto-draft and the $old_status is new - I change the code accordingly. @its_me Besides that I found another nice piece of code, I add to the answer. –  ialocin Oct 15 '13 at 19:56
    
The JavaScript-based solution worked, but not the first one. Marked as answer 'cause it solves my problem, but it'd be nice if you can find out what's wrong with the first code block. If you can't please remove it (to avoid confusion, for others). Thanks a lot for your time! –  its_me Oct 16 '13 at 3:48
    
I updated the answer, not sure if you get notified after you accepted the answer. @its_me –  ialocin Oct 16 '13 at 21:38

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.