WordPress.org

Make WordPress Core

Ticket #12706: Custom_Stati_Support.patch

File Custom_Stati_Support.patch, 82.7 KB (added by kevinB, 8 years ago)

comprehensive support for custom stati (public, private and moderation). RevC tightens code, fixes patch js bugs and a few core bugs (see comments). RevD registers and enforces type-specific stati, fleshes out custom public stati, allows scheduling to any public or private status. RevE is a 1-liner to include all readable stati in Recent Posts widget. RevF (15 Oct) fixes patch bugs related to sticky posts; supports custom public stati for sticky posts, term count, comment feed, archives, find posts, nav menu metabox & display

  • wp-admin/admin-ajax.php

     
    683683
    684684        $status = $wpdb->get_var( $wpdb->prepare("SELECT post_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) );
    685685
    686         if ( empty($status) )
     686        $post_status_obj = get_post_status_object($status);
     687       
     688        if ( empty($post_status_obj) )
    687689                die('1');
    688         elseif ( in_array($status, array('draft', 'pending', 'trash') ) )
     690        elseif ( ! $post_status_obj->public && ! $post_status_obj->private )
    689691                die( __('Error: you are replying to a comment on a draft post.') );
    690692
    691693        $user = wp_get_current_user();
     
    11811183        if ( isset($data['post_parent']) )
    11821184                $data['parent_id'] = $data['post_parent'];
    11831185
     1186        $post_type_object = get_post_type_object( $post['post_type'] );
     1187
    11841188        // status
    1185         if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
    1186                 $data['post_status'] = 'private';
    1187         else
     1189        foreach( get_post_stati( array( 'internal' => false, 'object_type' => $post['post_type'] ), 'object' ) as $_status => $_status_obj ) {
     1190                if ( ( 'publish' == $_status ) || ( ! $_status_obj->private && ! $_status_obj->public ) ) // private and custom public stati only here
     1191                        continue;
     1192
     1193                if ( isset($data["keep_{$_status}"]) ) {
     1194                        $set_status_cap = "set_{$_status}_posts";
     1195                        $check_cap = ( ! empty( $post_type_object->cap->$set_status_cap ) ) ? $post_type_object->cap->$set_status_cap : $post_type_object->cap->publish_posts;
     1196
     1197                        if ( current_user_can( $check_cap ) ) {
     1198                                $data['post_status'] = $_status;
     1199                                $keeping_private = true;
     1200                                break;
     1201                        }       
     1202                }
     1203        }
     1204
     1205        if ( empty($keeping_private) ) // private or custom public status selected and granted
    11881206                $data['post_status'] = $data['_status'];
    11891207
    11901208        if ( empty($data['comment_status']) )
     
    12581276        if ( count($search_terms) > 1 && $search_terms[0] != $s )
    12591277                $search .= " OR ($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%')";
    12601278
    1261         $posts = $wpdb->get_results( "SELECT ID, post_title, post_status, post_date FROM $wpdb->posts WHERE post_type = '$what' AND post_status IN ('draft', 'publish') AND ($search) ORDER BY post_date_gmt DESC LIMIT 50" );
     1279        $public_stati = apply_filters( 'find_posts_stati', get_post_stati( array( 'public' => true ) ) );
     1280        $public_csv = implode( "', '", $public_stati );
    12621281
     1282        $posts = $wpdb->get_results( "SELECT ID, post_title, post_status, post_date FROM $wpdb->posts WHERE post_type = '$what' AND post_status IN ('draft', '$public_csv') AND ($search) ORDER BY post_date_gmt DESC LIMIT 50" );
     1283
    12631284        if ( ! $posts ) {
    12641285                $posttype = get_post_type_object($what);
    12651286                exit($posttype->labels->not_found);
    12661287        }
    12671288
     1289        $stat = array();
     1290       
    12681291        $html = '<table class="widefat" cellspacing="0"><thead><tr><th class="found-radio"><br /></th><th>'.__('Title').'</th><th>'.__('Date').'</th><th>'.__('Status').'</th></tr></thead><tbody>';
    12691292        foreach ( $posts as $post ) {
     1293               
     1294                if ( ! isset( $stat[$post->post_status] ) ) {
     1295                        $_status_obj = get_post_status_object( $post->post_status );
     1296                       
     1297                        if ( ! $_status_obj )
     1298                                $_status_obj = get_post_status_object( 'draft' );
     1299                        elseif ( ( $_status_obj->public || $_status_obj->private ) &&  ( 'publish' != $post->post_status ) )
     1300                                $_status_obj = get_post_status_object( 'publish' );
    12701301
    1271                 switch ( $post->post_status ) {
    1272                         case 'publish' :
    1273                         case 'private' :
    1274                                 $stat = __('Published');
    1275                                 break;
    1276                         case 'future' :
    1277                                 $stat = __('Scheduled');
    1278                                 break;
    1279                         case 'pending' :
    1280                                 $stat = __('Pending Review');
    1281                                 break;
    1282                         case 'draft' :
    1283                                 $stat = __('Draft');
    1284                                 break;
     1302                        $stat[$post->post_status] = $_status_obj->labels->caption;
    12851303                }
    12861304
    12871305                if ( '0000-00-00 00:00:00' == $post->post_date ) {
     
    12921310                }
    12931311
    12941312                $html .= '<tr class="found-posts"><td class="found-radio"><input type="radio" id="found-'.$post->ID.'" name="found_post_id" value="' . esc_attr($post->ID) . '"></td>';
    1295                 $html .= '<td><label for="found-'.$post->ID.'">'.esc_html( $post->post_title ).'</label></td><td>'.esc_html( $time ).'</td><td>'.esc_html( $stat ).'</td></tr>'."\n\n";
     1313                $html .= '<td><label for="found-'.$post->ID.'">'.esc_html( $post->post_title ).'</label></td><td>'.esc_html( $time ).'</td><td>'.esc_html( $stat[$post->post_status] ).'</td></tr>'."\n\n";
    12961314        }
    12971315        $html .= '</tbody></table>';
    12981316
  • wp-admin/edit-form-advanced.php

     
    4949                // translators: Publish box date format, see http://php.net/date
    5050                date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
    5151        10 => sprintf( __('Post draft updated. <a target="_blank" href="%s">Preview post</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
     52        11 => sprintf( __('Post moderated. <a target="_blank" href="%s">Preview post</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    5253);
    5354$messages['page'] = array(
    5455         0 => '', // Unused. Messages start at index 1.
     
    6263         8 => sprintf( __('Page submitted. <a target="_blank" href="%s">Preview page</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    6364         9 => sprintf( __('Page scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview page</a>'), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
    6465        10 => sprintf( __('Page draft updated. <a target="_blank" href="%s">Preview page</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
     66        11 => sprintf( __('Page moderated. <a target="_blank" href="%s">Preview page</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    6567);
    6668
    6769$messages = apply_filters( 'post_updated_messages', $messages );
     
    142144if ( post_type_supports($post_type, 'comments') )
    143145        add_meta_box('commentstatusdiv', __('Discussion'), 'post_comment_status_meta_box', $post_type, 'normal', 'core');
    144146
    145 if ( ('publish' == $post->post_status || 'private' == $post->post_status) && post_type_supports($post_type, 'comments') )
     147if ( ! $post_status_object = get_post_status_object( $post->post_status ) )
     148        $post_status_object = get_post_status_object( 'draft' );
     149
     150if ( ( $post_status_object->public || $post_status_object->private ) && post_type_supports($post_type, 'comments') )
    146151        add_meta_box('commentsdiv', __('Comments'), 'post_comment_meta_box', $post_type, 'normal', 'core');
    147152
    148 if ( !( 'pending' == $post->post_status && !current_user_can( $post_type_object->cap->publish_posts ) ) )
     153if ( ! ( $post_status_object->moderation && ! current_user_can( $post_type_object->cap->publish_posts ) ) )
    149154        add_meta_box('slugdiv', __('Slug'), 'post_slug_meta_box', $post_type, 'normal', 'core');
    150155
    151156if ( post_type_supports($post_type, 'author') ) {
     
    247252if ( !empty($shortlink) )
    248253    $sample_permalink_html .= '<input id="shortlink" type="hidden" value="' . esc_attr($shortlink) . '" /><a href="#" class="button" onclick="prompt(&#39;URL:&#39;, jQuery(\'#shortlink\').val()); return false;">' . __('Get Shortlink') . '</a>';
    249254
    250 if ( !( 'pending' == $post->post_status && !current_user_can( $post_type_object->cap->publish_posts ) ) ) { ?>
     255if ( ! ( $post_status_object->moderation && ! current_user_can( $post_type_object->cap->publish_posts ) ) ) { ?>
    251256        <div id="edit-slug-box">
    252257        <?php
    253258                if ( ! empty($post->ID) && ! empty($sample_permalink_html) && 'auto-draft' != $post->post_status )
     
    314319try{document.post.title.focus();}catch(e){}
    315320</script>
    316321<?php endif; ?>
     322
     323
     324<?php
     325add_action( 'admin_print_footer_scripts', create_function('', "_edit_form_advanced_scripts('$post_type');") );
     326
     327function _edit_form_advanced_scripts( $post_type ) {
     328?>
     329       
     330<script type="text/javascript">
     331//<![CDATA[
     332jQuery(document).ready( function($) {
     333        function updateStatusCaptions() {
     334                postStatus = $('#post_status');
     335
     336                $('#post-status-display').html($('option:selected', postStatus).text());
     337
     338                switch( $('option:selected', postStatus).val() ) {
     339
     340<?php foreach( get_post_stati( array( 'public' => true, 'private' => true ), 'object', 'or' ) as $_status => $_status_obj ): ?>
     341                        case '<?php echo $_status ?>':
     342                                $('#save-post').hide();
     343                                break;
     344<?php endforeach; ?>
     345
     346<?php foreach( get_post_stati( array( 'moderation' => true, 'internal' => false, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ): ?>
     347                        case '<?php echo $_status ?>':
     348                                $('#save-post').show().val( '<?php echo $_status_obj->labels->save_as ?>' );
     349                                break;
     350<?php endforeach; ?>
     351
     352                        default :
     353                                <?php $draft_status_obj = get_post_status_object( 'draft' ); ?>                 
     354                                $('#save-post').show().val( '<?php echo $draft_status_obj->labels->save_as ?>' );
     355                }
     356        }
     357
     358        $('input:radio', '#post-visibility-select').change(function() {
     359                switch ( $('input:radio:checked', '#post-visibility-select').val() ) {
     360                        case 'public':
     361                                $('#sticky-span').show();
     362                                break;
     363
     364<?php foreach( get_post_stati( array( 'public' => true, 'object_type' => $post_type ) ) as $_status ) : ?>
     365                        case '<?php echo $_status ?>':
     366                                $('#sticky-span').show();
     367                                break;
     368<?php endforeach; ?>
     369
     370                        default :
     371                                $('#sticky').attr('checked', false);
     372                                $('#sticky-span').hide();
     373                }
     374        });
     375       
     376        function updateVisibilityCaptions() {
     377                var postStatus = $('#post_status'), optPublish = $('option[value=publish]', postStatus);
     378
     379                switch( $('input:radio:checked', '#post-visibility-select').val() ) {
     380
     381<?php foreach( get_post_stati( array( 'internal' => false, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ) :
     382                if ( ( 'publish' == $_status ) || ( ! $_status_obj->private && ! $_status_obj->public ) )
     383                        continue;
     384?>
     385                        case '<?php echo $_status ?>':
     386                                $('#publish').val( postL10n.update );
     387
     388                                if ( optPublish.length == 0 ) {
     389                                        postStatus.append('<option value="publish">' + '<?php echo $_status_obj->labels->caption ?>' + '</option>');
     390                                } else {
     391                                        optPublish.html( '<?php echo $_status_obj->labels->caption ?>' );
     392                                }
     393
     394                                $('option[value=publish]', postStatus).attr('selected', true);
     395                                $('.edit-post-status', '#misc-publishing-actions').hide();
     396
     397                                break;
     398<?php endforeach; ?>
     399
     400                        default:
     401                                if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) {
     402                                        if ( optPublish.length ) {
     403                                                optPublish.remove();
     404                                                postStatus.val($('#hidden_post_status').val());
     405                                        }
     406                                } else {
     407                                        optPublish.html( postL10n.published );
     408                                }
     409                                if ( postStatus.is(':hidden') )
     410                                        $('.edit-post-status', '#misc-publishing-actions').show();
     411                }
     412
     413                return true;
     414        }
     415       
     416        $('.save-post-status', '#post-status-select').click(function() {
     417                updateStatusCaptions();
     418                return false;
     419        });
     420       
     421        $('.cancel-post-visibility', '#post-visibility-select').click(function () {
     422                updateVisibilityCaptions();
     423                return false;
     424        });
     425
     426        $('.save-post-visibility', '#post-visibility-select').click(function () { // crazyhorse - multiple ok cancels
     427                updateVisibilityCaptions();
     428                updateStatusCaptions();
     429                return false;
     430        });
     431});
     432//]]>
     433</script>
     434
     435<?php
     436} // end function edit_form_advanced_scripts
     437?>
     438 No newline at end of file
  • wp-admin/includes/default-list-tables.php

     
    137137                }
    138138
    139139                $total_posts = array_sum( (array) $num_posts );
    140 
     140               
    141141                // Subtract post types that are not included in the admin all list.
    142                 foreach ( get_post_stati( array('show_in_admin_all_list' => false) ) as $state )
     142                foreach ( get_post_stati( array('show_in_admin_all_list' => false, 'object_type' => $post_type) ) as $state )
    143143                        $total_posts -= $num_posts->$state;
    144144
    145145                $class = empty($class) && empty($_REQUEST['post_status']) ? ' class="current"' : '';
    146146                $status_links['all'] = "<li><a href='edit.php?post_type=$post_type{$allposts}'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_posts, 'posts' ), number_format_i18n( $total_posts ) ) . '</a>';
    147147
    148                 foreach ( get_post_stati(array('show_in_admin_status_list' => true), 'objects') as $status ) {
     148                foreach ( get_post_stati(array('show_in_admin_status_list' => true, 'object_type' => $post_type), 'objects') as $status ) {
    149149                        $class = '';
    150150
    151151                        $status_name = $status->name;
     
    255255                if ( empty( $post_type ) || is_object_in_taxonomy( $post_type, 'post_tag' ) )
    256256                        $posts_columns['tags'] = __( 'Tags' );
    257257                $post_status = !empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all';
    258                 if ( !in_array( $post_status, array( 'pending', 'draft', 'future' ) ) && ( empty( $post_type ) || post_type_supports( $post_type, 'comments' ) ) )
     258               
     259                $post_status_obj = get_post_status_object( $post_status );
     260
     261                if ( ! in_array( $post_status, array( 'pending', 'draft', 'future' ) ) && empty( $GLOBALS['wp_post_statuses'][$post_status]->moderation ) && ( empty( $post_type ) || post_type_supports( $post_type, 'comments' ) ) )
    259262                        $posts_columns['comments'] = '<div class="vers"><img alt="Comments" src="' . esc_url( admin_url( 'images/comment-grey-bubble.png' ) ) . '" /></div>';
    260263                $posts_columns['date'] = __( 'Date' );
    261264
     
    523526                                        if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS )
    524527                                                $actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete Permanently' ) . "</a>";
    525528                                }
    526                                 if ( in_array( $post->post_status, array( 'pending', 'draft' ) ) ) {
     529                                if ( in_array( $post->post_status, array( 'pending', 'draft' ) ) || ! empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation ) ) {
    527530                                        if ( $can_edit_post )
    528531                                                $actions['view'] = '<a href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) . '" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ) . '" rel="permalink">' . __( 'Preview' ) . '</a>';
    529532                                } elseif ( 'trash' != $post->post_status ) {
     
    559562                                else
    560563                                        echo '<abbr title="' . $t_time . '">' . apply_filters( 'post_date_column_time', $h_time, $post, $column_name, $mode ) . '</abbr>';
    561564                                echo '<br />';
    562                                 if ( 'publish' == $post->post_status ) {
     565
     566                                $published_stati = get_post_stati( array( 'public' => true, 'private' => true ), 'names', 'or' );
     567                                if ( in_array( $post->post_status, $published_stati ) ) {
    563568                                        _e( 'Published' );
    564569                                } elseif ( 'future' == $post->post_status ) {
    565570                                        if ( $time_diff > 0 )
     
    761766                                        <span class="title"><?php _e( 'Password' ); ?></span>
    762767                                        <span class="input-text-wrap"><input type="text" name="post_password" class="inline-edit-password-input" value="" /></span>
    763768                                </label>
     769                               
     770        <?php
     771        foreach ( get_post_stati( array( 'internal' => false, 'object_type' => $screen->post_type ), 'object' ) as $_status => $_status_obj ) :
     772                if ( ( 'publish' == $_status ) || ( ! $_status_obj->private && ! $_status_obj->public ) ) // private and custom public stati only here
     773                        continue;
    764774
     775                $set_status_cap = "set_{$_status}_posts";
     776                $check_cap = ( ! empty( $post_type_object->cap->$set_status_cap ) ) ? $post_type_object->cap->$set_status_cap : $post_type_object->cap->publish_posts;
     777
     778                if ( current_user_can( $check_cap ) ) {
     779                        if ( empty( $did_or ) ) :
     780                                $did_or = true;
     781                        ?>
    765782                                <em style="margin:5px 10px 0 0" class="alignleft">
    766783                                        <?php
    767784                                        /* translators: Between password field and private checkbox on post quick edit interface */
    768785                                        echo __( '&ndash;OR&ndash;' );
    769786                                        ?>
    770787                                </em>
    771                                 <label class="alignleft inline-edit-private">
    772                                         <input type="checkbox" name="keep_private" value="private" />
    773                                         <span class="checkbox-title"><?php echo __( 'Private' ); ?></span>
    774                                 </label>
     788                        <?php endif; ?>
     789
     790                        <label class="alignleft keep-private inline-edit-<?php echo $_status ?>">
     791                                <input type="checkbox" name="keep_<?php echo $_status ?>" value="<?php echo $_status ?>" />
     792                                <span class="checkbox-title"><?php echo $_status_obj->labels->name ?>&nbsp; &nbsp;</span>
     793                        </label>                       
     794        <?php
     795                } // endif user can set status
     796        endforeach; ?>
     797       
    775798                        </div>
    776799
    777800        <?php endif; ?>
     
    908931        <?php if ( $bulk ) : ?>
    909932                                                <option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
    910933        <?php endif; // $bulk ?>
    911                                         <?php if ( $can_publish ) : // Contributors only get "Unpublished" and "Pending Review" ?>
     934        <?php if ( $can_publish ) : // Contributors only get draft and moderation stati ?>
    912935                                                <option value="publish"><?php _e( 'Published' ); ?></option>
    913936                                                <option value="future"><?php _e( 'Scheduled' ); ?></option>
    914         <?php if ( $bulk ) : ?>
    915                                                 <option value="private"><?php _e( 'Private' ) ?></option>
    916         <?php endif; // $bulk ?>
    917                                         <?php endif; ?>
    918                                                 <option value="pending"><?php _e( 'Pending Review' ); ?></option>
     937        <?php if ( $bulk ) :
     938        foreach( get_post_stati( array( 'private' => true, 'object_type' => $screen->post_type ), 'object' ) as $_status => $_status_obj ) {
     939        ?>
     940                                                <option value="<?php echo $_status ?>"><?php echo $_status_obj->labels->name ?></option>
     941        <?php
     942        } // endforeach stati
     943        endif; // $bulk ?>
     944                                <?php endif; ?>
     945        <?php foreach( get_post_stati( array( 'moderation' => true, 'internal' => false, 'object_type' => $screen->post_type ), 'object' ) as $_status => $_status_obj ) :
     946        $cap_name = "set_{$_status}_posts";
     947        if ( empty( $post_type_object->cap->$cap_name ) || current_user_can( $post_type_object->cap->$cap_name ) ) {
     948        ?>
     949                                                <option value="<?php echo $_status ?>"><?php echo $_status_obj->labels->caption ?></option>
     950        <?php
     951        } // endif
     952        endforeach; ?>
    919953                                                <option value="draft"><?php _e( 'Draft' ); ?></option>
    920954                                        </select>
    921955                                </label>
  • wp-admin/includes/meta-boxes.php

     
    1111 */
    1212function post_submit_meta_box($post) {
    1313        global $action;
     14       
     15        $post_type = $post->post_type;
     16        $post_type_obj = get_post_type_object($post_type);
     17        $can_publish = current_user_can($post_type_obj->cap->publish_posts);
     18        $post_status = $post->post_status;
     19       
     20        if ( ! $post_status_obj = get_post_status_object($post_status) )
     21                $post_status_obj = get_post_status_object( 'draft' );
     22       
     23        $moderation_stati = get_post_stati( array( 'moderation' => true, 'internal' => false, 'object_type' => $post_type ), 'object' );
    1424
    15         $post_type = $post->post_type;
    16         $post_type_object = get_post_type_object($post_type);
    17         $can_publish = current_user_can($post_type_object->cap->publish_posts);
     25        foreach( array_keys($moderation_stati) as $_status ) {
     26                $set_cap = "set_{$_status}_posts";
     27                if ( ( $_status != $post_status ) && ( ! empty( $post_type_obj->cap->$set_cap ) && ! current_user_can( $post_type_obj->cap->$set_cap ) ) )
     28                        unset( $moderation_stati[$_status] );
     29        }
    1830?>
    1931<div class="submitbox" id="submitpost">
    2032
     
    2739
    2840<div id="minor-publishing-actions">
    2941<div id="save-action">
    30 <?php if ( 'publish' != $post->post_status && 'future' != $post->post_status && 'pending' != $post->post_status )  { ?>
    31 <input <?php if ( 'private' == $post->post_status ) { ?>style="display:none"<?php } ?> type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save Draft'); ?>" tabindex="4" class="button button-highlighted" />
    32 <?php } elseif ( 'pending' == $post->post_status && $can_publish ) { ?>
    33 <input type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save as Pending'); ?>" tabindex="4" class="button button-highlighted" />
     42<?php //if ( 'publish' != $post_status && 'future' != $post_status && 'pending' != $post_status )  {
     43if ( ! $post_status_obj->public && ! $post_status_obj->private && ! $post_status_obj->moderation && ( 'future' != $post_status ) ) {  // TODO: confirm we don't need a hidden save button when current status is private
     44        $draft_status_obj = get_post_status_object( 'draft' );
     45?>
     46<input type="submit" name="save" id="save-post" value="<?php echo $draft_status_obj->labels->save_as ?>" tabindex="4" class="button button-highlighted" />
     47<?php
     48} elseif ( $post_status_obj->moderation && $can_publish ) {                     
     49?>
     50<input type="submit" name="save" id="save-post" value="<?php echo $post_status_obj->labels->save_as ?>" tabindex="4" class="button button-highlighted" />
    3451<?php } ?>
    3552<img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-loading" id="draft-ajax-loading" alt="" />
    3653</div>
    3754
    3855<div id="preview-action">
    3956<?php
    40 if ( 'publish' == $post->post_status ) {
     57if ( $post_status_obj->public ) {
    4158        $preview_link = esc_url(get_permalink($post->ID));
    4259        $preview_button = __('Preview Changes');
    4360} else {
     
    5774<div class="misc-pub-section<?php if ( !$can_publish ) { echo ' misc-pub-section-last'; } ?>"><label for="post_status"><?php _e('Status:') ?></label>
    5875<span id="post-status-display">
    5976<?php
    60 switch ( $post->post_status ) {
    61         case 'private':
    62                 _e('Privately Published');
    63                 break;
    64         case 'publish':
    65                 _e('Published');
    66                 break;
    67         case 'future':
    68                 _e('Scheduled');
    69                 break;
    70         case 'pending':
    71                 _e('Pending Review');
    72                 break;
    73         case 'draft':
    74         case 'auto-draft':
    75                 _e('Draft');
    76                 break;
    77         case 'auto-draft':
    78                 _e('Unsaved');
    79                 break;
    80 }
     77echo $post_status_obj->labels->caption;
    8178?>
    8279</span>
    83 <?php if ( 'publish' == $post->post_status || 'private' == $post->post_status || $can_publish ) { ?>
    84 <a href="#post_status" <?php if ( 'private' == $post->post_status ) { ?>style="display:none;" <?php } ?>class="edit-post-status hide-if-no-js" tabindex='4'><?php _e('Edit') ?></a>
     80<?php
     81$select_moderation = ( count($moderation_stati) > 1 || ( $post_status != key($moderation_stati) ) );  // multiple moderation stati are selectable or a single non-current moderation stati is selectable
    8582
     83if ( $post_status_obj->public || $post_status_obj->private || $can_publish || $select_moderation ) { ?>
     84<a href="#post_status" <?php if ( $post_status_obj->private || ( $post_status_obj->public && 'publish' != $post_status ) ) { ?>style="display:none;" <?php } ?>class="edit-post-status hide-if-no-js" tabindex='4'><?php _e('Edit') ?></a>
     85
    8686<div id="post-status-select" class="hide-if-js">
    87 <input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr( ('auto-draft' == $post->post_status ) ? 'draft' : $post->post_status); ?>" />
     87<input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr( ('auto-draft' == $post_status ) ? 'draft' : $post_status); ?>" />
    8888<select name='post_status' id='post_status' tabindex='4'>
    89 <?php if ( 'publish' == $post->post_status ) : ?>
    90 <option<?php selected( $post->post_status, 'publish' ); ?> value='publish'><?php _e('Published') ?></option>
    91 <?php elseif ( 'private' == $post->post_status ) : ?>
    92 <option<?php selected( $post->post_status, 'private' ); ?> value='publish'><?php _e('Privately Published') ?></option>
    93 <?php elseif ( 'future' == $post->post_status ) : ?>
    94 <option<?php selected( $post->post_status, 'future' ); ?> value='future'><?php _e('Scheduled') ?></option>
     89
     90<?php if ( $post_status_obj->public || $post_status_obj->private || ( 'future' == $post_status ) ) : ?>
     91<option<?php selected( $post_status, $post_status ); ?> value='publish'><?php echo $post_status_obj->labels->caption ?></option>
    9592<?php endif; ?>
    96 <option<?php selected( $post->post_status, 'pending' ); ?> value='pending'><?php _e('Pending Review') ?></option>
    97 <?php if ( 'auto-draft' == $post->post_status ) : ?>
    98 <option<?php selected( $post->post_status, 'auto-draft' ); ?> value='draft'><?php _e('Draft') ?></option>
    99 <?php else : ?>
    100 <option<?php selected( $post->post_status, 'draft' ); ?> value='draft'><?php _e('Draft') ?></option>
    101 <?php endif; ?>
     93
     94<?php
     95foreach( $moderation_stati as $_status => $_status_obj ) : ?>
     96<option<?php selected( $post_status, $_status ); ?> value='<?php echo $_status ?>'><?php echo $_status_obj->labels->caption ?></option>
     97<?php endforeach ?>
     98
     99<?php
     100$draft_status_obj = get_post_status_object( 'draft' );
     101$compare_status = ( 'auto-draft' == $post_status ) ? 'auto-draft' : 'draft';
     102?>
     103<option<?php selected( $post_status, $compare_status ); ?> value='draft'><?php echo $draft_status_obj->label ?></option>
     104
    102105</select>
    103106 <a href="#post_status" class="save-post-status hide-if-no-js button"><?php _e('OK'); ?></a>
    104107 <a href="#post_status" class="cancel-post-status hide-if-no-js"><?php _e('Cancel'); ?></a>
     
    110113<div class="misc-pub-section " id="visibility">
    111114<?php _e('Visibility:'); ?> <span id="post-visibility-display"><?php
    112115
    113 if ( 'private' == $post->post_status ) {
     116if ( 'future' == $post_status ) {       // indicate eventual visibility of scheduled post
     117        if ( ! $vis_status = get_post_meta( $post->ID, '_scheduled_status', true ) )
     118                $vis_status = 'publish';       
     119
     120        $vis_status_obj = get_post_status_object( $vis_status );
     121} else {
     122        $vis_status = $post_status;
     123        $vis_status_obj = $post_status_obj;
     124}
     125       
     126if ( 'publish' == $vis_status ) {
    114127        $post->post_password = '';
    115         $visibility = 'private';
    116         $visibility_trans = __('Private');
     128        $visibility = 'public';
     129
     130        if ( post_type_supports( $post->post_type, 'sticky' ) && is_sticky( $post->ID ) ) {
     131                $visibility_trans = __('Public, Sticky');
     132        } else {
     133            $visibility_trans = __('Public');
     134        }
     135} elseif ( $vis_status_obj->public  ) {
     136        $post->post_password = '';
     137        $visibility = $vis_status;
     138
     139        if ( post_type_supports( $post->post_type, 'sticky' ) && is_sticky( $post->ID ) ) {
     140                $visibility_trans = sprintf( __('%s, Sticky'), $vis_status_obj->label );
     141    } else {
     142            $visibility_trans = $vis_status_obj->labels->visibility;
     143        }
     144} elseif ( $vis_status_obj->private ) {
     145        $post->post_password = '';
     146        $visibility_trans = $vis_status_obj->labels->visibility;
    117147} elseif ( !empty( $post->post_password ) ) {
    118148        $visibility = 'password';
    119149        $visibility_trans = __('Password protected');
    120 } elseif ( post_type_supports( $post->post_type, 'sticky' ) && is_sticky( $post->ID ) ) {
    121         $visibility = 'public';
    122         $visibility_trans = __('Public, Sticky');
    123150} else {
    124151        $visibility = 'public';
    125152        $visibility_trans = __('Public');
     
    136163<?php endif; ?>
    137164<input type="hidden" name="hidden_post_visibility" id="hidden-post-visibility" value="<?php echo esc_attr( $visibility ); ?>" />
    138165
     166<input type="radio" name="visibility" id="visibility-radio-public" value="public" <?php checked( $visibility, 'public' ); ?> /> <label for="visibility-radio-public" class="selectit"><?php _e('Public'); ?></label><br />
    139167
    140 <input type="radio" name="visibility" id="visibility-radio-public" value="public" <?php checked( $visibility, 'public' ); ?> /> <label for="visibility-radio-public" class="selectit"><?php _e('Public'); ?></label><br />
    141 <?php if ( post_type_supports( $post->post_type, 'sticky' ) ): ?>
     168<?php
     169foreach( get_post_stati( array( 'public' => true, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ) :
     170        if ( 'publish' == $_status )
     171                continue;
     172
     173        $post_cap = "set_{$_status}_posts";
     174        if ( empty( $post_type_obj->cap->$post_cap ) || current_user_can( $post_type_obj->cap->$post_cap ) ) {
     175?>
     176<input type="radio" name="visibility" id="visibility-radio-<?php echo $_status ?>" value="<?php echo $_status ?>" <?php checked( $visibility, $_status ); ?> /> <label for="visibility-radio-<?php echo $_status ?>" class="selectit"><?php echo $_status_obj->labels->visibility ?></label><br />     
     177<?php
     178        } // end if this user can set status
     179endforeach ?>
     180
     181<?php if ( post_type_supports( $post->post_type, 'sticky' ) ) : ?>
    142182<span id="sticky-span"><input id="sticky" name="sticky" type="checkbox" value="sticky" <?php checked(is_sticky($post->ID)); ?> tabindex="4" /> <label for="sticky" class="selectit"><?php _e('Stick this to the front page') ?></label><br /></span>
    143183<?php endif; ?>
     184
    144185<input type="radio" name="visibility" id="visibility-radio-password" value="password" <?php checked( $visibility, 'password' ); ?> /> <label for="visibility-radio-password" class="selectit"><?php _e('Password protected'); ?></label><br />
    145186<span id="password-span"><label for="post_password"><?php _e('Password:'); ?></label> <input type="text" name="post_password" id="post_password" value="<?php echo esc_attr($post->post_password); ?>" /><br /></span>
    146 <input type="radio" name="visibility" id="visibility-radio-private" value="private" <?php checked( $visibility, 'private' ); ?> /> <label for="visibility-radio-private" class="selectit"><?php _e('Private'); ?></label><br />
    147187
     188<?php
     189foreach( get_post_stati( array( 'private' => true, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ) :
     190        $post_cap = "set_{$_status}_posts";
     191        if ( empty( $post_type_obj->cap->$post_cap ) || current_user_can( $post_type_obj->cap->$post_cap ) ) {
     192?>
     193<input type="radio" name="visibility" id="visibility-radio-<?php echo $_status ?>" value="<?php echo $_status ?>" <?php checked( $visibility, $_status ); ?> /> <label for="visibility-radio-<?php echo $_status ?>" class="selectit"><?php echo $_status_obj->label ?></label><br />   
     194<?php
     195        } // end if this user can set status
     196endforeach ?>
    148197<p>
    149198 <a href="#visibility" class="save-post-visibility hide-if-no-js button"><?php _e('OK'); ?></a>
    150199 <a href="#visibility" class="cancel-post-visibility hide-if-no-js"><?php _e('Cancel'); ?></a>
     
    158207<?php
    159208// translators: Publish box date formt, see http://php.net/date
    160209$datef = __( 'M j, Y @ G:i' );
     210
     211$published_stati = get_post_stati( array( 'public' => true, 'private' => true ), 'names', 'or' );
     212
    161213if ( 0 != $post->ID ) {
    162         if ( 'future' == $post->post_status ) { // scheduled for publishing at a future date
     214        if ( 'future' == $post_status ) { // scheduled for publishing at a future date
    163215                $stamp = __('Scheduled for: <b>%1$s</b>');
    164         } else if ( 'publish' == $post->post_status || 'private' == $post->post_status ) { // already published
     216        } else if ( in_array( $post_status, $published_stati ) ) { // already published
    165217                $stamp = __('Published on: <b>%1$s</b>');
    166218        } else if ( '0000-00-00 00:00:00' == $post->post_date_gmt ) { // draft, 1 or more saves, no date specified
    167219                $stamp = __('Publish <b>immediately</b>');
     
    207259<div id="publishing-action">
    208260<img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-loading" id="ajax-loading" alt="" />
    209261<?php
    210 if ( !in_array( $post->post_status, array('publish', 'future', 'private') ) || 0 == $post->ID ) {
     262if ( ( ! $post_status_obj->public && ! $post_status_obj->private && ( 'future' != $post_status ) ) ) {
    211263        if ( $can_publish ) :
    212                 if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) : ?>
    213                 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Schedule') ?>" />
    214                 <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php esc_attr_e('Schedule') ?>" />
    215 <?php   else : ?>
    216                 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish') ?>" />
    217                 <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php esc_attr_e('Publish') ?>" />
     264                if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) :
     265                $future_status_obj = get_post_status_object( 'future' );
     266                ?>
     267                <input name="original_publish" type="hidden" id="original_publish" value="<?php echo $future_status_obj->labels->publish ?>" />
     268                <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php echo $future_status_obj->labels->publish ?>" />
     269<?php   else :
     270                $publish_status_obj = get_post_status_object( 'publish' );
     271                ?>
     272                <input name="original_publish" type="hidden" id="original_publish" value="<?php echo $publish_status_obj->labels->publish ?>" />
     273                <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php echo $publish_status_obj->labels->publish ?>" />
    218274<?php   endif;
    219275        else : ?>
    220                 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review') ?>" />
    221                 <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php esc_attr_e('Submit for Review') ?>" />
     276                <?php
     277                $moderation_button_status = apply_filters( 'post_moderation_status', 'pending', $post->ID );
     278
     279                $status_obj = get_post_status_object( $moderation_button_status );
     280                $cap_name = "set_{$moderation_button_status}_posts";
     281
     282                if ( ! $status_obj || ( ! empty($post_type_obj->cap->$cap_name) && ! current_user_can($post_type_obj->cap->$cap_name) ) )
     283                        $status_obj = get_post_status_object( 'pending' );
     284                ?>
     285                <input name="original_publish" type="hidden" id="original_publish" value="<?php echo $status_obj->labels->publish ?>" />
     286                <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php echo $status_obj->labels->publish ?>" />
    222287<?php
    223288        endif;
    224289} else { ?>
  • wp-admin/includes/nav-menu.php

     
    10131013 */
    10141014function _wp_nav_menu_meta_box_object( $object = null ) {
    10151015        if ( isset( $object->name ) ) {
     1016                $public_stati = apply_filters( 'nav_menu_metabox_stati', get_post_stati( array( 'public' => true, 'object_type' => $object->name ) ), $object );
     1017                $public_csv = implode( ',', $public_stati );
    10161018
    10171019                if ( 'page' == $object->name ) {
    10181020                        $object->_default_query = array(
    10191021                                'orderby' => 'menu_order title',
    1020                                 'post_status' => 'publish',
     1022                                'post_status' => $public_csv,
    10211023                        );
    10221024
    1023                 // posts should show only published items
     1025                // posts should show only public items
    10241026                } elseif ( 'post' == $object->name ) {
    10251027                        $object->_default_query = array(
    1026                                 'post_status' => 'publish',
     1028                                'post_status' => $public_csv,
    10271029                        );
    10281030
    10291031                // cats should be in reverse chronological order
     
    10331035                                'order' => 'DESC',
    10341036                        );
    10351037
    1036                 // custom post types should show only published items
     1038                // custom post types should show only public items
    10371039                } else {
    10381040                        $object->_default_query = array(
    1039                                 'post_status' => 'publish',
     1041                                'post_status' => $public_csv,
    10401042                        );
    10411043                }
    10421044        }
  • wp-admin/includes/post.php

     
    6464        // What to do based on which button they pressed
    6565        if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
    6666                $post_data['post_status'] = 'draft';
    67         if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
     67        if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] ) // TODO: is this set anywhere?
    6868                $post_data['post_status'] = 'private';
    6969        if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( !isset($post_data['post_status']) || $post_data['post_status'] != 'private' ) )
    7070                $post_data['post_status'] = 'publish';
     
    8181
    8282        // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
    8383        // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
    84         if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $ptype->cap->publish_posts )) )
    85                 if ( $previous_status != 'publish' || !current_user_can( 'edit_post', $post_id ) )
    86                         $post_data['post_status'] = 'pending';
     84        if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $ptype->cap->publish_posts )) ) {
     85                if ( $previous_status != 'publish' || !current_user_can( 'edit_post', $post_id ) ) {
     86                        $moderation_status = apply_filters( 'post_moderation_status', 'pending', $post->ID );
    8787
     88                        $_status_obj = get_post_status_object( $moderation_status );
     89                        $cap_name = "set_{$moderation_status}_posts";
     90
     91                        if ( empty($_status_obj) || ! $_status_obj->moderation || ( ! empty($ptype->cap->$cap_name) && ! current_user_can($ptype->cap->$cap_name) ) )
     92                                $moderation_status = 'pending';
     93
     94                        $post_data['post_status'] = $moderation_status;
     95                }
     96        }
     97
    8898        if ( ! isset($post_data['post_status']) )
    8999                $post_data['post_status'] = $previous_status;
    90100
     
    169179                        case 'password' :
    170180                                unset( $post_data['sticky'] );
    171181                                break;
    172                         case 'private' :
    173                                 $post_data['post_status'] = 'private';
    174                                 $post_data['post_password'] = '';
    175                                 unset( $post_data['sticky'] );
    176                                 break;
     182                        default:
     183                                $status_obj = get_post_status_object( $post_data['visibility'] );
     184       
     185                                if ( ! empty( $status_obj->private ) || ! empty( $status_obj->public ) ) {
     186                                        $post_data['post_status'] = $status_obj->name;
     187                                        $post_data['post_password'] = '';
     188                                }
     189
     190                                if ( ! empty( $status_obj->private ) ) {
     191                                        unset( $post_data['sticky'] );
     192                                }
    177193                }
    178194        }
    179195
     
    476492                        case 'password' :
    477493                                unset( $_POST['sticky'] );
    478494                                break;
    479                         case 'private' :
    480                                 $_POST['post_status'] = 'private';
    481                                 $_POST['post_password'] = '';
    482                                 unset( $_POST['sticky'] );
    483                                 break;
     495                        default:
     496                                $status_obj = get_post_status_object( $_POST['visibility'] );   
     497                                if ( ! empty( $status_obj->private ) ) {
     498                                        $_POST['post_status'] = $status_obj->name;
     499                                        $_POST['post_password'] = '';
     500                                        unset( $_POST['sticky'] );
     501                                }
    484502                }
    485503        }
    486504
     
    827845
    828846        if ( isset($q['orderby']) )
    829847                $orderby = $q['orderby'];
    830         elseif ( isset($q['post_status']) && in_array($q['post_status'], array('pending', 'draft')) )
     848        elseif ( isset($q['post_status']) && ( in_array($q['post_status'], array('pending', 'draft')) || ! empty( $GLOBALS['wp_post_statuses'][$q['post_status']]->moderation ) ) )
    831849                $orderby = 'modified';
    832850
    833851        if ( isset($q['order']) )
     
    977995        $original_date = $post->post_date;
    978996        $original_name = $post->post_name;
    979997
     998        $post_status_obj = get_post_status_object( $post->post_status );
     999       
    9801000        // Hack: get_permalink would return ugly permalink for
    9811001        // drafts, so we will fake, that our post is published
    982         if ( in_array($post->post_status, array('draft', 'pending')) ) {
     1002        if ( in_array($post->post_status, array('draft', 'pending')) || ! empty($post_status_obj->moderation) ) {
    9831003                $post->post_status = 'publish';
    9841004                $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
    9851005        }
     
    10361056
    10371057        list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
    10381058
    1039         if ( 'publish' == $post->post_status ) {
     1059        $public_stati = get_post_stati( array( 'public' => true ) );
     1060        if ( in_array( $post->post_status, $public_stati ) ) {
    10401061                $ptype = get_post_type_object($post->post_type);
    10411062                $view_post = $ptype->labels->view_item;
    10421063                $title = __('Click to edit this part of the permalink');
  • wp-admin/includes/template.php

     
    277277        <div class="post_author">' . $post->post_author . '</div>
    278278        <div class="comment_status">' . $post->comment_status . '</div>
    279279        <div class="ping_status">' . $post->ping_status . '</div>
    280         <div class="_status">' . $post->post_status . '</div>
     280        <div class="_status">' . $post->post_status . '</div>';
     281
     282        if ( 'future' == $post->post_status ) {
     283                if ( ! $scheduled_status = get_post_meta( $post->ID, '_scheduled_status', true ) )
     284                        $scheduled_status = 'publish'; 
     285        echo '
     286        <div class="scheduled_status">' . $scheduled_status . '</div>';
     287        }
     288
     289        echo '
    281290        <div class="jj">' . mysql2date( 'd', $post->post_date, false ) . '</div>
    282291        <div class="mm">' . mysql2date( 'm', $post->post_date, false ) . '</div>
    283292        <div class="aa">' . mysql2date( 'Y', $post->post_date, false ) . '</div>
     
    579588function touch_time( $edit = 1, $for_post = 1, $tab_index = 0, $multi = 0 ) {
    580589        global $wp_locale, $post, $comment;
    581590
    582         if ( $for_post )
    583                 $edit = ! ( in_array($post->post_status, array('draft', 'pending') ) && (!$post->post_date_gmt || '0000-00-00 00:00:00' == $post->post_date_gmt ) );
    584 
     591        if ( $for_post ) {
     592                $post_status_obj = get_post_status_object($post->post_status);
     593                $edit = ( ( 'draft' != $post->post_status ) && empty($post_status_obj->moderation) ) || ( $post->post_date_gmt && '0000-00-00 00:00:00' != $post->post_date_gmt );
     594        }
     595                       
    585596        $tab_index_attribute = '';
    586597        if ( (int) $tab_index > 0 )
    587598                $tab_index_attribute = " tabindex=\"$tab_index\"";
     
    15961607        else
    15971608                $post_status = '';
    15981609
     1610        $post_status_obj = get_post_status_object($post->post_status);
     1611       
    15991612        if ( !empty($post->post_password) )
    16001613                $post_states[] = __('Password protected');
    1601         if ( 'private' == $post->post_status && 'private' != $post_status )
    1602                 $post_states[] = __('Private');
    1603         if ( 'draft' == $post->post_status && 'draft' != $post_status )
    1604                 $post_states[] = __('Draft');
    1605         if ( 'pending' == $post->post_status && 'pending' != $post_status )
    1606                 /* translators: post state */
    1607                 $post_states[] = _x('Pending', 'post state');
     1614       
     1615        if ( $post_status_obj && ( 'publish' != $post->post_status ) ) {
     1616                if ( $post->post_status != $post_status ) {
     1617                        $post_states[] = $post_status_obj->label;
     1618
     1619                        if ( 'future' == $post->post_status ) {
     1620                                if ( $scheduled_status = get_post_meta( $post->ID, '_scheduled_status', true ) ) {
     1621                                        if ( 'publish' != $scheduled_status ) {
     1622                                                if ( $_scheduled_status_obj = get_post_status_object( $scheduled_status ) )
     1623                                                        $post_states[] = $_scheduled_status_obj->label;
     1624                                        }
     1625                                }
     1626                        }
     1627                }
     1628        }
     1629
    16081630        if ( is_sticky($post->ID) )
    16091631                $post_states[] = __('Sticky');
    16101632
  • wp-admin/js/inline-edit-post.dev.js

     
    7878                        if ( $('form#posts-filter tr.inline-editor').length > 0 )
    7979                                t.revert();
    8080                });
     81               
     82                $('.keep-private, .keep-private input').click(function() {
     83                        if ( $(this).attr('checked') ) {
     84                                $('.keep-private input').filter("[name!='" + $(this).attr('name') + "']").removeAttr('checked');
     85                        }
     86                });
    8187        },
    8288
    8389        toggle : function(el){
     
    128134                if ( typeof(id) == 'object' )
    129135                        id = t.getId(id);
    130136
    131                 fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password'];
     137                fields = ['post_title', 'post_name', 'post_author', '_status', 'scheduled_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password'];
    132138                if ( t.type == 'page' )
    133139                        fields.push('post_parent', 'menu_order', 'page_template');
    134140
     
    178184                        }
    179185                });
    180186
    181 
    182187                // handle the post status
    183188                status = $('._status', rowData).text();
    184                 if ( 'future' != status )
     189
     190                if ( 'future' == status ) {
     191                        status = $('.scheduled_status', rowData).text();
     192                } else {
    185193                        $('select[name="_status"] option[value="future"]', editRow).remove();
     194                }
    186195
    187                 if ( 'private' == status ) {
    188                         $('input[name="keep_private"]', editRow).attr("checked", "checked");
     196                if ( $('[name=keep_' + status + ']').length > 0) {
     197                        $('input[name="keep_' + status + '"]', editRow).attr("checked", "checked");
    189198                        $('input.inline-edit-password-input').val('').attr('disabled', 'disabled');
    190199                }
    191200
  • wp-admin/js/post.dev.js

     
    346346
    347347                function updateVisibility() {
    348348                        var pvSelect = $('#post-visibility-select');
    349                         if ( $('input:radio:checked', pvSelect).val() != 'public' ) {
    350                                 $('#sticky').attr('checked', false);
    351                                 $('#sticky-span').hide();
    352                         } else {
    353                                 $('#sticky-span').show();
    354                         }
    355349                        if ( $('input:radio:checked', pvSelect).val() != 'password' ) {
    356350                                $('#password-span').hide();
    357351                        } else {
     
    360354                }
    361355
    362356                function updateText() {
    363                         var attemptedDate, originalDate, currentDate, publishOn, page = 'page' == pagenow || 'page-new' == pagenow,
     357                        var attemptedDate, originalDate, currentDate, publishOn,
    364358                                postStatus = $('#post_status'), optPublish = $('option[value=publish]', postStatus), aa = $('#aa').val(),
    365359                                mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val();
    366360
     
    383377                                $('#publish').val( postL10n.publish );
    384378                        } else {
    385379                                publishOn = postL10n.publishOnPast;
    386                                 if ( page )
    387                                         $('#publish').val( postL10n.updatePage );
    388                                 else
    389                                         $('#publish').val( postL10n.updatePost );
     380                                $('#publish').val( postL10n.update );
    390381                        }
     382
    391383                        if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) { //hack
    392384                                $('#timestamp').html(stamp);
    393385                        } else {
     
    402394                        }
    403395
    404396                        if ( $('input:radio:checked', '#post-visibility-select').val() == 'private' ) {
    405                                 if ( page )
    406                                         $('#publish').val( postL10n.updatePage );
    407                                 else
    408                                         $('#publish').val( postL10n.updatePost );
    409                                 if ( optPublish.length == 0 ) {
    410                                         postStatus.append('<option value="publish">' + postL10n.privatelyPublished + '</option>');
    411                                 } else {
    412                                         optPublish.html( postL10n.privatelyPublished );
     397                                if ( attemptedDate <= currentDate ) {
     398                                        $('#publish').val( postL10n.update );
    413399                                }
     400
    414401                                $('option[value=publish]', postStatus).attr('selected', true);
    415402                                $('.edit-post-status', '#misc-publishing-actions').hide();
    416403                        } else {
     
    425412                                if ( postStatus.is(':hidden') )
    426413                                        $('.edit-post-status', '#misc-publishing-actions').show();
    427414                        }
    428                         $('#post-status-display').html($('option:selected', postStatus).text());
    429                         if ( $('option:selected', postStatus).val() == 'private' || $('option:selected', postStatus).val() == 'publish' ) {
    430                                 $('#save-post').hide();
    431                         } else {
    432                                 $('#save-post').show();
    433                                 if ( $('option:selected', postStatus).val() == 'pending' ) {
    434                                         $('#save-post').show().val( postL10n.savePending );
    435                                 } else {
    436                                         $('#save-post').show().val( postL10n.saveDraft );
    437                                 }
    438                         }
     415
    439416                        return true;
    440417                }
    441418
     
    447424                        }
    448425                        return false;
    449426                });
    450 
     427               
    451428                $('.cancel-post-visibility', '#post-visibility-select').click(function () {
    452429                        $('#post-visibility-select').slideUp("normal");
    453430                        $('#visibility-radio-' + $('#hidden-post-visibility').val()).attr('checked', true);
     
    455432                        $('#sticky').attr('checked', $('#hidden-post-sticky').attr('checked'));
    456433                        $('#post-visibility-display').html(visibility);
    457434                        $('.edit-visibility', '#visibility').show();
    458                         updateText();
    459435                        return false;
    460436                });
    461 
     437               
    462438                $('.save-post-visibility', '#post-visibility-select').click(function () { // crazyhorse - multiple ok cancels
    463439                        var pvSelect = $('#post-visibility-select');
    464440
    465441                        pvSelect.slideUp("normal");
    466442                        $('.edit-visibility', '#visibility').show();
    467                         updateText();
    468443
    469                         if ( $('input:radio:checked', pvSelect).val() != 'public' ) {
    470                                 $('#sticky').attr('checked', false);
    471                         } // WEAPON LOCKED
    472 
    473444                        if ( true == $('#sticky').attr('checked') ) {
    474445                                sticky = 'Sticky';
    475446                        } else {
    476447                                sticky = '';
    477448                        }
    478 
     449       
    479450                        $('#post-visibility-display').html(     postL10n[$('input:radio:checked', pvSelect).val() + sticky]     );
    480451                        return false;
    481452                });
    482 
     453               
    483454                $('input:radio', '#post-visibility-select').change(function() {
    484455                        updateVisibility();
    485456                });
  • wp-admin/post.php

     
    6868                                        $message = 9;
    6969                                        break;
    7070                                default:
    71                                         $message = 6;
     71                                        $status_obj = get_post_status_object( $status );
     72                                        if ( ! empty($status_obj->moderation) )
     73                                                $message = 11;
     74                                        else
     75                                                $message = 6;
    7276                        }
    7377                } else {
    7478                                $message = 'draft' == $status ? 10 : 1;
  • wp-comments-post.php

     
    3737} elseif ( 'trash' == $status ) {
    3838        do_action('comment_on_trash', $comment_post_ID);
    3939        exit;
    40 } elseif ( !$status_obj->public && !$status_obj->private ) {
     40} elseif ( empty($status_obj->public) && empty($status_obj->private) ) {
    4141        do_action('comment_on_draft', $comment_post_ID);
    4242        exit;
    4343} elseif ( post_password_required($comment_post_ID) ) {
  • wp-includes/default-widgets.php

     
    542542                else if ( $number > 15 )
    543543                        $number = 15;
    544544
    545                 $r = new WP_Query(array('posts_per_page' => $number, 'nopaging' => 0, 'post_status' => 'publish', 'ignore_sticky_posts' => true));
     545                $public_stati = apply_filters( 'recent_posts_stati', get_post_stati( array( 'public' => true ) ) );
     546                $status_arg = implode( ',', $public_stati );
     547
     548                $r = new WP_Query(array('posts_per_page' => $number, 'nopaging' => 0, 'post_status' => $status_arg, 'ignore_sticky_posts' => true));
    546549                if ($r->have_posts()) :
    547550?>
    548551                <?php echo $before_widget; ?>
  • wp-includes/functions.php

     
    30473047        $filtered = array();
    30483048
    30493049        foreach ( $list as $key => $obj ) {
    3050                 $matched = count( array_intersect_assoc( (array) $obj, $args ) );
    3051                 if ( ('and' == $operator && $matched == $count) || ('or' == $operator && $matched <= $count) ) {
     3050                $matched = array_intersect_assoc( (array) $obj, $args );
     3051
     3052                foreach( array_keys( $matched ) as $_key ) {
     3053                        if ( is_array( $args[$_key] ) ) {
     3054                                if ( ! array_intersect( $args[$_key], $matched[$_key] ) )
     3055                                        unset( $matched[$_key] );       
     3056                        }       
     3057                }
     3058
     3059                $num_matched = count( $matched );
     3060               
     3061                if ( ( 'and' == $operator && $num_matched == $count ) || ( 'or' == $operator && $num_matched ) ) {
    30523062                        $filtered[$key] = $obj;
    30533063                }
    30543064        }
  • wp-includes/general-template.php

     
    882882        }
    883883
    884884        //filters
    885         $where = apply_filters('getarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
     885        $public_stati = apply_filters( 'getarchives_stati', get_post_stati( array( 'public' => true ) ) );
     886        $public_csv = implode( "', '", $public_stati );
     887
     888        $where = apply_filters('getarchives_where', "WHERE post_type = 'post' AND post_status IN ('" . $public_csv . "')", $r );
    886889        $join = apply_filters('getarchives_join', "", $r);
    887890
    888891        $output = '';
  • wp-includes/link-template.php

     
    114114
    115115        $permalink = apply_filters('pre_post_link', $permalink, $post, $leavename);
    116116
    117         if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {
     117        if ( '' != $permalink && ! in_array( $post->post_status, array('draft', 'auto-draft', 'pending') ) && empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation ) ) {
    118118                $unixtime = strtotime($post->post_date);
    119119
    120120                $category = '';
     
    185185
    186186        $slug = $post->post_name;
    187187
    188         $draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
     188        $draft_or_pending = in_array( $post->post_status, array('draft', 'auto-draft', 'pending') ) || ! empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation );
    189189
    190190        $post_type = get_post_type_object($post->post_type);
    191191
     
    273273
    274274        $link = $wp_rewrite->get_page_permastruct();
    275275
    276         if ( '' != $link && ( ( isset($post->post_status) && 'draft' != $post->post_status && 'pending' != $post->post_status ) || $sample ) ) {
     276        if ( '' != $link && ( ( isset($post->post_status) && ! in_array( $post->post_status, array('draft', 'auto-draft', 'pending') ) && empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation ) ) || $sample ) ) {
    277277                if ( ! $leavename )
    278278                        $link = str_replace('%pagename%', get_page_uri($id), $link);
    279279                $link = home_url($link);
  • wp-includes/nav-menu.php

     
    466466        if ( empty( $items ) )
    467467                return $items;
    468468
     469        $public_stati = apply_filters( 'nav_menu_stati', get_post_stati( array( 'public' => true ) ), $menu );
     470        $public_csv = implode( ',', $public_stati );
     471
    469472        $defaults = array( 'order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item',
    470                 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true,
     473                'post_status' => $public_csv, 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true,
    471474                'update_post_term_cache' => false );
    472475        $args = wp_parse_args( $args, $defaults );
    473476        if ( count( $items ) > 1 )
  • wp-includes/post-template.php

     
    108108        $id = isset($post->ID) ? $post->ID : (int) $id;
    109109
    110110        if ( !is_admin() ) {
    111                 if ( !empty($post->post_password) ) {
    112                         $protected_title_format = apply_filters('protected_title_format', __('Protected: %s'));
     111                if ( ! empty($post->post_password) ) {
     112                        $protected_title_format = apply_filters( 'protected_title_format', __( 'Protected: %s' ) );
    113113                        $title = sprintf($protected_title_format, $title);
    114                 } else if ( isset($post->post_status) && 'private' == $post->post_status ) {
    115                         $private_title_format = apply_filters('private_title_format', __('Private: %s'));
    116                         $title = sprintf($private_title_format, $title);
     114                } elseif ( isset($post->post_status) ) {
     115                        $post_status_obj = get_post_status_object( $post->post_status );
     116                        if ( $post_status_obj && $post_status_obj->private ) {
     117                                if ( 'private' == $post->post_status ) {
     118                                        $format_string = __( 'Private: %s' );  // preserve existing translation string
     119                                        $private_title_format = apply_filters( 'private_title_format', $format_string );
     120                                        $title = sprintf($private_title_format, $title);
     121                                } else {
     122                                        $format_string = _x( '%1$s: %2$s', 'post status: title' );     
     123                                        $private_title_format = apply_filters( 'post_title_format', $format_string, $_status );
     124                                        $title = sprintf($private_title_format, $post_status_obj->labels->name, $title);
     125                                }
     126                        }
    117127                }
    118128        }
    119129        return apply_filters( 'the_title', $title, $id );
     
    631641        if ( 1 == $i ) {
    632642                $url = get_permalink();
    633643        } else {
    634                 if ( '' == get_option('permalink_structure') || in_array($post->post_status, array('draft', 'pending')) )
     644                if ( '' == get_option('permalink_structure') || in_array( $post->post_status, array('draft', 'auto-draft', 'pending') ) || ! empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation ) )
    635645                        $url = add_query_arg( 'page', $i, get_permalink() );
    636646                elseif ( 'page' == get_option('show_on_front') && get_option('page_on_front') == $post->ID )
    637647                        $url = trailingslashit(get_permalink()) . user_trailingslashit("$wp_rewrite->pagination_base/" . $i, 'single_paged');
  • wp-includes/post.php

     
    8181        ) );
    8282
    8383        register_post_status( 'publish', array(
    84                 'label'       => _x( 'Published', 'post' ),
     84                'labels'          => array(
     85                        'name'    => _x( 'Published', 'post' ),
     86                        'publish' => esc_attr__('Publish'),
     87                        'count' => _n_noop( 'Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>' ),
     88                ),
    8589                'public'      => true,
    8690                '_builtin'    => true, /* internal use only. */
    87                 'label_count' => _n_noop( 'Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>' ),
    8891        ) );
    8992
    9093        register_post_status( 'future', array(
    91                 'label'       => _x( 'Scheduled', 'post' ),
     94                'labels'          => array(
     95                        'name'    => _x( 'Scheduled', 'post' ),
     96                        'publish' => esc_attr__('Schedule'),
     97                        'count' => _n_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>' ),
     98                ),
    9299                'protected'   => true,
    93100                '_builtin'    => true, /* internal use only. */
    94                 'label_count' => _n_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>' ),
    95101        ) );
    96102
    97103        register_post_status( 'draft', array(
    98                 'label'       => _x( 'Draft', 'post' ),
     104                'labels'          => array(
     105                        'name'    => _x( 'Draft', 'post' ),
     106                        'save_as' => esc_attr__('Save Draft'),
     107                        'count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>' ),
     108                ),
    99109                'protected'   => true,
    100110                '_builtin'    => true, /* internal use only. */
    101                 'label_count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>' ),
    102111        ) );
    103112
    104113        register_post_status( 'pending', array(
    105                 'label'       => _x( 'Pending', 'post' ),
     114                'labels'          => array(
     115                        'name'    => _x( 'Pending', 'post' ),
     116                        'caption' => __( 'Pending Review' ),
     117                        'publish' => esc_attr__('Submit for Review'),
     118                        'count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>' ),
     119                ),
    106120                'protected'   => true,
    107121                '_builtin'    => true, /* internal use only. */
    108                 'label_count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>' ),
     122                'moderation'  => true,
    109123        ) );
    110124
    111125        register_post_status( 'private', array(
    112                 'label'       => _x( 'Private', 'post' ),
     126                'labels'          => array(
     127                        'name'   => _x( 'Private', 'post' ),
     128                        'caption' => __( 'Privately Published' ),
     129                        'count' => _n_noop( 'Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>' ),
     130                ),
    113131                'private'     => true,
    114132                '_builtin'    => true, /* internal use only. */
    115                 'label_count' => _n_noop( 'Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>' ),
    116133        ) );
    117134
    118135        register_post_status( 'trash', array(
    119                 'label'       => _x( 'Trash', 'post' ),
     136                'labels'          => array(
     137                        'name'   => _x( 'Trash', 'post' ),
     138                        'count' => _n_noop( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>' ),
     139                ),
    120140                'internal'    => true,
    121141                '_builtin'    => true, /* internal use only. */
    122                 'label_count' => _n_noop( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>' ),
    123142                'show_in_admin_status_list' => true,
    124143        ) );
    125144
    126145        register_post_status( 'auto-draft', array(
    127                 'label'    => 'auto-draft',
     146                'labels'          => array(
     147                        'name'    => 'auto-draft',
     148                        'caption' => __( 'Draft' ),
     149                ),
    128150                'internal' => true,
    129151                '_builtin' => true, /* internal use only. */
    130152        ) );
    131153
    132154        register_post_status( 'inherit', array(
    133                 'label'    => 'inherit',
     155                'labels'          => array(
     156                        'name'   => 'inherit',
     157                ),
    134158                'internal' => true,
    135159                '_builtin' => true, /* internal use only. */
    136160                'exclude_from_search' => false,
     
    594618}
    595619
    596620/**
     621 * Add an already registered post status to an object type.
     622 *
     623 * @package WordPress
     624 * @subpackage Taxonomy
     625 * @since 3.1.0
     626 * @uses $wp_post_statuses Modifies post_type object
     627 *
     628 * @param string $post_status Name of post_status object
     629 * @param array|string $object_type Name of the object type
     630 * @return bool True if successful, false if not
     631 */
     632function register_status_for_object_type( $post_status, $object_type) {
     633        global $wp_post_statuses;
     634
     635        if ( ! isset( $wp_post_statuses[$post_status] ) )
     636                return false;
     637
     638        if ( ! get_post_type_object($object_type) )
     639                return false;
     640
     641        $wp_post_statuses[$post_status]->object_type[] = $object_type;
     642
     643        return true;
     644}
     645
     646/**
    597647 * Register a post type. Do not use before init.
    598648 *
    599649 * A simple function for creating or modifying a post status based on the
     
    622672                $wp_post_statuses = array();
    623673
    624674        // Args prefixed with an underscore are reserved for internal use.
    625         $defaults = array('label' => false, 'label_count' => false, 'exclude_from_search' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d', 'capability_type' => 'post', 'hierarchical' => false, 'public' => null, 'internal' => null, 'protected' => null, 'private' => null, 'show_in_admin_all' => null, 'publicly_queryable' => null, 'show_in_admin_status_list' => null, 'show_in_admin_all_list' => null, 'single_view_cap' => null);
     675        $defaults = array( 'object_type' => null, 'labels' => array(), 'label_count' => false, 'exclude_from_search' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d', 'capability_type' => 'post', 'hierarchical' => false, 'public' => null, 'internal' => null, 'protected' => null, 'private' => null, 'moderation' => null, 'show_in_admin_all' => null, 'publicly_queryable' => null, 'show_in_admin_status_list' => null, 'show_in_admin_all_list' => null, 'single_view_cap' => null);
     676       
    626677        $args = wp_parse_args($args, $defaults);
    627678        $args = (object) $args;
    628679
    629680        $post_status = sanitize_key($post_status);
    630681        $args->name = $post_status;
    631682
     683        if ( null == $args->object_type ) {
     684                $args->object_type = get_post_types( array( 'public' => true, 'show_ui' => true ) );
     685        } else {
     686                $args->object_type = (array) $args->object_type;
     687        }
     688       
    632689        if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private )
    633690                $args->internal = true;
    634691
     
    638695        if ( null === $args->private  )
    639696                $args->private = false;
    640697
     698        if ( null === $args->moderation  )
     699                $args->moderation = false;
     700               
    641701        if ( null === $args->protected  )
    642702                $args->protected = false;
    643703
     
    659719        if ( null === $args->single_view_cap )
    660720                $args->single_view_cap = $args->public ? '' : 'edit';
    661721
    662         if ( false === $args->label )
    663                 $args->label = $post_status;
     722        $args->labels = (object) $args->labels;
    664723
    665         if ( false === $args->label_count )
    666                 $args->label_count = array( $args->label, $args->label );
     724        if ( empty( $args->labels->name ) )
     725                $args->labels->name = ( ! empty( $args->label ) ) ? $args->label : $post_status;
     726       
     727        if ( empty( $args->label ) )
     728                $args->label = $args->labels->name;
     729               
     730        if ( empty( $args->labels->caption ) )
     731                $args->labels->caption = $args->label;
    667732
     733        if ( empty( $args->labels->count ) )
     734                $args->labels->count = ( ! empty( $args->label_count ) ) ? $args->label_count : array( $args->label, $args->label );
     735
     736        if ( empty( $args->label_count ) )      // TODO: need to support this for external API?
     737                $args->label_count = $args->labels->count;
     738
     739        if ( empty( $args->labels->publish ) )
     740                $args->labels->publish = esc_attr( sprintf( __( 'Set %s' ), $args->label ) );
     741
     742        if ( empty( $args->labels->save_as ) )
     743                $args->labels->save_as = esc_attr( sprintf( __( 'Save as %s' ), $args->label ) );
     744
     745        if ( empty( $args->labels->visibility ) ) {
     746                if ( 'publish' == $post_status )
     747                        $args->labels->visibility =__( 'Public' );
     748                elseif ( $args->public )
     749                        $args->labels->visibility = esc_attr( sprintf( __( 'Public (%s)' ), $args->label ) );
     750                elseif ( $args->private )
     751                        $args->labels->visibility = $args->label;
     752        }
     753
    668754        $wp_post_statuses[$post_status] = $args;
    669755
    670756        return $args;
     
    713799
    714800        $field = ('names' == $output) ? 'name' : false;
    715801
     802        if ( ! empty( $args['object_type'] ) )
     803                $args['object_type'] = (array) $args['object_type'];
     804       
    716805        return wp_filter_object_list($wp_post_statuses, $args, $operator, $field);
    717806}
    718807
     
    868957                'labels' => array(), 'description' => '', 'publicly_queryable' => null, 'exclude_from_search' => null,
    869958                '_builtin' => false, '_edit_link' => 'post.php?post=%d', 'capability_type' => 'post', 'capabilities' => array(), 'hierarchical' => false,
    870959                'public' => false, 'rewrite' => true, 'query_var' => true, 'supports' => array(), 'register_meta_box_cb' => null,
    871                 'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
     960                'taxonomies' => array(), 'statuses' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
    872961                'permalink_epmask' => EP_PERMALINK, 'can_export' => true, 'show_in_nav_menus' => null
    873962        );
    874963        $args = wp_parse_args($args, $defaults);
     
    9581047        foreach ( $args->taxonomies as $taxonomy ) {
    9591048                register_taxonomy_for_object_type( $taxonomy, $post_type );
    9601049        }
     1050       
     1051        foreach ( $args->statuses as $post_status ) {
     1052                register_status_for_object_type( $post_status, $post_type );
     1053        }
    9611054
    9621055        return $args;
    9631056}
     
    16241717        $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
    16251718        if ( 'readable' == $perm && is_user_logged_in() ) {
    16261719                $post_type_object = get_post_type_object($type);
    1627                 if ( !current_user_can( $post_type_object->cap->read_private_posts ) ) {
    1628                         $cache_key .= '_' . $perm . '_' . $user->ID;
    1629                         $query .= " AND (post_status != 'private' OR ( post_author = '$user->ID' AND post_status = 'private' ))";
     1720                foreach( get_post_stati( array( 'private' => true, 'object_type' => $type ) ) as $_status ) {
     1721                        $cap_name = "read_{$_status}_posts";
     1722                        if ( ! empty($post_type_object->cap->$cap_name) && ! current_user_can( $post_type_object->cap->$cap_name ) ) {
     1723                                $suffix = ( 'private' == $_status ) ? '' : $_status;
     1724                                $cache_key .= '_' . $perm . $suffix . '_' . $user->ID;
     1725                                $query .= " AND (post_status != '$_status' OR ( post_author = '$user->ID' AND post_status = '$_status' ))";
     1726                        }
    16301727                }
    16311728        }
    16321729        $query .= ' GROUP BY post_status';
    1633 
     1730       
    16341731        $count = wp_cache_get($cache_key, 'counts');
    16351732        if ( false !== $count )
    16361733                return $count;
     
    16381735        $count = $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
    16391736
    16401737        $stats = array();
    1641         foreach ( get_post_stati() as $state )
     1738        foreach ( get_post_stati( array( 'object_type' => $type ) ) as $state )
    16421739                $stats[$state] = 0;
    16431740
    16441741        foreach ( (array) $count as $row )
     
    21232220                $limit = "LIMIT $num";
    21242221        }
    21252222
    2126         $sql = "SELECT * FROM $wpdb->posts WHERE post_type = 'post' AND post_status IN ( 'draft', 'publish', 'future', 'pending', 'private' ) ORDER BY post_date DESC $limit";
     2223        $status_names = get_post_stati( array( 'public' => true, 'object_type' => 'post' ) );
     2224
     2225        $sql = "SELECT * FROM $wpdb->posts WHERE post_type = 'post' AND post_status IN ( '" . implode( "', '", $status_names ) . "' ) ORDER BY post_date DESC $limit";
    21272226        $result = $wpdb->get_results($sql, ARRAY_A);
    21282227
    21292228        return $result ? $result : array();
     
    22712370                $post_before = get_post($post_ID);
    22722371        }
    22732372
    2274         // Don't allow contributors to set to set the post slug for pending review posts
    2275         if ( 'pending' == $post_status && !current_user_can( 'publish_posts' ) )
     2373        // Don't allow contributors to set the post slug for pending review posts
     2374        $post_status_obj = get_post_status_object( $post_status );
     2375        $draft_or_pending = in_array( $post_status, array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation);
     2376
     2377        if ( ! empty( $post_status_obj->moderation ) && ! current_user_can( 'publish_posts' ) )
    22762378                $post_name = '';
    22772379
    22782380        // Create a valid post name.  Drafts and pending posts are allowed to have an empty
    22792381        // post name.
    22802382        if ( empty($post_name) ) {
    2281                 if ( !in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
     2383                if ( ! $draft_or_pending )
    22822384                        $post_name = sanitize_title($post_title);
    22832385                else
    22842386                        $post_name = '';
     
    22912393                $post_date = current_time('mysql');
    22922394
    22932395        if ( empty($post_date_gmt) || '0000-00-00 00:00:00' == $post_date_gmt ) {
    2294                 if ( !in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
     2396                if ( ! $draft_or_pending )
    22952397                        $post_date_gmt = get_gmt_from_date($post_date);
    22962398                else
    22972399                        $post_date_gmt = '0000-00-00 00:00:00';
     
    23052407                $post_modified_gmt = $post_date_gmt;
    23062408        }
    23072409
    2308         if ( 'publish' == $post_status ) {
     2410        $set_status = $post_status;
     2411       
     2412        if ( $post_status_obj->public || $post_status_obj->private ) {
    23092413                $now = gmdate('Y-m-d H:i:59');
    23102414                if ( mysql2date('U', $post_date_gmt, false) > mysql2date('U', $now, false) )
    23112415                        $post_status = 'future';
     
    23152419                        $post_status = 'publish';
    23162420        }
    23172421
     2422        if ( ( 'future' == $post_status ) && ( 'publish' != $set_status ) ) {
     2423                update_post_meta( $post_ID, '_scheduled_status', $set_status );
     2424        } else
     2425                delete_post_meta( $post_ID, '_scheduled_status' );
     2426
    23182427        if ( empty($comment_status) ) {
    23192428                if ( $update )
    23202429                        $comment_status = 'closed';
     
    23452454        else
    23462455                $menu_order = 0;
    23472456
    2348         if ( !isset($post_password) || 'private' == $post_status )
     2457        if ( ! isset($post_password) || $post_status_obj->private )
    23492458                $post_password = '';
    23502459
    23512460        $post_name = wp_unique_post_slug($post_name, $post_ID, $post_status, $post_type, $post_parent);
     
    23862495                $where = array( 'ID' => $post_ID );
    23872496        }
    23882497
    2389         if ( empty($data['post_name']) && !in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
     2498        $post_status_obj = get_post_status_object( $data['post_status'] );
     2499        $draft_or_pending = in_array( $data['post_status'], array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation);
     2500       
     2501        if ( empty($data['post_name']) && ! $draft_or_pending ) {
    23902502                $data['post_name'] = sanitize_title($data['post_title'], $post_ID);
    23912503                $wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where );
    23922504        }
     
    24792591                $post_cats = $post['post_category'];
    24802592
    24812593        // Drafts shouldn't be assigned a date unless explicitly done so by the user
    2482         if ( isset( $post['post_status'] ) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) && empty($postarr['edit_date']) &&
    2483                          ('0000-00-00 00:00:00' == $post['post_date_gmt']) )
    2484                 $clear_date = true;
    2485         else
     2594        if ( isset( $post['post_status'] ) && empty($postarr['edit_date']) && ('0000-00-00 00:00:00' == $post['post_date_gmt']) ) {
     2595                $post_status_obj = get_post_status_object( $post['post_status'] );
     2596
     2597                $clear_date = in_array( $post['post_status'], array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation);
     2598        } else
    24862599                $clear_date = false;
    24872600
    24882601        // Merge old and new fields with new fields overwriting old ones.
     
    25202633        if ( 'publish' == $post->post_status )
    25212634                return;
    25222635
    2523         $wpdb->update( $wpdb->posts, array( 'post_status' => 'publish' ), array( 'ID' => $post_id ) );
     2636        if ( 'future' == $post->post_status ) {
     2637                if ( ! $post_status = get_post_meta( $post_id, '_scheduled_status', true ) )
     2638                        $post_status = 'publish';       
     2639        } else
     2640                $post_status = 'publish';
    25242641
     2642        $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $post_id ) );
     2643
    25252644        $old_status = $post->post_status;
    25262645        $post->post_status = 'publish';
    25272646        wp_transition_post_status('publish', $old_status, $post);
     
    25832702 * @return string unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)
    25842703 */
    25852704function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent ) {
    2586         if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
     2705        $post_status_obj = get_post_status_object( $post_status );
     2706
     2707        if ( in_array( $post['post_status'], array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation) )
    25872708                return $slug;
    25882709
    25892710        global $wpdb, $wp_rewrite;
     
    31273248                return false;
    31283249
    31293250        // Make sure we have a valid post status
    3130         if ( !in_array($post_status, get_post_stati()) )
     3251        if ( ! in_array( $post_status, get_post_stati( array( 'object_type' => $post_type ) ) ) )
    31313252                return false;
    31323253
    31333254        $cache = array();
  • wp-includes/query.php

     
    20332033                        $post_type_object = get_post_type_object ( 'post' );
    20342034                }
    20352035
     2036                $_post_type = ( $post_type ) ? $post_type : 'post';  // corresponds to hardcoded default for POST_TYPE clause
     2037                $type_arg = ( 'any' == $_post_type ) ? array() : array( 'object_type' => $_post_type );
     2038
    20362039                if ( !empty($post_type_object) ) {
    20372040                        $post_type_cap = $post_type_object->capability_type;
    20382041                        $edit_cap = $post_type_object->cap->edit_post;
    20392042                        $read_cap = $post_type_object->cap->read_post;
    20402043                        $edit_others_cap = $post_type_object->cap->edit_others_posts;
    2041                         $read_private_cap = $post_type_object->cap->read_private_posts;
    20422044                } else {
    20432045                        $edit_cap = 'edit_' . $post_type_cap;
    20442046                        $read_cap = 'read_' . $post_type_cap;
    20452047                        $edit_others_cap = 'edit_others_' . $post_type_cap . 's';
    2046                         $read_private_cap = 'read_private_' . $post_type_cap . 's';
    20472048                }
    20482049
    20492050                if ( isset($q['post_status']) && '' != $q['post_status'] ) {
     
    20512052                        $q_status = explode(',', $q['post_status']);
    20522053                        $r_status = array();
    20532054                        $p_status = array();
     2055                        $p_status_owner = array();
    20542056                        $e_status = array();
    20552057                        if ( $q['post_status'] == 'any' ) {
    20562058                                foreach ( get_post_stati( array('exclude_from_search' => true) ) as $status )
    20572059                                        $e_status[] = "$wpdb->posts.post_status <> '$status'";
    20582060                        } else {
    2059                                 foreach ( get_post_stati() as $status ) {
     2061                                $_args = array_merge( array(), $type_arg );
     2062                                foreach ( get_post_stati( $_args, 'object' ) as $status => $status_obj ) {
    20602063                                        if ( in_array( $status, $q_status ) ) {
    2061                                                 if ( 'private' == $status )
    2062                                                         $p_status[] = "$wpdb->posts.post_status = '$status'";
    2063                                                 else
     2064                                                if ( $status_obj->private ) {
     2065                                                        if ( ! empty($post_type_object) ) {
     2066                                                                $check_cap = "read_{$status}_posts";
     2067                                                                $read_private_cap = ( ! empty( $post_type_object->cap->$check_cap ) ) ? $post_type_object->cap->$check_cap : $post_type_object->cap->read_private_posts;
     2068                                                        } else
     2069                                                                $read_private_cap = 'read_private_' . $post_type_cap . 's';
     2070                                                       
     2071                                                        if ( ! empty($q['perm'] ) && 'readable' == $q['perm'] && ! current_user_can( $read_private_cap ) )
     2072                                                                $p_status_owner[] = "$wpdb->posts.post_status = '$status'";
     2073                                                        else
     2074                                                                $p_status[] = "$wpdb->posts.post_status = '$status'";
     2075                                                } else
    20642076                                                        $r_status[] = "$wpdb->posts.post_status = '$status'";
    20652077                                        }
    20662078                                }
    20672079                        }
    20682080
    20692081                        if ( empty($q['perm'] ) || 'readable' != $q['perm'] ) {
    2070                                 $r_status = array_merge($r_status, $p_status);
     2082                                $r_status = array_merge($r_status, $p_status, $p_status_owner);
    20712083                                unset($p_status);
     2084                                unset($p_status_owner);
    20722085                        }
    20732086
    20742087                        if ( !empty($e_status) ) {
     
    20802093                                else
    20812094                                        $statuswheres[] = "(" . join( ' OR ', $r_status ) . ")";
    20822095                        }
    2083                         if ( !empty($p_status) ) {
    2084                                 if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) )
    2085                                         $statuswheres[] = "($wpdb->posts.post_author = $user_ID " .  "AND (" . join( ' OR ', $p_status ) . "))";
    2086                                 else
    2087                                         $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
     2096                        if ( ! empty( $p_status_owner ) ) {
     2097                                $statuswheres[] = "($wpdb->posts.post_author = $user_ID " .  "AND (" . join( ' OR ', $p_status_owner ) . "))";
    20882098                        }
     2099                        if ( ! empty( $p_status ) ) {                   
     2100                                $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
     2101                        }
    20892102                        if ( $post_status_join ) {
    20902103                                $join .= " LEFT JOIN $wpdb->posts AS p2 ON ($wpdb->posts.post_parent = p2.ID) ";
    20912104                                foreach ( $statuswheres as $index => $statuswhere )
    20922105                                        $statuswheres[$index] = "($statuswhere OR ($wpdb->posts.post_status = 'inherit' AND " . str_replace($wpdb->posts, 'p2', $statuswhere) . "))";
    20932106                        }
    20942107                        foreach ( $statuswheres as $statuswhere )
    2095                                 $where .= " AND $statuswhere";
     2108                                $where .= " AND $statuswhere"; 
     2109
    20962110                } elseif ( !$this->is_singular ) {
    20972111                        $where .= " AND ($wpdb->posts.post_status = 'publish'";
    20982112
    20992113                        // Add public states.
    2100                         $public_states = get_post_stati( array('public' => true) );
     2114                        $_args = array_merge( array( 'public' => true ), $type_arg );
     2115                        $public_states = apply_filters_ref_array( 'posts_public_stati', array( get_post_stati( $_args ), &$this ) );
    21012116                        foreach ( (array) $public_states as $state ) {
    21022117                                if ( 'publish' == $state ) // Publish is hard-coded above.
    21032118                                        continue;
     
    21062121
    21072122                        if ( is_admin() ) {
    21082123                                // Add protected states that should show in the admin all list.
    2109                                 $admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true) );
     2124                                $_args = array_merge( array( 'protected' => true, 'show_in_admin_all_list' => true ), $type_arg );
     2125                                $admin_all_states = get_post_stati( $_args );
    21102126                                foreach ( (array) $admin_all_states as $state )
    21112127                                        $where .= " OR $wpdb->posts.post_status = '$state'";
    21122128                        }
    21132129
    21142130                        if ( is_user_logged_in() ) {
    21152131                                // Add private states that are limited to viewing by the author of a post or someone who has caps to read private states.
    2116                                 $private_states = get_post_stati( array('private' => true) );
    2117                                 foreach ( (array) $private_states as $state )
     2132                                $_args = array_merge( array( 'private' => true ), $type_arg );
     2133                                $private_states = apply_filters_ref_array( 'posts_private_stati', array( get_post_stati( $_args ), &$this ) );
     2134                                foreach ( (array) $private_states as $state ) {
     2135                                        if ( ! empty($post_type_object) ) {
     2136                                                $check_cap = "read_{$status}_posts";
     2137                                                $read_private_cap = ( ! empty( $post_type_object->cap->$check_cap ) ) ? $post_type_object->cap->$check_cap : $post_type_object->cap->read_private_posts;
     2138                                        } else
     2139                                                $read_private_cap = 'read_private_' . $post_type_cap . 's';
     2140
    21182141                                        $where .= current_user_can( $read_private_cap ) ? " OR $wpdb->posts.post_status = '$state'" : " OR $wpdb->posts.post_author = $user_ID AND $wpdb->posts.post_status = '$state'";
     2142                                }
    21192143                        }
    21202144
    21212145                        $where .= ')';
     
    21582182                                $cwhere = "WHERE comment_approved = '1' $where";
    21592183                                $cgroupby = "$wpdb->comments.comment_id";
    21602184                        } else { // Other non singular e.g. front
     2185                                $public_stati = apply_filters( 'comment_feed_stati', get_post_stati( array( 'public' => true ) ) );
     2186                                $public_csv = implode( "', '", $public_stati );
     2187
    21612188                                $cjoin = "JOIN $wpdb->posts ON ( $wpdb->comments.comment_post_ID = $wpdb->posts.ID )";
    2162                                 $cwhere = "WHERE post_status = 'publish' AND comment_approved = '1'";
     2189                                $cwhere = "WHERE post_status IN ( '$public_csv' ) AND comment_approved = '1'";
    21632190                                $cgroupby = '';
    21642191                        }
    21652192
     
    23372364                                        $stickies_where = "AND $wpdb->posts.post_type IN ('" . $post_types . "')";
    23382365                                }
    23392366
     2367                                $public_stati = apply_filters_ref_array( 'posts_sticky_stati', array( get_post_stati( array( 'public' => true ) ), &$this ) );
    23402368                                $stickies = $wpdb->get_results( "SELECT * FROM $wpdb->posts WHERE $wpdb->posts.ID IN ($stickies__in) $stickies_where" );
    23412369                                foreach ( $stickies as $sticky_post ) {
    23422370                                        // Ignore sticky posts the current user cannot read or are not published.
    2343                                         if ( 'publish' != $sticky_post->post_status )
     2371                                        if ( ! in_array( $sticky_post->post_status, $public_stati ) )
    23442372                                                continue;
     2373
    23452374                                        array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
    23462375                                        $sticky_offset++;
    23472376                                }
  • wp-includes/script-loader.php

     
    290290
    291291                $scripts->add( 'post', "/wp-admin/js/post$suffix.js", array('suggest', 'wp-lists', 'postbox'), '20100526' );
    292292                $scripts->add_data( 'post', 'group', 1 );
    293                 $scripts->localize( 'post', 'postL10n', array(
     293                $arr = array(
    294294                        'tagsUsed' =>  __('Tags used on this post:'),
    295295                        'add' => esc_attr(__('Add')),
    296296                        'addTag' => esc_attr(__('Add new tag')),
     
    305305                        'endcomm' => __('No more comments found.'),
    306306                        'publish' => __('Publish'),
    307307                        'schedule' => __('Schedule'),
     308                        'update' => __('Update'),
    308309                        'updatePost' => __('Update Post'),
    309310                        'updatePage' => __('Update Page'),
    310311                        'savePending' => __('Save as Pending'),
     
    316317                        'privatelyPublished' => __('Privately Published'),
    317318                        'published' => __('Published'),
    318319                        'l10n_print_after' => 'try{convertEntities(postL10n);}catch(e){};'
    319                 ) );
     320                );
     321               
     322                $custom = array();
     323                foreach( get_post_stati( array( 'public' => true, 'private' => true ), 'object', 'or' ) as $_status => $_status_obj ) {
     324                        if ( 'publish' == $_status )
     325                                continue;
    320326
     327                        $custom[ $_status ] = $_status_obj->labels->visibility;
     328
     329                        if ( $_status_obj->public )
     330                                $custom[ $_status . 'Sticky' ] = sprintf( __('%s, Sticky'), $_status_obj->label );
     331                }
     332
     333                $arr = array_merge( $custom, $arr );  // note: 'publish' has existing value of 'Publish', cannot be used to reference status name
     334
     335                $scripts->localize( 'post', 'postL10n', $arr );
     336
    321337                $scripts->add( 'link', "/wp-admin/js/link$suffix.js", array('wp-lists', 'postbox'), '20090526' );
    322338                $scripts->add_data( 'link', 'group', 1 );
    323339
  • wp-includes/taxonomy.php

     
    109109
    110110        $field = ('names' == $output) ? 'name' : false;
    111111
     112        if ( isset( $args['object_type'] ) )
     113                $args['object_type'] = (array) $args['object_type'];
     114
    112115        return wp_filter_object_list($wp_taxonomies, $args, $operator, $field);
    113116}
    114117
     
    25162519        // Get the object and term ids and stick them in a lookup table
    25172520        $tax_obj = get_taxonomy($taxonomy);
    25182521        $object_types = esc_sql($tax_obj->object_type);
    2519         $results = $wpdb->get_results("SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (" . implode(',', array_keys($term_ids)) . ") AND post_type IN ('" . implode("', '", $object_types) . "') AND post_status = 'publish'");
     2522       
     2523        $public_stati = apply_filters( 'term_count_stati', get_post_stati( array( 'public' => true, 'object_type' => $tax_obj->object_type ) ) );
     2524        $public_csv = implode( "', '", $public_stati );
     2525
     2526        $results = $wpdb->get_results("SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (" . implode(',', array_keys($term_ids)) . ") AND post_type IN ('" . implode("', '", $object_types) . "') AND post_status IN ('$public_csv')");
    25202527        foreach ( $results as $row ) {
    25212528                $id = $term_ids[$row->term_taxonomy_id];
    25222529                $term_items[$id][$row->object_id] = isset($term_items[$id][$row->object_id]) ? ++$term_items[$id][$row->object_id] : 1;
     
    25652572        $object_types = is_array($taxonomy->object_type) ? $taxonomy->object_type : array($taxonomy->object_type);
    25662573        $object_types = esc_sql($object_types);
    25672574
     2575        $public_stati = apply_filters( 'term_count_stati', get_post_stati( array( 'public' => true, 'object_type' => $taxonomy->object_type ) ) );
     2576        $public_csv = implode( "', '", $public_stati );
     2577
    25682578        foreach ( (array) $terms as $term ) {
    2569                 $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type IN ('" . implode("', '", $object_types) . "') AND term_taxonomy_id = %d", $term ) );
     2579                $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status IN ('$public_csv') AND post_type IN ('" . implode("', '", $object_types) . "') AND term_taxonomy_id = %d", $term ) );
    25702580                do_action( 'edit_term_taxonomy', $term, $taxonomy );
    25712581                $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
    25722582                do_action( 'edited_term_taxonomy', $term, $taxonomy );