Make WordPress Core

Ticket #12706: 12706-1.diff

File 12706-1.diff, 81.0 KB (added by benbalter, 12 years ago)

Updated patch with bugfixes, refinements, and lastest trunk

  • wp-admin/edit-form-advanced.php

    diff --git wp-admin/edit-form-advanced.php wp-admin/edit-form-advanced.php
    index c22c68a..47a652d 100644
    $messages['post'] = array( 
    4545                // translators: Publish box date format, see http://php.net/date
    4646                date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
    4747        10 => sprintf( __('Post draft updated. <a target="_blank" href="%s">Preview post</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
     48        11 => sprintf( __('Post moderated. <a target="_blank" href="%s">Preview post</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    4849);
    4950$messages['page'] = array(
    5051         0 => '', // Unused. Messages start at index 1.
    $messages['page'] = array( 
    5859         8 => sprintf( __('Page submitted. <a target="_blank" href="%s">Preview page</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    5960         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) ) ),
    6061        10 => sprintf( __('Page draft updated. <a target="_blank" href="%s">Preview page</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
     62        11 => sprintf( __('Page moderated. <a target="_blank" href="%s">Preview page</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    6163);
    6264
    6365$messages = apply_filters( 'post_updated_messages', $messages );
    do_action('dbx_post_advanced'); 
    140142if ( post_type_supports($post_type, 'comments') )
    141143        add_meta_box('commentstatusdiv', __('Discussion'), 'post_comment_status_meta_box', null, 'normal', 'core');
    142144
    143 if ( ('publish' == $post->post_status || 'private' == $post->post_status) && post_type_supports($post_type, 'comments') )
     145if ( ! $post_status_object = get_post_status_object( $post->post_status ) )
     146        $post_status_object = get_post_status_object( 'draft' );
     147
     148if ( ( $post_status_object->public || $post_status_object->private ) && post_type_supports($post_type, 'comments') )
    144149        add_meta_box('commentsdiv', __('Comments'), 'post_comment_meta_box', null, 'normal', 'core');
    145150
    146 if ( !( 'pending' == $post->post_status && !current_user_can( $post_type_object->cap->publish_posts ) ) )
     151if ( ! ( $post_status_object->moderation && ! current_user_can( $post_type_object->cap->publish_posts ) ) )
    147152        add_meta_box('slugdiv', __('Slug'), 'post_slug_meta_box', null, 'normal', 'core');
    148153
    149154if ( post_type_supports($post_type, 'author') ) {
    $shortlink = wp_get_shortlink($post->ID, 'post'); 
    292297if ( !empty($shortlink) )
    293298    $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>';
    294299
    295 if ( $post_type_object->public && ! ( 'pending' == $post->post_status && !current_user_can( $post_type_object->cap->publish_posts ) ) ) { ?>
     300if ( $post_type_object->public && ! ( $post_status_object->moderation && ! current_user_can( $post_type_object->cap->publish_posts ) ) ) { ?>
    296301        <div id="edit-slug-box">
    297302        <?php
    298303                if ( ! empty($post->ID) && ! empty($sample_permalink_html) && 'auto-draft' != $post->post_status )
    if ( post_type_supports( $post_type, 'comments' ) ) 
    383388try{document.post.title.focus();}catch(e){}
    384389</script>
    385390<?php endif; ?>
     391
     392
     393<?php
     394add_action( 'admin_print_footer_scripts', create_function('', "_edit_form_advanced_scripts('$post_type');") );
     395
     396function _edit_form_advanced_scripts( $post_type ) {
     397?>
     398       
     399<script type="text/javascript">
     400//<![CDATA[
     401jQuery(document).ready( function($) {
     402        function updateStatusCaptions() {
     403                postStatus = $('#post_status');
     404
     405                $('#post-status-display').html($('option:selected', postStatus).text());
     406
     407                switch( $('option:selected', postStatus).val() ) {
     408
     409<?php foreach( get_post_stati( array( 'public' => true, 'private' => true ), 'object', 'or' ) as $_status => $_status_obj ): ?>
     410                        case '<?php echo $_status ?>':
     411                                $('#save-post').hide();
     412                                break;
     413<?php endforeach; ?>
     414
     415<?php foreach( get_post_stati( array( 'moderation' => true, 'internal' => false, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ): ?>
     416                        case '<?php echo $_status ?>':
     417                                $('#save-post').show().val( '<?php echo $_status_obj->labels->save_as ?>' );
     418                                break;
     419<?php endforeach; ?>
     420
     421                        default :
     422                                <?php $draft_status_obj = get_post_status_object( 'draft' ); ?>                 
     423                                $('#save-post').show().val( '<?php echo $draft_status_obj->labels->save_as ?>' );
     424                }
     425        }
     426
     427        $('input:radio', '#post-visibility-select').change(function() {
     428                switch ( $('input:radio:checked', '#post-visibility-select').val() ) {
     429                        case 'public':
     430                                $('#sticky-span').show();
     431                                break;
     432
     433<?php foreach( get_post_stati( array( 'public' => true, 'object_type' => $post_type ) ) as $_status ) : ?>
     434                        case '<?php echo $_status ?>':
     435                                $('#sticky-span').show();
     436                                break;
     437<?php endforeach; ?>
     438
     439                        default :
     440                                $('#sticky').attr('checked', false);
     441                                $('#sticky-span').hide();
     442                }
     443        });
     444       
     445        function updateVisibilityCaptions() {
     446                var postStatus = $('#post_status'), optPublish = $('option[value=publish]', postStatus);
     447
     448                switch( $('input:radio:checked', '#post-visibility-select').val() ) {
     449
     450<?php foreach( get_post_stati( array( 'internal' => false, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ) :
     451                if ( ( 'publish' == $_status ) || ( ! $_status_obj->private && ! $_status_obj->public ) )
     452                        continue;
     453?>
     454                        case '<?php echo $_status ?>':
     455                                $('#publish').val( postL10n.update );
     456
     457                                if ( optPublish.length == 0 ) {
     458                                        postStatus.append('<option value="publish">' + '<?php echo $_status_obj->labels->caption ?>' + '</option>');
     459                                } else {
     460                                        optPublish.html( '<?php echo $_status_obj->labels->caption ?>' );
     461                                }
     462
     463                                $('option[value=publish]', postStatus).attr('selected', true);
     464                                $('.edit-post-status', '#misc-publishing-actions').hide();
     465
     466                                break;
     467<?php endforeach; ?>
     468
     469                        default:
     470                                if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) {
     471                                        if ( optPublish.length ) {
     472                                                optPublish.remove();
     473                                                postStatus.val($('#hidden_post_status').val());
     474                                        }
     475                                } else {
     476                                        optPublish.html( postL10n.published );
     477                                }
     478                                if ( postStatus.is(':hidden') )
     479                                        $('.edit-post-status', '#misc-publishing-actions').show();
     480                }
     481
     482                return true;
     483        }
     484       
     485        $('.save-post-status', '#post-status-select').click(function() {
     486                updateStatusCaptions();
     487                return false;
     488        });
     489       
     490        $('.cancel-post-visibility', '#post-visibility-select').click(function () {
     491                updateVisibilityCaptions();
     492                return false;
     493        });
     494
     495        $('.save-post-visibility', '#post-visibility-select').click(function () { // crazyhorse - multiple ok cancels
     496                updateVisibilityCaptions();
     497                updateStatusCaptions();
     498                return false;
     499        });
     500});
     501//]]>
     502</script>
     503
     504<?php
     505} // end function edit_form_advanced_scripts
     506?>
     507 No newline at end of file
  • wp-admin/includes/ajax-actions.php

    diff --git wp-admin/includes/ajax-actions.php wp-admin/includes/ajax-actions.php
    index 5ced901..4fc7541 100644
    function wp_ajax_replyto_comment( $action ) { 
    730730                wp_die( -1 );
    731731
    732732        $status = $wpdb->get_var( $wpdb->prepare("SELECT post_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) );
     733    $post_status_obj = get_post_status_object($status);
    733734
    734         if ( empty($status) )
     735        if ( empty($post_status_obj) )
    735736                wp_die( 1 );
    736         elseif ( in_array($status, array('draft', 'pending', 'trash') ) )
     737        elseif ( ! $post_status_obj->public && ! $post_status_obj->private )
    737738                wp_die( __('ERROR: you are replying to a comment on a draft post.') );
    738739
    739740        $user = wp_get_current_user();
    function wp_ajax_inline_save() { 
    13511352        if ( isset($data['post_parent']) )
    13521353                $data['parent_id'] = $data['post_parent'];
    13531354
     1355        $post_type_object = get_post_type_object( $post['post_type'] );
     1356
    13541357        // status
    1355         if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
    1356                 $data['post_status'] = 'private';
    1357         else
     1358        foreach( get_post_stati( array( 'internal' => false, 'object_type' => $post['post_type'] ), 'object' ) as $_status => $_status_obj ) {
     1359                if ( ( 'publish' == $_status ) || ( ! $_status_obj->private && ! $_status_obj->public ) ) // private and custom public stati only here
     1360                        continue;
     1361
     1362                if ( isset($data["keep_{$_status}"]) ) {
     1363                        $set_status_cap = "set_{$_status}_posts";
     1364                        $check_cap = ( ! empty( $post_type_object->cap->$set_status_cap ) ) ? $post_type_object->cap->$set_status_cap : $post_type_object->cap->publish_posts;
     1365
     1366                        if ( current_user_can( $check_cap ) ) {
     1367                                $data['post_status'] = $_status;
     1368                                $keeping_private = true;
     1369                                break;
     1370                        }       
     1371                }
     1372        }
     1373
     1374        if ( empty($keeping_private) ) // private or custom public status selected and granted
    13581375                $data['post_status'] = $data['_status'];
    13591376
    13601377        if ( empty($data['comment_status']) )
    function wp_ajax_find_posts() { 
    14421459        if ( count($search_terms) > 1 && $search_terms[0] != $s )
    14431460                $search .= " OR ($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%')";
    14441461
    1445         $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" );
     1462        $public_stati = apply_filters( 'find_posts_stati', get_post_stati( array( 'public' => true ) ) );
     1463        $public_csv = implode( "', '", $public_stati );
     1464         
     1465        $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" );
    14461466
    14471467        if ( ! $posts ) {
    14481468                $posttype = get_post_type_object($what);
    14491469                wp_die( $posttype->labels->not_found );
    14501470        }
     1471       
     1472        $stat = array();
    14511473
    14521474        $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>';
    14531475        foreach ( $posts as $post ) {
    14541476
    1455                 switch ( $post->post_status ) {
    1456                         case 'publish' :
    1457                         case 'private' :
    1458                                 $stat = __('Published');
    1459                                 break;
    1460                         case 'future' :
    1461                                 $stat = __('Scheduled');
    1462                                 break;
    1463                         case 'pending' :
    1464                                 $stat = __('Pending Review');
    1465                                 break;
    1466                         case 'draft' :
    1467                                 $stat = __('Draft');
    1468                                 break;
     1477                if ( ! isset( $stat[$post->post_status] ) ) {
     1478                        $_status_obj = get_post_status_object( $post->post_status );
     1479                       
     1480                        if ( ! $_status_obj )
     1481                                $_status_obj = get_post_status_object( 'draft' );
     1482                        elseif ( ( $_status_obj->public || $_status_obj->private ) &&  ( 'publish' != $post->post_status ) )
     1483                                $_status_obj = get_post_status_object( 'publish' );
     1484
     1485                        $stat[$post->post_status] = $_status_obj->labels->caption;
    14691486                }
    14701487
    14711488                if ( '0000-00-00 00:00:00' == $post->post_date ) {
    function wp_ajax_find_posts() { 
    14761493                }
    14771494
    14781495                $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>';
    1479                 $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";
     1496                $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";
    14801497        }
    14811498        $html .= '</tbody></table>';
    14821499
  • wp-admin/includes/meta-boxes.php

    diff --git wp-admin/includes/meta-boxes.php wp-admin/includes/meta-boxes.php
    index 7dc4552..c8ec50d 100644
     
    1010 * @param object $post
    1111 */
    1212function post_submit_meta_box($post) {
    13         global $action;
    14 
     13        global $action; 
     14               
    1515        $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);
     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' );
     24
     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
    function post_submit_meta_box($post) { 
    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
     43//if ( 'publish' != $post_status && 'future' != $post_status && 'pending' != $post_status )  {
     44if ( ! $post_status_obj->public && ! $post_status_obj->private && ! $post_status_obj->moderation && ( 'future' != $post_status ) ) { 
     45// TODO: confirm we don't need a hidden save button when current status is private
     46        $draft_status_obj = get_post_status_object( 'draft' );
     47?>
     48<input type="submit" name="save" id="save-post" value="<?php echo $draft_status_obj->labels->save_as ?>" tabindex="4" class="button button-highlighted" />
     49<?php
     50} elseif ( $post_status_obj->moderation && $can_publish ) {                     
     51?>
     52<input type="submit" name="save" id="save-post" value="<?php echo $post_status_obj->labels->save_as ?>" tabindex="4" class="button button-highlighted" />
    3453<?php } ?>
    3554<img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-loading" id="draft-ajax-loading" alt="" />
    3655</div>
    37 <?php if ( $post_type_object->public ) : ?>
     56<?php if ( $post_type_obj->public ) : ?>
    3857<div id="preview-action">
    3958<?php
    40 if ( 'publish' == $post->post_status ) {
     59if ( $post_status_obj->public ) {
    4160        $preview_link = esc_url( get_permalink( $post->ID ) );
    4261        $preview_button = __( 'Preview Changes' );
    4362} else {
    if ( 'publish' == $post->post_status ) { 
    5978
    6079<div class="misc-pub-section"><label for="post_status"><?php _e('Status:') ?></label>
    6180<span id="post-status-display">
    62 <?php
    63 switch ( $post->post_status ) {
    64         case 'private':
    65                 _e('Privately Published');
    66                 break;
    67         case 'publish':
    68                 _e('Published');
    69                 break;
    70         case 'future':
    71                 _e('Scheduled');
    72                 break;
    73         case 'pending':
    74                 _e('Pending Review');
    75                 break;
    76         case 'draft':
    77         case 'auto-draft':
    78                 _e('Draft');
    79                 break;
    80 }
    81 ?>
     81<?php echo $post_status_obj->labels->caption; ?>
    8282</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>
     83<?php
     84$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
     85
     86if ( $post_status_obj->public || $post_status_obj->private || $can_publish || $select_moderation ) { ?>
     87<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>
    8588
    8689<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); ?>" />
     90<input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr( ('auto-draft' == $post_status ) ? 'draft' : $post_status); ?>" />
    8891<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>
    95 <?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>
     92
     93<?php if ( $post_status_obj->public || $post_status_obj->private || ( 'future' == $post_status ) ) : ?>
     94<option<?php selected( $post_status, $post_status ); ?> value='publish'><?php echo $post_status_obj->labels->caption ?></option>
    10195<?php endif; ?>
     96
     97<?php
     98foreach( $moderation_stati as $_status => $_status_obj ) : ?>
     99<option<?php selected( $post_status, $_status ); ?> value='<?php echo $_status ?>'><?php echo $_status_obj->labels->caption ?></option>
     100<?php endforeach ?>
     101
     102<?php
     103$draft_status_obj = get_post_status_object( 'draft' );
     104$compare_status = ( 'auto-draft' == $post_status ) ? 'auto-draft' : 'draft';
     105?>
     106<option<?php selected( $post_status, $compare_status ); ?> value='draft'><?php echo $draft_status_obj->label ?></option>
     107
    102108</select>
    103109 <a href="#post_status" class="save-post-status hide-if-no-js button"><?php _e('OK'); ?></a>
    104110 <a href="#post_status" class="cancel-post-status hide-if-no-js"><?php _e('Cancel'); ?></a>
    switch ( $post->post_status ) { 
    110116<div class="misc-pub-section" id="visibility">
    111117<?php _e('Visibility:'); ?> <span id="post-visibility-display"><?php
    112118
    113 if ( 'private' == $post->post_status ) {
     119if ( 'future' == $post_status ) {       // indicate eventual visibility of scheduled post
     120        if ( ! $vis_status = get_post_meta( $post->ID, '_scheduled_status', true ) )
     121                $vis_status = 'publish';       
     122
     123        $vis_status_obj = get_post_status_object( $vis_status );
     124} else {
     125        $vis_status = $post_status;
     126        $vis_status_obj = $post_status_obj;
     127}
     128       
     129if ( 'publish' == $vis_status ) {
     130        $post->post_password = '';
     131        $visibility = 'public';
     132
     133        if ( post_type_supports( $post->post_type, 'sticky' ) && is_sticky( $post->ID ) ) {
     134                $visibility_trans = __('Public, Sticky');
     135        } else {
     136            $visibility_trans = __('Public');
     137        }
     138} elseif ( $vis_status_obj->public  ) {
     139        $post->post_password = '';
     140        $visibility = $vis_status;
     141
     142        if ( post_type_supports( $post->post_type, 'sticky' ) && is_sticky( $post->ID ) ) {
     143                $visibility_trans = sprintf( __('%s, Sticky'), $vis_status_obj->label );
     144    } else {
     145            $visibility_trans = $vis_status_obj->labels->visibility;
     146        }
     147} elseif ( $vis_status_obj->private ) {
    114148        $post->post_password = '';
    115         $visibility = 'private';
    116         $visibility_trans = __('Private');
     149        $visibility_trans = $vis_status_obj->labels->visibility;
    117150} elseif ( !empty( $post->post_password ) ) {
    118151        $visibility = 'password';
    119152        $visibility_trans = __('Password protected');
    echo esc_html( $visibility_trans ); ?></span> 
    135168<input type="checkbox" style="display:none" name="hidden_post_sticky" id="hidden-post-sticky" value="sticky" <?php checked(is_sticky($post->ID)); ?> />
    136169<?php endif; ?>
    137170<input type="hidden" name="hidden_post_visibility" id="hidden-post-visibility" value="<?php echo esc_attr( $visibility ); ?>" />
     171
    138172<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 />
     173
     174<?php
     175foreach( get_post_stati( array( 'public' => true, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ) :
     176        if ( 'publish' == $_status )
     177                continue;
     178
     179        $post_cap = "set_{$_status}_posts";
     180        if ( empty( $post_type_obj->cap->$post_cap ) || current_user_can( $post_type_obj->cap->$post_cap ) ) {
     181?>
     182<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 />     
     183<?php
     184        } // end if this user can set status
     185endforeach ?>
     186
    139187<?php if ( $post_type == 'post' && current_user_can( 'edit_others_posts' ) ) : ?>
    140188<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 post to the front page' ); ?></label><br /></span>
    141189<?php endif; ?>
     190
    142191<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 />
    143192<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>
    144 <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 />
    145193
     194<?php
     195foreach( get_post_stati( array( 'private' => true, 'object_type' => $post_type ), 'object' ) as $_status => $_status_obj ) :
     196        $post_cap = "set_{$_status}_posts";
     197        if ( empty( $post_type_obj->cap->$post_cap ) || current_user_can( $post_type_obj->cap->$post_cap ) ) {
     198?>
     199<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 />   
     200<?php
     201        } // end if this user can set status
     202endforeach ?>
    146203<p>
    147204 <a href="#visibility" class="save-post-visibility hide-if-no-js button"><?php _e('OK'); ?></a>
    148205 <a href="#visibility" class="cancel-post-visibility hide-if-no-js"><?php _e('Cancel'); ?></a>
    echo esc_html( $visibility_trans ); ?></span> 
    155212<?php
    156213// translators: Publish box date format, see http://php.net/date
    157214$datef = __( 'M j, Y @ G:i' );
     215
     216$published_stati = get_post_stati( array( 'public' => true, 'private' => true ), 'names', 'or' );
     217
    158218if ( 0 != $post->ID ) {
    159         if ( 'future' == $post->post_status ) { // scheduled for publishing at a future date
     219        if ( 'future' == $post_status ) { // scheduled for publishing at a future date
    160220                $stamp = __('Scheduled for: <b>%1$s</b>');
    161         } else if ( 'publish' == $post->post_status || 'private' == $post->post_status ) { // already published
     221        } else if ( in_array( $post_status, $published_stati ) ) { // already published
    162222                $stamp = __('Published on: <b>%1$s</b>');
    163223        } else if ( '0000-00-00 00:00:00' == $post->post_date_gmt ) { // draft, 1 or more saves, no date specified
    164224                $stamp = __('Publish <b>immediately</b>');
    if ( current_user_can( "delete_post", $post->ID ) ) { 
    204264<div id="publishing-action">
    205265<img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-loading" id="ajax-loading" alt="" />
    206266<?php
    207 if ( !in_array( $post->post_status, array('publish', 'future', 'private') ) || 0 == $post->ID ) {
     267if ( ( ! $post_status_obj->public && ! $post_status_obj->private && ( 'future' != $post_status ) ) ) {
    208268        if ( $can_publish ) :
    209                 if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) : ?>
    210                 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Schedule') ?>" />
    211                 <?php submit_button( __( 'Schedule' ), 'primary', 'publish', false, array( 'tabindex' => '5', 'accesskey' => 'p' ) ); ?>
    212 <?php   else : ?>
    213                 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish') ?>" />
    214                 <?php submit_button( __( 'Publish' ), 'primary', 'publish', false, array( 'tabindex' => '5', 'accesskey' => 'p' ) ); ?>
     269
     270                if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) :
     271                $future_status_obj = get_post_status_object( 'future' );
     272                ?>
     273                <input name="original_publish" type="hidden" id="original_publish" value="<?php echo $future_status_obj->labels->publish ?>" />
     274                <?php submit_button( $future_status_obj->labels->publish, 'primary', 'publish', false, array( 'tabindex' => '5', 'accesskey' => 'p' ) ); ?>
     275<?php   else :
     276                $publish_status_obj = get_post_status_object( 'publish' );
     277                ?>
     278                <input name="original_publish" type="hidden" id="original_publish" value="<?php echo $publish_status_obj->labels->publish ?>" />
     279                <?php submit_button( $publish_status_obj->labels->publish, 'primary', 'publish', false, array( 'tabindex' => '5', 'accesskey' => 'p' ) ); ?>
    215280<?php   endif;
    216281        else : ?>
    217                 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review') ?>" />
    218                 <?php submit_button( __( 'Submit for Review' ), 'primary', 'publish', false, array( 'tabindex' => '5', 'accesskey' => 'p' ) ); ?>
     282                <?php
     283                $moderation_button_status = apply_filters( 'post_moderation_status', 'pending', $post->ID );
     284
     285                $status_obj = get_post_status_object( $moderation_button_status );
     286                $cap_name = "set_{$moderation_button_status}_posts";
     287
     288                if ( ! $status_obj || ( ! empty($post_type_obj->cap->$cap_name) && ! current_user_can($post_type_obj->cap->$cap_name) ) )
     289                        $status_obj = get_post_status_object( 'pending' );
     290                ?>
     291                <input name="original_publish" type="hidden" id="original_publish" value="<?php echo $status_obj->labels->publish ?>" />
     292                <?php submit_button( $status_obj->labels->publish, 'primary', 'publish', false, array( 'tabindex' => '5', 'accesskey' => 'p' ) ); ?>
    219293<?php
    220294        endif;
    221295} else { ?>
  • wp-admin/includes/nav-menu.php

    diff --git wp-admin/includes/nav-menu.php wp-admin/includes/nav-menu.php
    index 5fc73fc..1780b07 100644
    function wp_save_nav_menu_items( $menu_id = 0, $menu_data = array() ) { 
    10391039 */
    10401040function _wp_nav_menu_meta_box_object( $object = null ) {
    10411041        if ( isset( $object->name ) ) {
     1042                $public_stati = apply_filters( 'nav_menu_metabox_stati', get_post_stati( array( 'public' => true, 'object_type' => $object->name ) ), $object );
     1043                $public_csv = implode( ',', $public_stati );
    10421044
    10431045                if ( 'page' == $object->name ) {
    10441046                        $object->_default_query = array(
    10451047                                'orderby' => 'menu_order title',
    1046                                 'post_status' => 'publish',
     1048                                'post_status' => $public_csv,
    10471049                        );
    10481050
    1049                 // posts should show only published items
     1051                // posts should show only public items
    10501052                } elseif ( 'post' == $object->name ) {
    10511053                        $object->_default_query = array(
    1052                                 'post_status' => 'publish',
     1054                                'post_status' => $public_csv,
    10531055                        );
    10541056
    10551057                // cats should be in reverse chronological order
    function _wp_nav_menu_meta_box_object( $object = null ) { 
    10591061                                'order' => 'DESC',
    10601062                        );
    10611063
    1062                 // custom post types should show only published items
     1064                // custom post types should show only public items
    10631065                } else {
    10641066                        $object->_default_query = array(
    1065                                 'post_status' => 'publish',
     1067                                'post_status' => $public_csv,
    10661068                        );
    10671069                }
    10681070        }
  • wp-admin/includes/post.php

    diff --git wp-admin/includes/post.php wp-admin/includes/post.php
    index 3bfea57..3762889 100644
    function _wp_translate_postdata( $update = false, $post_data = null ) { 
    7171        // What to do based on which button they pressed
    7272        if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
    7373                $post_data['post_status'] = 'draft';
    74         if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
     74        if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] ) // TODO: is this set anywhere?
    7575                $post_data['post_status'] = 'private';
    7676        if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( !isset($post_data['post_status']) || $post_data['post_status'] != 'private' ) )
    7777                $post_data['post_status'] = 'publish';
    function _wp_translate_postdata( $update = false, $post_data = null ) { 
    8888
    8989        // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
    9090        // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
    91         if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $ptype->cap->publish_posts )) )
    92                 if ( $previous_status != 'publish' || !current_user_can( 'edit_post', $post_id ) )
    93                         $post_data['post_status'] = 'pending';
     91        if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $ptype->cap->publish_posts )) ) {
     92                if ( $previous_status != 'publish' || !current_user_can( 'edit_post', $post_id ) ) {
     93                        $moderation_status = apply_filters( 'post_moderation_status', 'pending', $post->ID );
     94
     95                        $_status_obj = get_post_status_object( $moderation_status );
     96                        $cap_name = "set_{$moderation_status}_posts";
     97
     98                        if ( empty($_status_obj) || ! $_status_obj->moderation || ( ! empty($ptype->cap->$cap_name) && ! current_user_can($ptype->cap->$cap_name) ) )
     99                                $moderation_status = 'pending';
     100
     101                        $post_data['post_status'] = $moderation_status;
     102                }
     103        }
    94104
    95105        if ( ! isset($post_data['post_status']) )
    96106                $post_data['post_status'] = $previous_status;
    function edit_post( $post_data = null ) { 
    182192                        case 'password' :
    183193                                unset( $post_data['sticky'] );
    184194                                break;
    185                         case 'private' :
    186                                 $post_data['post_status'] = 'private';
    187                                 $post_data['post_password'] = '';
    188                                 unset( $post_data['sticky'] );
    189                                 break;
     195                        default:
     196                                $status_obj = get_post_status_object( $post_data['visibility'] );
     197       
     198                                if ( ! empty( $status_obj->private ) || ! empty( $status_obj->public ) ) {
     199                                        $post_data['post_status'] = $status_obj->name;
     200                                        $post_data['post_password'] = '';
     201                                }
     202
     203                                if ( ! empty( $status_obj->private ) ) {
     204                                        unset( $post_data['sticky'] );
     205                                }
    190206                }
    191207        }
    192208
    function wp_write_post() { 
    564580                        case 'password' :
    565581                                unset( $_POST['sticky'] );
    566582                                break;
    567                         case 'private' :
    568                                 $_POST['post_status'] = 'private';
    569                                 $_POST['post_password'] = '';
    570                                 unset( $_POST['sticky'] );
    571                                 break;
     583                        default:
     584                                $status_obj = get_post_status_object( $_POST['visibility'] );   
     585                                if ( ! empty( $status_obj->private ) ) {
     586                                        $_POST['post_status'] = $status_obj->name;
     587                                        $_POST['post_password'] = '';
     588                                        unset( $_POST['sticky'] );
     589                                }
    572590                }
    573591        }
    574592
    function wp_edit_posts_query( $q = false ) { 
    849867        else
    850868                $post_type = 'post';
    851869
    852         $avail_post_stati = get_available_post_statuses($post_type);
     870        $avail_post_stati = get_available_post_statuses( $post_type );
    853871
    854872        if ( isset($q['post_status']) && in_array( $q['post_status'], $post_stati ) ) {
    855873                $post_status = $q['post_status'];
    function wp_edit_posts_query( $q = false ) { 
    858876
    859877        if ( isset($q['orderby']) )
    860878                $orderby = $q['orderby'];
    861         elseif ( isset($q['post_status']) && in_array($q['post_status'], array('pending', 'draft')) )
     879        elseif ( isset($q['post_status']) && ( in_array($q['post_status'], array('pending', 'draft')) || ! empty( $GLOBALS['wp_post_statuses'][$q['post_status']]->moderation ) ) )
    862880                $orderby = 'modified';
    863881
    864882        if ( isset($q['order']) )
    function get_sample_permalink($id, $title = null, $name = null) { 
    10201038        $original_date = $post->post_date;
    10211039        $original_name = $post->post_name;
    10221040
     1041        $post_status_obj = get_post_status_object( $post->post_status );
     1042       
    10231043        // Hack: get_permalink would return ugly permalink for
    10241044        // drafts, so we will fake, that our post is published
    1025         if ( in_array($post->post_status, array('draft', 'pending')) ) {
     1045        if ( in_array($post->post_status, array('draft', 'pending')) || ! empty($post_status_obj->moderation) ) {
    10261046                $post->post_status = 'publish';
    10271047                $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
    10281048        }
    function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) { 
    10801100
    10811101        list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
    10821102
    1083         if ( 'publish' == $post->post_status ) {
     1103        $public_stati = get_post_stati( array( 'public' => true ) );
     1104        if ( in_array( $post->post_status, $public_stati ) ) {
    10841105                $ptype = get_post_type_object($post->post_type);
    10851106                $view_post = $ptype->labels->view_item;
    10861107                $title = __('Click to edit this part of the permalink');
  • wp-admin/includes/template.php

    diff --git wp-admin/includes/template.php wp-admin/includes/template.php
    index 3834874..c7fc1bf 100644
    function get_inline_data($post) { 
    256256        <div class="post_author">' . $post->post_author . '</div>
    257257        <div class="comment_status">' . esc_html( $post->comment_status ) . '</div>
    258258        <div class="ping_status">' . esc_html( $post->ping_status ) . '</div>
    259         <div class="_status">' . esc_html( $post->post_status ) . '</div>
     259        <div class="_status">' . esc_html( $post->post_status ) . '</div>';
     260
     261        if ( 'future' == $post->post_status ) {
     262                if ( ! $scheduled_status = get_post_meta( $post->ID, '_scheduled_status', true ) )
     263                        $scheduled_status = 'publish'; 
     264        echo '
     265        <div class="scheduled_status">' . esc_html( $scheduled_status  ). '</div>';
     266        }
     267
     268        echo '
    260269        <div class="jj">' . mysql2date( 'd', $post->post_date, false ) . '</div>
    261270        <div class="mm">' . mysql2date( 'm', $post->post_date, false ) . '</div>
    262271        <div class="aa">' . mysql2date( 'Y', $post->post_date, false ) . '</div>
    function meta_form() { 
    577586function touch_time( $edit = 1, $for_post = 1, $tab_index = 0, $multi = 0 ) {
    578587        global $wp_locale, $post, $comment;
    579588
    580         if ( $for_post )
    581                 $edit = ! ( in_array($post->post_status, array('draft', 'pending') ) && (!$post->post_date_gmt || '0000-00-00 00:00:00' == $post->post_date_gmt ) );
    582 
     589        if ( $for_post ) {
     590                $post_status_obj = get_post_status_object($post->post_status);
     591                $edit = ( ( 'draft' != $post->post_status ) && empty($post_status_obj->moderation) ) || ( $post->post_date_gmt && '0000-00-00 00:00:00' != $post->post_date_gmt );
     592        }
     593                       
    583594        $tab_index_attribute = '';
    584595        if ( (int) $tab_index > 0 )
    585596                $tab_index_attribute = " tabindex=\"$tab_index\"";
    function _post_states($post) { 
    14691480        else
    14701481                $post_status = '';
    14711482
     1483        $post_status_obj = get_post_status_object($post->post_status);
     1484       
    14721485        if ( !empty($post->post_password) )
    14731486                $post_states['protected'] = __('Password protected');
    1474         if ( 'private' == $post->post_status && 'private' != $post_status )
    1475                 $post_states['private'] = __('Private');
    1476         if ( 'draft' == $post->post_status && 'draft' != $post_status )
    1477                 $post_states['draft'] = __('Draft');
    1478         if ( 'pending' == $post->post_status && 'pending' != $post_status )
    1479                 /* translators: post state */
    1480                 $post_states['pending'] = _x('Pending', 'post state');
    1481         if ( is_sticky($post->ID) )
    1482                 $post_states['sticky'] = __('Sticky');
     1487       
     1488        if ( $post_status_obj && ( 'publish' != $post->post_status ) ) {
     1489                if ( $post->post_status != $post_status ) {
     1490                        $post_states[] = $post_status_obj->label;
     1491
     1492                        if ( 'future' == $post->post_status ) {
     1493                                if ( $scheduled_status = get_post_meta( $post->ID, '_scheduled_status', true ) ) {
     1494                                        if ( 'publish' != $scheduled_status ) {
     1495                                                if ( $_scheduled_status_obj = get_post_status_object( $scheduled_status ) )
     1496                                                        $post_states[] = $_scheduled_status_obj->label;
     1497                                        }
     1498                                }
     1499                        }
     1500                }
     1501        }
    14831502
    14841503        $post_states = apply_filters( 'display_post_states', $post_states );
    14851504
  • wp-admin/js/inline-edit-post.dev.js

    diff --git wp-admin/js/inline-edit-post.dev.js wp-admin/js/inline-edit-post.dev.js
    index 4b0eb2e..69f8586 100644
    inlineEditPost = { 
    7878                        t.revert();
    7979                        $('select[name^="action"]').val('-1');
    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){
    inlineEditPost = { 
    129135                if ( typeof(id) == 'object' )
    130136                        id = t.getId(id);
    131137
    132                 fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order'];
     138                fields = ['post_title', 'post_name', 'post_author', '_status', 'scheduled_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order'];
     139
    133140                if ( t.type == 'page' )
    134141                        fields.push('post_parent', 'page_template');
    135142
    inlineEditPost = { 
    198205
    199206                // handle the post status
    200207                status = $('._status', rowData).text();
    201                 if ( 'future' != status )
     208
     209                if ( 'future' == status ) {
     210                        status = $('.scheduled_status', rowData).text();
     211                } else {
    202212                        $('select[name="_status"] option[value="future"]', editRow).remove();
     213                }
    203214
    204                 if ( 'private' == status ) {
    205                         $('input[name="keep_private"]', editRow).prop("checked", true);
    206                         $('input.inline-edit-password-input').val('').prop('disabled', true);
     215                if ( $('[name=keep_' + status + ']').length > 0) {
     216                        $('input[name="keep_' + status + '"]', editRow).prop("checked", "checked");
     217                        $('input.inline-edit-password-input').val('').prop('disabled', 'disabled');
    207218                }
    208219
    209220                // remove the current page and children from the parent dropdown
  • wp-admin/js/post.dev.js

    diff --git wp-admin/js/post.dev.js wp-admin/js/post.dev.js
    index 42cd217..ba12f63 100644
    jQuery(document).ready( function($) { 
    382382                }
    383383
    384384                function updateText() {
    385                         var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'),
    386                                 optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(),
     385                        var attemptedDate, originalDate, currentDate, publishOn,
     386                                postStatus = $('#post_status'), optPublish = $('option[value=publish]', postStatus), aa = $('#aa').val(),
    387387                                mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val();
    388388
    389389                        attemptedDate = new Date( aa, mm - 1, jj, hh, mn );
    jQuery(document).ready( function($) { 
    407407                                publishOn = postL10n.publishOnPast;
    408408                                $('#publish').val( postL10n.update );
    409409                        }
     410
    410411                        if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) { //hack
    411412                                $('#timestamp').html(stamp);
    412413                        } else {
    jQuery(document).ready( function($) { 
    421422                        }
    422423
    423424                        if ( $('input:radio:checked', '#post-visibility-select').val() == 'private' ) {
     425
    424426                                $('#publish').val( postL10n.update );
    425427                                if ( optPublish.length == 0 ) {
    426428                                        postStatus.append('<option value="publish">' + postL10n.privatelyPublished + '</option>');
    427429                                } else {
    428430                                        optPublish.html( postL10n.privatelyPublished );
    429431                                }
     432
    430433                                $('option[value="publish"]', postStatus).prop('selected', true);
     434
    431435                                $('.edit-post-status', '#misc-publishing-actions').hide();
    432436                        } else {
    433437                                if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) {
    jQuery(document).ready( function($) { 
    441445                                if ( postStatus.is(':hidden') )
    442446                                        $('.edit-post-status', '#misc-publishing-actions').show();
    443447                        }
    444                         $('#post-status-display').html($('option:selected', postStatus).text());
    445                         if ( $('option:selected', postStatus).val() == 'private' || $('option:selected', postStatus).val() == 'publish' ) {
    446                                 $('#save-post').hide();
    447                         } else {
    448                                 $('#save-post').show();
    449                                 if ( $('option:selected', postStatus).val() == 'pending' ) {
    450                                         $('#save-post').show().val( postL10n.savePending );
    451                                 } else {
    452                                         $('#save-post').show().val( postL10n.saveDraft );
    453                                 }
    454                         }
     448
    455449                        return true;
    456450                }
    457451
    jQuery(document).ready( function($) { 
    463457                        }
    464458                        return false;
    465459                });
    466 
     460               
    467461                $('.cancel-post-visibility', '#post-visibility-select').click(function () {
    468462                        $('#post-visibility-select').slideUp('fast');
    469463                        $('#visibility-radio-' + $('#hidden-post-visibility').val()).prop('checked', true);
    jQuery(document).ready( function($) { 
    471465                        $('#sticky').prop('checked', $('#hidden-post-sticky').prop('checked'));
    472466                        $('#post-visibility-display').html(visibility);
    473467                        $('.edit-visibility', '#visibility').show();
    474                         updateText();
    475468                        return false;
    476469                });
    477 
     470               
    478471                $('.save-post-visibility', '#post-visibility-select').click(function () { // crazyhorse - multiple ok cancels
    479472                        var pvSelect = $('#post-visibility-select');
    480473
    481474                        pvSelect.slideUp('fast');
    482475                        $('.edit-visibility', '#visibility').show();
    483                         updateText();
     476
    484477
    485478                        if ( $('input:radio:checked', pvSelect).val() != 'public' ) {
    486479                                $('#sticky').prop('checked', false);
    jQuery(document).ready( function($) { 
    491484                        } else {
    492485                                sticky = '';
    493486                        }
    494 
     487       
    495488                        $('#post-visibility-display').html(     postL10n[$('input:radio:checked', pvSelect).val() + sticky]     );
    496489                        return false;
    497490                });
    498 
     491               
    499492                $('input:radio', '#post-visibility-select').change(function() {
    500493                        updateVisibility();
    501494                });
  • wp-admin/post.php

    diff --git wp-admin/post.php wp-admin/post.php
    index 035a185..85f6924 100644
    function redirect_post($post_id = '') { 
    5151                                        $message = 9;
    5252                                        break;
    5353                                default:
    54                                         $message = 6;
     54                                        $status_obj = get_post_status_object( $status );
     55                                        if ( ! empty($status_obj->moderation) )
     56                                                $message = 11;
     57                                        else
     58                                                $message = 6;
    5559                        }
    5660                } else {
    5761                                $message = 'draft' == $status ? 10 : 1;
  • wp-comments-post.php

    diff --git wp-comments-post.php wp-comments-post.php
    index 194e00f..a71686b 100644
    if ( !comments_open($comment_post_ID) ) { 
    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

    diff --git wp-includes/default-widgets.php wp-includes/default-widgets.php
    index e4856da..85e4b2a 100644
    class WP_Widget_Recent_Posts extends WP_Widget { 
    562562                if ( empty( $instance['number'] ) || ! $number = absint( $instance['number'] ) )
    563563                        $number = 10;
    564564
     565                $public_stati = apply_filters( 'recent_posts_stati', get_post_stati( array( 'public' => true ) ) );
     566                $status_arg = implode( ',', $public_stati );
     567
    565568                $r = new WP_Query( apply_filters( 'widget_posts_args', array( 'posts_per_page' => $number, 'no_found_rows' => true, 'post_status' => 'publish', 'ignore_sticky_posts' => true ) ) );
    566569                if ($r->have_posts()) :
    567570?>
  • wp-includes/general-template.php

    diff --git wp-includes/general-template.php wp-includes/general-template.php
    index 1972696..297ec99 100644
    function wp_get_archives($args = '') { 
    915915        }
    916916
    917917        //filters
    918         $where = apply_filters( 'getarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
    919         $join = apply_filters( 'getarchives_join', '', $r );
     918        $public_stati = apply_filters( 'getarchives_stati', get_post_stati( array( 'public' => true ) ) );
     919        $public_csv = implode( "', '", $public_stati );
     920
     921        $where = apply_filters('getarchives_where', "WHERE post_type = 'post' AND post_status IN ('" . $public_csv . "')", $r );
     922        $join = apply_filters('getarchives_join', "", $r);
    920923
    921924        $output = '';
    922925
  • wp-includes/link-template.php

    diff --git wp-includes/link-template.php wp-includes/link-template.php
    index ae8a9f1..17c59dd 100644
    function get_permalink($id = 0, $leavename = false) { 
    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 = '';
    function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { 
    185185
    186186        $slug = $post->post_name;
    187187
    188         $draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
     188        $draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) ) || ! empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation );
    189189
    190190        $post_type = get_post_type_object($post->post_type);
    191191
    function _get_page_link( $id = false, $leavename = false, $sample = false ) { 
    275275
    276276        $link = $wp_rewrite->get_page_permastruct();
    277277
    278         if ( !empty($link) && ( ( isset($post->post_status) && !$draft_or_pending ) || $sample ) ) {
     278        if ( !empty($link) && ( ( isset($post->post_status) && !$draft_or_pending ) && empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation ) ) || $sample ) {
    279279                if ( ! $leavename ) {
    280280                        $link = str_replace('%pagename%', get_page_uri($id), $link);
    281281                }
  • wp-includes/load.php

    diff --git wp-includes/load.php wp-includes/load.php
    index 94e6339..9d51e86 100644
    function wp_get_active_and_valid_plugins() { 
    491491
    492492        $network_plugins = is_multisite() ? wp_get_active_network_plugins() : false;
    493493
    494         foreach ( $active_plugins as $plugin ) {
     494        foreach ( $active_plugins as $plugin ) { 
    495495                if ( ! validate_file( $plugin ) // $plugin must validate as file
    496496                        && '.php' == substr( $plugin, -4 ) // $plugin must end with '.php'
    497497                        && file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist
    function wp_get_active_and_valid_plugins() { 
    499499                        && ( ! $network_plugins || ! in_array( WP_PLUGIN_DIR . '/' . $plugin, $network_plugins ) )
    500500                        )
    501501                $plugins[] = WP_PLUGIN_DIR . '/' . $plugin;
    502         }
     502        } 
    503503        return $plugins;
    504504}
    505505
  • wp-includes/nav-menu.php

    diff --git wp-includes/nav-menu.php wp-includes/nav-menu.php
    index 361a8de..2cddd01 100644
    function wp_get_nav_menu_items( $menu, $args = array() ) { 
    482482        if ( empty( $items ) )
    483483                return $items;
    484484
     485        $public_stati = apply_filters( 'nav_menu_stati', get_post_stati( array( 'public' => true ) ), $menu );
     486        $public_csv = implode( ',', $public_stati );
     487
    485488        $defaults = array( 'order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item',
    486                 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true,
     489                'post_status' => $public_csv, 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true,
    487490                'update_post_term_cache' => false );
    488491        $args = wp_parse_args( $args, $defaults );
    489492        if ( count( $items ) > 1 )
  • wp-includes/post-template.php

    diff --git wp-includes/post-template.php wp-includes/post-template.php
    index 5a414ea..716790f 100644
    function get_the_title( $id = 0 ) { 
    107107        $id = isset($post->ID) ? $post->ID : (int) $id;
    108108
    109109        if ( !is_admin() ) {
    110                 if ( !empty($post->post_password) ) {
    111                         $protected_title_format = apply_filters('protected_title_format', __('Protected: %s'));
     110                if ( ! empty($post->post_password) ) {
     111                        $protected_title_format = apply_filters( 'protected_title_format', __( 'Protected: %s' ) );
    112112                        $title = sprintf($protected_title_format, $title);
    113                 } else if ( isset($post->post_status) && 'private' == $post->post_status ) {
    114                         $private_title_format = apply_filters('private_title_format', __('Private: %s'));
    115                         $title = sprintf($private_title_format, $title);
     113                } elseif ( isset($post->post_status) ) {
     114                        $post_status_obj = get_post_status_object( $post->post_status );
     115                        if ( $post_status_obj && $post_status_obj->private ) {
     116                                if ( 'private' == $post->post_status ) {
     117                                        $format_string = __( 'Private: %s' );  // preserve existing translation string
     118                                        $private_title_format = apply_filters( 'private_title_format', $format_string );
     119                                        $title = sprintf( $private_title_format, $title );
     120                                } else {
     121                                        $format_string = _x( '%1$s: %2$s', 'post status: title' );     
     122                                        $private_title_format = apply_filters( 'post_title_format', $format_string, $_status );
     123                                        $title = sprintf( $private_title_format, $post_status_obj->labels->name, $title );
     124                                }
     125                        }
    116126                }
    117127        }
    118128        return apply_filters( 'the_title', $title, $id );
    function _wp_link_page( $i ) { 
    697707        if ( 1 == $i ) {
    698708                $url = get_permalink();
    699709        } else {
    700                 if ( '' == get_option('permalink_structure') || in_array($post->post_status, array('draft', 'pending')) )
     710                if ( '' == get_option('permalink_structure') || in_array( $post->post_status, array('draft', 'auto-draft', 'pending') ) || ! empty( $GLOBALS['wp_post_statuses'][$post->post_status]->moderation ) )
    701711                        $url = add_query_arg( 'page', $i, get_permalink() );
    702712                elseif ( 'page' == get_option('show_on_front') && get_option('page_on_front') == $post->ID )
    703713                        $url = trailingslashit(get_permalink()) . user_trailingslashit("$wp_rewrite->pagination_base/" . $i, 'single_paged');
  • wp-includes/post.php

    diff --git wp-includes/post.php wp-includes/post.php
    index dee484e..392cbec 100644
    function create_initial_post_types() { 
    101101        ) );
    102102
    103103        register_post_status( 'publish', array(
    104                 'label'       => _x( 'Published', 'post' ),
     104                'labels'          => array(
     105                        'name'    => _x( 'Published', 'post' ),
     106                        'publish' => esc_attr__('Publish'),
     107                        'count' => _n_noop( 'Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>' ),
     108                ),
    105109                'public'      => true,
    106110                '_builtin'    => true, /* internal use only. */
    107                 'label_count' => _n_noop( 'Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>' ),
    108111        ) );
    109112
    110113        register_post_status( 'future', array(
    111                 'label'       => _x( 'Scheduled', 'post' ),
     114                'labels'          => array(
     115                        'name'    => _x( 'Scheduled', 'post' ),
     116                        'publish' => esc_attr__('Schedule'),
     117                        'count' => _n_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>' ),
     118                ),
    112119                'protected'   => true,
    113120                '_builtin'    => true, /* internal use only. */
    114                 'label_count' => _n_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>' ),
    115121        ) );
    116122
    117123        register_post_status( 'draft', array(
    118                 'label'       => _x( 'Draft', 'post' ),
     124                'labels'          => array(
     125                        'name'    => _x( 'Draft', 'post' ),
     126                        'save_as' => esc_attr__('Save Draft'),
     127                        'count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>' ),
     128                ),
    119129                'protected'   => true,
    120130                '_builtin'    => true, /* internal use only. */
    121                 'label_count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>' ),
    122131        ) );
    123132
    124133        register_post_status( 'pending', array(
    125                 'label'       => _x( 'Pending', 'post' ),
     134                'labels'          => array(
     135                        'name'    => _x( 'Pending', 'post' ),
     136                        'caption' => __( 'Pending Review' ),
     137                        'publish' => esc_attr__('Submit for Review'),
     138                        'count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>' ),
     139                ),
    126140                'protected'   => true,
    127141                '_builtin'    => true, /* internal use only. */
    128                 'label_count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>' ),
     142                'moderation'  => true,
    129143        ) );
    130144
    131145        register_post_status( 'private', array(
    132                 'label'       => _x( 'Private', 'post' ),
     146                'labels'          => array(
     147                        'name'   => _x( 'Private', 'post' ),
     148                        'caption' => __( 'Privately Published' ),
     149                        'count' => _n_noop( 'Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>' ),
     150                ),
    133151                'private'     => true,
    134152                '_builtin'    => true, /* internal use only. */
    135                 'label_count' => _n_noop( 'Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>' ),
    136153        ) );
    137154
    138155        register_post_status( 'trash', array(
    139                 'label'       => _x( 'Trash', 'post' ),
     156                'labels'          => array(
     157                        'name'   => _x( 'Trash', 'post' ),
     158                        'count' => _n_noop( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>' ),
     159                ),
    140160                'internal'    => true,
    141161                '_builtin'    => true, /* internal use only. */
    142                 'label_count' => _n_noop( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>' ),
    143162                'show_in_admin_status_list' => true,
    144163        ) );
    145164
    146165        register_post_status( 'auto-draft', array(
    147                 'label'    => 'auto-draft',
     166                'labels'          => array(
     167                        'name'    => 'auto-draft',
     168                        'caption' => __( 'Draft' ),
     169                ),
    148170                'internal' => true,
    149171                '_builtin' => true, /* internal use only. */
     172                'a' => false,
     173                'show_in_admin_status_list' => false,
    150174        ) );
    151175
    152176        register_post_status( 'inherit', array(
    153                 'label'    => 'inherit',
     177                'labels'          => array(
     178                        'name'   => 'inherit',
     179                ),
    154180                'internal' => true,
    155181                '_builtin' => true, /* internal use only. */
    156182                'exclude_from_search' => false,
    function register_post_status($post_status, $args = array()) { 
    671697                $wp_post_statuses = array();
    672698
    673699        // Args prefixed with an underscore are reserved for internal use.
    674         $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);
     700        $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, 'publicly_queryable' => null, 'show_in_admin_status_list' => null, 'show_in_admin_all_list' => null, 'single_view_cap' => null);
     701       
    675702        $args = wp_parse_args($args, $defaults);
    676703        $args = (object) $args;
    677704
    678705        $post_status = sanitize_key($post_status);
    679706        $args->name = $post_status;
    680707
     708        if ( null == $args->object_type ) {
     709                $args->object_type = array_values( get_post_types( array( 'public' => true, 'show_ui' => true ) ) );
     710        } else {
     711                $args->object_type = (array) $args->object_type;
     712        }
     713       
    681714        if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private )
    682715                $args->internal = true;
    683716
    function register_post_status($post_status, $args = array()) { 
    687720        if ( null === $args->private  )
    688721                $args->private = false;
    689722
     723        if ( null === $args->moderation  )
     724                $args->moderation = false;
     725               
    690726        if ( null === $args->protected  )
    691727                $args->protected = false;
    692728
    function register_post_status($post_status, $args = array()) { 
    708744        if ( null === $args->single_view_cap )
    709745                $args->single_view_cap = $args->public ? '' : 'edit';
    710746
    711         if ( false === $args->label )
    712                 $args->label = $post_status;
     747        $args->labels = (object) $args->labels;
     748
     749        if ( empty( $args->labels->name ) )
     750                $args->labels->name = ( ! empty( $args->label ) ) ? $args->label : $post_status;
     751       
     752        if ( empty( $args->label ) )
     753                $args->label = $args->labels->name;
     754               
     755        if ( empty( $args->labels->caption ) )
     756                $args->labels->caption = $args->label;
     757
     758        if ( empty( $args->labels->count ) )
     759                $args->labels->count = ( ! empty( $args->label_count ) ) ? $args->label_count : array( $args->label, $args->label );
    713760
    714         if ( false === $args->label_count )
    715                 $args->label_count = array( $args->label, $args->label );
     761        if ( empty( $args->label_count ) )      // TODO: need to support this for external API?
     762                $args->label_count = $args->labels->count;
     763
     764        if ( empty( $args->labels->publish ) )
     765                $args->labels->publish = esc_attr( sprintf( __( 'Set %s' ), $args->label ) );
     766
     767        if ( empty( $args->labels->save_as ) )
     768                $args->labels->save_as = esc_attr( sprintf( __( 'Save as %s' ), $args->label ) );
     769
     770        if ( empty( $args->labels->visibility ) ) {
     771                if ( 'publish' == $post_status )
     772                        $args->labels->visibility =__( 'Public' );
     773                elseif ( $args->public )
     774                        $args->labels->visibility = esc_attr( sprintf( __( 'Public (%s)' ), $args->label ) );
     775                elseif ( $args->private )
     776                        $args->labels->visibility = $args->label;
     777        }
    716778
    717779        $wp_post_statuses[$post_status] = $args;
    718780
    719781        return $args;
    720782}
    721783
     784 /**
     785 * Add an already registered post status to an object type.
     786 *
     787 * @package WordPress
     788 * @subpackage Taxonomy
     789 * @since 3.1.0
     790 * @uses $wp_post_statuses Modifies post_type object
     791 *
     792 * @param string $post_status Name of post_status object
     793 * @param array|string $object_type Name of the object type
     794 * @return bool True if successful, false if not
     795 */
     796function register_status_for_object_type( $post_status, $object_type) {
     797        global $wp_post_statuses;
     798
     799        if ( ! isset( $wp_post_statuses[$post_status] ) )
     800                return false;
     801
     802        if ( ! get_post_type_object($object_type) )
     803                return false;
     804
     805        $wp_post_statuses[$post_status]->object_type[] = $object_type;
     806
     807        return true;
     808}
     809
    722810/**
    723811 * Retrieve a post status object by name
    724812 *
    function get_post_status_object( $post_status ) { 
    759847 */
    760848function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) {
    761849        global $wp_post_statuses;
     850       
     851        $post_statuses = $wp_post_statuses;
    762852
    763853        $field = ('names' == $output) ? 'name' : false;
     854       
     855        //wp_filter_object_list doesn't like nested arrays,
     856        //so grab a subset of post stati that match the query, and THEN run through wp_list_filter
     857        if ( ! empty( $args['object_type'] ) ) {
     858                $post_statuses = get_object_stati( $args['object_type'], 'objects' );
     859                unset( $args['object_type'] );
     860        }
    764861
    765         return wp_filter_object_list($wp_post_statuses, $args, $operator, $field);
     862        return wp_filter_object_list( $post_statuses, $args, $operator, $field );
     863}
     864
     865/**
     866 * Return all of the post_statuses that are of $object_type.
     867 * *
     868 * <code><?php $taxonomies = get_object_stati('post'); ?></code> Should
     869 * result in <code>Array('publish', 'future', 'pending', etc. )</code>
     870 *
     871 * @package WordPress
     872 * @subpackage Taxonomy
     873 * @since 3.5
     874 *
     875 * @uses $wp_post_statuses
     876 *
     877 * @param array|string|object $object Name of the type of post_status object, or an object (row from posts)
     878 * @param string $output The type of output to return, either status 'names' or 'objects'. 'names' is the default.
     879 * @return array The names of all statuses of $object_type.
     880 */
     881
     882function get_object_stati($object, $output = 'names') {
     883        global $wp_post_statuses;
     884
     885        if ( is_object($object) )
     886                $object = $object->post_type;
     887
     888        $object = (array) $object;
     889
     890        $stati = array();
     891        foreach ( (array) $wp_post_statuses as $status_name => $status_obj ) {
     892                if ( array_intersect($object, (array) $status_obj->object_type) ) {
     893                        if ( 'names' == $output )
     894                                $stati[] = $status_name;
     895                        else
     896                                $stati[ $status_name ] = $status_obj;
     897                }
     898        }
     899
     900        return $stati;
    766901}
    767902
    768903/**
    function register_post_type( $post_type, $args = array() ) { 
    9661101                '_builtin' => false, '_edit_link' => 'post.php?post=%d', 'hierarchical' => false,
    9671102                'public' => false, 'rewrite' => true, 'has_archive' => false, 'query_var' => true,
    9681103                'supports' => array(), 'register_meta_box_cb' => null,
    969                 'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
     1104                'taxonomies' => array(), 'statuses' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
    9701105                'can_export' => true,
    9711106                'show_in_nav_menus' => null, 'show_in_menu' => null, 'show_in_admin_bar' => null,
    9721107                'delete_with_user' => null,
    function register_post_type( $post_type, $args = array() ) { 
    10881223        foreach ( $args->taxonomies as $taxonomy ) {
    10891224                register_taxonomy_for_object_type( $taxonomy, $post_type );
    10901225        }
     1226       
     1227        foreach ( $args->statuses as $post_status ) {
     1228                register_status_for_object_type( $post_status, $post_type );
     1229        }
    10911230
    10921231        do_action( 'registered_post_type', $post_type, $args );
    10931232
    function wp_count_posts( $type = 'post', $perm = '' ) { 
    18622001        $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
    18632002        if ( 'readable' == $perm && is_user_logged_in() ) {
    18642003                $post_type_object = get_post_type_object($type);
    1865                 if ( !current_user_can( $post_type_object->cap->read_private_posts ) ) {
    1866                         $cache_key .= '_' . $perm . '_' . $user->ID;
    1867                         $query .= " AND (post_status != 'private' OR ( post_author = '$user->ID' AND post_status = 'private' ))";
     2004                foreach( get_post_stati( array( 'private' => true, 'object_type' => $type ) ) as $_status ) {
     2005                        $cap_name = "read_{$_status}_posts";
     2006                        if ( ! empty($post_type_object->cap->$cap_name) && ! current_user_can( $post_type_object->cap->$cap_name ) ) {
     2007                                $suffix = ( 'private' == $_status ) ? '' : $_status;
     2008                                $cache_key .= '_' . $perm . $suffix . '_' . $user->ID;
     2009                                $query .= " AND (post_status != '$_status' OR ( post_author = '$user->ID' AND post_status = '$_status' ))";
     2010                        }
    18682011                }
    18692012        }
    18702013        $query .= ' GROUP BY post_status';
    1871 
     2014       
    18722015        $count = wp_cache_get($cache_key, 'counts');
    18732016        if ( false !== $count )
    18742017                return $count;
    function wp_count_posts( $type = 'post', $perm = '' ) { 
    18762019        $count = $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
    18772020
    18782021        $stats = array();
    1879         foreach ( get_post_stati() as $state )
     2022        foreach ( get_post_stati( array( 'object_type' => $type ) ) as $state )
    18802023                $stats[$state] = 0;
    18812024
    18822025        foreach ( (array) $count as $row )
    function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) { 
    23512494                $args = array( 'numberposts' => absint( $args ) );
    23522495        }
    23532496
     2497        $status_names = get_post_stati( array( 'public' => true, 'object_type' => 'post' ) );
     2498        $status_names_csv = "'" . implode( "', '", $status_names ) . "'";
     2499
    23542500        // Set default arguments
    23552501        $defaults = array(
    23562502                'numberposts' => 10, 'offset' => 0,
    23572503                'category' => 0, 'orderby' => 'post_date',
    23582504                'order' => 'DESC', 'include' => '',
    23592505                'exclude' => '', 'meta_key' => '',
    2360                 'meta_value' =>'', 'post_type' => 'post', 'post_status' => 'draft, publish, future, pending, private',
     2506                'meta_value' =>'', 'post_type' => 'post', 'post_status' => $status_names_csv,
    23612507                'suppress_filters' => true
    23622508        );
    23632509
    function wp_insert_post($postarr, $wp_error = false) { 
    25242670        }
    25252671
    25262672        // Don't allow contributors to set the post slug for pending review posts
    2527         if ( 'pending' == $post_status && !current_user_can( 'publish_posts' ) )
     2673        $post_status_obj = get_post_status_object( $post_status );
     2674        $draft_or_pending = in_array( $post_status, array( 'draft', 'auto-draft' ) ) || ! empty( $post_status_obj->moderation );
     2675
     2676        if ( ! empty( $post_status_obj->moderation ) && ! current_user_can( 'publish_posts' ) )
    25282677                $post_name = '';
    25292678
    25302679        // Create a valid post name. Drafts and pending posts are allowed to have an empty
    25312680        // post name.
    25322681        if ( empty($post_name) ) {
    2533                 if ( !in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
     2682                if ( ! $draft_or_pending )
    25342683                        $post_name = sanitize_title($post_title);
    25352684                else
    25362685                        $post_name = '';
    function wp_insert_post($postarr, $wp_error = false) { 
    25482697                $post_date = current_time('mysql');
    25492698
    25502699        if ( empty($post_date_gmt) || '0000-00-00 00:00:00' == $post_date_gmt ) {
    2551                 if ( !in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
     2700                if ( ! $draft_or_pending )
    25522701                        $post_date_gmt = get_gmt_from_date($post_date);
    25532702                else
    25542703                        $post_date_gmt = '0000-00-00 00:00:00';
    function wp_insert_post($postarr, $wp_error = false) { 
    25622711                $post_modified_gmt = $post_date_gmt;
    25632712        }
    25642713
    2565         if ( 'publish' == $post_status ) {
     2714        $set_status = $post_status;
     2715       
     2716        if ( $post_status_obj->public || $post_status_obj->private ) {
    25662717                $now = gmdate('Y-m-d H:i:59');
    25672718                if ( mysql2date('U', $post_date_gmt, false) > mysql2date('U', $now, false) )
    25682719                        $post_status = 'future';
    function wp_insert_post($postarr, $wp_error = false) { 
    25722723                        $post_status = 'publish';
    25732724        }
    25742725
     2726        if ( ( 'future' == $post_status ) && ( 'publish' != $set_status ) ) {
     2727                update_post_meta( $post_ID, '_scheduled_status', $set_status );
     2728        } else
     2729                delete_post_meta( $post_ID, '_scheduled_status' );
     2730
    25752731        if ( empty($comment_status) ) {
    25762732                if ( $update )
    25772733                        $comment_status = 'closed';
    function wp_insert_post($postarr, $wp_error = false) { 
    26022758        else
    26032759                $menu_order = 0;
    26042760
    2605         if ( !isset($post_password) || 'private' == $post_status )
     2761        if ( ! isset($post_password) || $post_status_obj->private )
    26062762                $post_password = '';
    26072763
    26082764        $post_name = wp_unique_post_slug($post_name, $post_ID, $post_status, $post_type, $post_parent);
    function wp_insert_post($postarr, $wp_error = false) { 
    26432799                $where = array( 'ID' => $post_ID );
    26442800        }
    26452801
    2646         if ( empty($data['post_name']) && !in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
     2802        $post_status_obj = get_post_status_object( $data['post_status'] );
     2803        $draft_or_pending = in_array( $data['post_status'], array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation);
     2804       
     2805        if ( empty($data['post_name']) && ! $draft_or_pending ) {
    26472806                $data['post_name'] = sanitize_title($data['post_title'], $post_ID);
    26482807                $wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where );
    26492808        }
    function wp_update_post($postarr = array()) { 
    27332892                $post_cats = $post['post_category'];
    27342893
    27352894        // Drafts shouldn't be assigned a date unless explicitly done so by the user
    2736         if ( isset( $post['post_status'] ) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) && empty($postarr['edit_date']) &&
    2737                          ('0000-00-00 00:00:00' == $post['post_date_gmt']) )
    2738                 $clear_date = true;
    2739         else
     2895        if ( isset( $post['post_status'] ) && empty($postarr['edit_date']) && ('0000-00-00 00:00:00' == $post['post_date_gmt']) ) {
     2896                $post_status_obj = get_post_status_object( $post['post_status'] );
     2897
     2898                $clear_date = in_array( $post['post_status'], array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation);
     2899        } else
    27402900                $clear_date = false;
    27412901
    27422902        // Merge old and new fields with new fields overwriting old ones.
    function wp_publish_post($post_id) { 
    27742934        if ( 'publish' == $post->post_status )
    27752935                return;
    27762936
    2777         $wpdb->update( $wpdb->posts, array( 'post_status' => 'publish' ), array( 'ID' => $post_id ) );
     2937        if ( 'future' == $post->post_status ) {
     2938                if ( ! $post_status = get_post_meta( $post_id, '_scheduled_status', true ) )
     2939                        $post_status = 'publish';       
     2940        } else
     2941                $post_status = 'publish';
     2942
     2943        $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $post_id ) );
    27782944
    27792945        $old_status = $post->post_status;
    27802946        $post->post_status = 'publish';
    function check_and_publish_future_post($post_id) { 
    28322998 * @return string unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)
    28332999 */
    28343000function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent ) {
    2835         if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
     3001        $post_status_obj = get_post_status_object( $post_status );
     3002
     3003        if ( in_array( $post_status, array('draft', 'auto-draft') ) || ! empty($post_status_obj->moderation) )
    28363004                return $slug;
    28373005
    28383006        global $wpdb, $wp_rewrite;
    function get_page_uri($page) { 
    33703538 * @param mixed $args Optional. Array or string of options that overrides defaults.
    33713539 * @return array List of pages matching defaults or $args
    33723540 */
    3373 function &get_pages($args = '') {
     3541function &get_pages($args = '') { 
    33743542        global $wpdb;
    33753543
    33763544        $defaults = array(
    function &get_pages($args = '') { 
    33873555        extract( $r, EXTR_SKIP );
    33883556        $number = (int) $number;
    33893557        $offset = (int) $offset;
    3390 
     3558        $false = false;
     3559       
    33913560        // Make sure the post type is hierarchical
    33923561        $hierarchical_post_types = get_post_types( array( 'hierarchical' => true ) );
    33933562        if ( !in_array( $post_type, $hierarchical_post_types ) )
    3394                 return false;
     3563                return $false;
    33953564
    33963565        // Make sure we have a valid post status
    33973566        if ( !is_array( $post_status ) )
    33983567                $post_status = explode( ',', $post_status );
    3399         if ( array_diff( $post_status, get_post_stati() ) )
    3400                 return false;
     3568
     3569        if ( array_diff( $post_status, get_post_stati( array( 'object_type' => $post_type ) ) ) )
     3570                return $false;
    34013571
    34023572        $cache = array();
    34033573        $key = md5( serialize( compact(array_keys($defaults)) ) );
  • wp-includes/query.php

    diff --git wp-includes/query.php wp-includes/query.php
    index 5f6ccdd..35d3785 100644
    class WP_Query { 
    24032403                        $post_type_object = get_post_type_object ( 'post' );
    24042404                }
    24052405
     2406                $_post_type = ( $post_type ) ? $post_type : 'post';  // corresponds to hardcoded default for POST_TYPE clause
     2407                $type_arg = ( 'any' == $_post_type ) ? array() : array( 'object_type' => $_post_type );
     2408
    24062409                if ( ! empty( $post_type_object ) ) {
     2410                        $post_type_cap = $post_type_object->capability_type;
    24072411                        $edit_cap = $post_type_object->cap->edit_post;
    24082412                        $read_cap = $post_type_object->cap->read_post;
    24092413                        $edit_others_cap = $post_type_object->cap->edit_others_posts;
    2410                         $read_private_cap = $post_type_object->cap->read_private_posts;
    24112414                } else {
    24122415                        $edit_cap = 'edit_' . $post_type_cap;
    24132416                        $read_cap = 'read_' . $post_type_cap;
    24142417                        $edit_others_cap = 'edit_others_' . $post_type_cap . 's';
    2415                         $read_private_cap = 'read_private_' . $post_type_cap . 's';
    24162418                }
    24172419
    24182420                if ( ! empty( $q['post_status'] ) ) {
    class WP_Query { 
    24222424                                $q_status = explode(',', $q_status);
    24232425                        $r_status = array();
    24242426                        $p_status = array();
     2427                        $p_status_owner = array();
    24252428                        $e_status = array();
    24262429                        if ( in_array('any', $q_status) ) {
    24272430                                foreach ( get_post_stati( array('exclude_from_search' => true) ) as $status )
    24282431                                        $e_status[] = "$wpdb->posts.post_status <> '$status'";
    24292432                        } else {
    2430                                 foreach ( get_post_stati() as $status ) {
     2433                                $_args = array_merge( array(), $type_arg );
     2434                                foreach ( get_post_stati( $_args, 'object' ) as $status => $status_obj ) {
    24312435                                        if ( in_array( $status, $q_status ) ) {
    2432                                                 if ( 'private' == $status )
    2433                                                         $p_status[] = "$wpdb->posts.post_status = '$status'";
    2434                                                 else
     2436                                                if ( $status_obj->private ) {
     2437                                                        if ( ! empty($post_type_object) ) {
     2438                                                                $check_cap = "read_{$status}_posts";
     2439                                                                $read_private_cap = ( ! empty( $post_type_object->cap->$check_cap ) ) ? $post_type_object->cap->$check_cap : $post_type_object->cap->read_private_posts;
     2440                                                        } else
     2441                                                                $read_private_cap = 'read_private_' . $post_type_cap . 's';
     2442                                                       
     2443                                                        if ( ! empty($q['perm'] ) && 'readable' == $q['perm'] && ! current_user_can( $read_private_cap ) )
     2444                                                                $p_status_owner[] = "$wpdb->posts.post_status = '$status'";
     2445                                                        else
     2446                                                                $p_status[] = "$wpdb->posts.post_status = '$status'";
     2447                                                } else
    24352448                                                        $r_status[] = "$wpdb->posts.post_status = '$status'";
    24362449                                        }
    24372450                                }
    24382451                        }
    24392452
    24402453                        if ( empty($q['perm'] ) || 'readable' != $q['perm'] ) {
    2441                                 $r_status = array_merge($r_status, $p_status);
     2454                                $r_status = array_merge($r_status, $p_status, $p_status_owner);
    24422455                                unset($p_status);
     2456                                unset($p_status_owner);
    24432457                        }
    24442458
    24452459                        if ( !empty($e_status) ) {
    class WP_Query { 
    24512465                                else
    24522466                                        $statuswheres[] = "(" . join( ' OR ', $r_status ) . ")";
    24532467                        }
    2454                         if ( !empty($p_status) ) {
     2468
     2469                        if ( ! empty( $p_status ) ) {
    24552470                                if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) )
    24562471                                        $statuswheres[] = "($wpdb->posts.post_author = $user_ID " . "AND (" . join( ' OR ', $p_status ) . "))";
    24572472                                else
    24582473                                        $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
    24592474                        }
     2475                        if ( ! empty( $p_status ) ) {                   
     2476                                $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
     2477                        }
    24602478                        if ( $post_status_join ) {
    24612479                                $join .= " LEFT JOIN $wpdb->posts AS p2 ON ($wpdb->posts.post_parent = p2.ID) ";
    24622480                                foreach ( $statuswheres as $index => $statuswhere )
    24632481                                        $statuswheres[$index] = "($statuswhere OR ($wpdb->posts.post_status = 'inherit' AND " . str_replace($wpdb->posts, 'p2', $statuswhere) . "))";
    24642482                        }
    24652483                        foreach ( $statuswheres as $statuswhere )
    2466                                 $where .= " AND $statuswhere";
     2484                                $where .= " AND $statuswhere"; 
     2485
    24672486                } elseif ( !$this->is_singular ) {
    24682487                        $where .= " AND ($wpdb->posts.post_status = 'publish'";
    24692488
    24702489                        // Add public states.
    2471                         $public_states = get_post_stati( array('public' => true) );
     2490                        $_args = array_merge( array( 'public' => true ), $type_arg );
     2491                        $public_states = apply_filters_ref_array( 'posts_public_stati', array( get_post_stati( $_args ), &$this ) );
    24722492                        foreach ( (array) $public_states as $state ) {
    24732493                                if ( 'publish' == $state ) // Publish is hard-coded above.
    24742494                                        continue;
    class WP_Query { 
    24772497
    24782498                        if ( $this->is_admin ) {
    24792499                                // Add protected states that should show in the admin all list.
    2480                                 $admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true) );
     2500                                $_args = array_merge( array( 'show_in_admin_all_list' => true ), $type_arg );
     2501                                $admin_all_states = get_post_stati( $_args );
    24812502                                foreach ( (array) $admin_all_states as $state )
    24822503                                        $where .= " OR $wpdb->posts.post_status = '$state'";
    24832504                        }
    24842505
    24852506                        if ( is_user_logged_in() ) {
    24862507                                // Add private states that are limited to viewing by the author of a post or someone who has caps to read private states.
    2487                                 $private_states = get_post_stati( array('private' => true) );
    2488                                 foreach ( (array) $private_states as $state )
     2508                                $_args = array_merge( array( 'private' => true ), $type_arg );
     2509                                $private_states = apply_filters_ref_array( 'posts_private_stati', array( get_post_stati( $_args ), &$this ) );
     2510                                foreach ( (array) $private_states as $state ) {
     2511                                        if ( ! empty($post_type_object) ) {
     2512                                                $check_cap = "read_{$state}_posts";
     2513                                                $read_private_cap = ( ! empty( $post_type_object->cap->$check_cap ) ) ? $post_type_object->cap->$check_cap : $post_type_object->cap->read_private_posts;
     2514                                        } else
     2515                                                $read_private_cap = 'read_private_' . $post_type_cap . 's';
     2516
    24892517                                        $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'";
     2518                                }
    24902519                        }
    24912520
    24922521                        $where .= ')';
    class WP_Query { 
    25272556                                $cwhere = "WHERE comment_approved = '1' $where";
    25282557                                $cgroupby = "$wpdb->comments.comment_id";
    25292558                        } else { // Other non singular e.g. front
     2559                                $public_stati = apply_filters( 'comment_feed_stati', get_post_stati( array( 'public' => true ) ) );
     2560                                $public_csv = implode( "', '", $public_stati );
     2561
    25302562                                $cjoin = "JOIN $wpdb->posts ON ( $wpdb->comments.comment_post_ID = $wpdb->posts.ID )";
    2531                                 $cwhere = "WHERE post_status = 'publish' AND comment_approved = '1'";
     2563                                $cwhere = "WHERE post_status IN ( '$public_csv' ) AND comment_approved = '1'";
    25322564                                $cgroupby = '';
    25332565                        }
    25342566
    class WP_Query { 
    27422774                                        $stickies_where = "AND $wpdb->posts.post_type IN ('" . $post_types . "')";
    27432775                                }
    27442776
     2777                                $public_stati = apply_filters_ref_array( 'posts_sticky_stati', array( get_post_stati( array( 'public' => true ) ), &$this ) );
    27452778                                $stickies = $wpdb->get_results( "SELECT * FROM $wpdb->posts WHERE $wpdb->posts.ID IN ($stickies__in) $stickies_where" );
    27462779                                foreach ( $stickies as $sticky_post ) {
    27472780                                        // Ignore sticky posts the current user cannot read or are not published.
    2748                                         if ( 'publish' != $sticky_post->post_status )
     2781                                        if ( ! in_array( $sticky_post->post_status, $public_stati ) )
    27492782                                                continue;
     2783
    27502784                                        array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
    27512785                                        $sticky_offset++;
    27522786                                }
  • wp-includes/script-loader.php

    diff --git wp-includes/script-loader.php wp-includes/script-loader.php
    index dab5868..c54ccd9 100644
    function wp_default_scripts( &$scripts ) { 
    339339                $scripts->add( 'postbox', "/wp-admin/js/postbox$suffix.js", array('jquery-ui-sortable'), false, 1 );
    340340
    341341                $scripts->add( 'post', "/wp-admin/js/post$suffix.js", array('suggest', 'wp-lists', 'postbox'), false, 1 );
    342                 $scripts->localize( 'post', 'postL10n', array(
     342                $arr = array(
    343343                        'ok' => __('OK'),
    344344                        'cancel' => __('Cancel'),
    345345                        'publishOn' => __('Publish on:'),
    function wp_default_scripts( &$scripts ) { 
    359359                        'privatelyPublished' => __('Privately Published'),
    360360                        'published' => __('Published'),
    361361                        'comma' => _x( ',', 'tag delimiter' ),
    362                 ) );
     362                );
     363               
     364                if ( function_exists( 'get_post_stati' ) ) {
     365                        $custom = array();
     366                        foreach( get_post_stati( array( 'public' => true, 'private' => true ), 'object', 'or' ) as $_status => $_status_obj ) {
     367                                if ( 'publish' == $_status )
     368                                        continue;
     369                       
     370                                $custom[ $_status ] = $_status_obj->labels->visibility;
     371                       
     372                                if ( $_status_obj->public )
     373                                        $custom[ $_status . 'Sticky' ] = sprintf( __('%s, Sticky'), $_status_obj->label );
     374                        }
     375                       
     376                        $arr = array_merge( $custom, $arr );  // note: 'publish' has existing value of 'Publish', cannot be used to reference status name
     377                }
     378               
     379                $scripts->localize( 'post', 'postL10n', $arr );
    363380
    364381                $scripts->add( 'link', "/wp-admin/js/link$suffix.js", array('wp-lists', 'postbox'), false, 1 );
     382                $scripts->add_data( 'link', 'group', 1 );
    365383
    366384                $scripts->add( 'comment', "/wp-admin/js/comment$suffix.js", array('jquery') );
    367385                $scripts->add_data( 'comment', 'group', 1 );
  • wp-includes/taxonomy.php

    diff --git wp-includes/taxonomy.php wp-includes/taxonomy.php
    index 8ea976f..25bd211 100644
    function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) 
    132132
    133133        $field = ('names' == $output) ? 'name' : false;
    134134
     135        if ( isset( $args['object_type'] ) )
     136                $args['object_type'] = (array) $args['object_type'];
     137
    135138        return wp_filter_object_list($wp_taxonomies, $args, $operator, $field);
    136139}
    137140
    function _pad_term_counts(&$terms, $taxonomy) { 
    28402843        // Get the object and term ids and stick them in a lookup table
    28412844        $tax_obj = get_taxonomy($taxonomy);
    28422845        $object_types = esc_sql($tax_obj->object_type);
    2843         $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'");
     2846       
     2847        $public_stati = apply_filters( 'term_count_stati', get_post_stati( array( 'public' => true, 'object_type' => $tax_obj->object_type ) ) );
     2848        $public_csv = implode( "', '", $public_stati );
     2849
     2850        $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')");
    28442851        foreach ( $results as $row ) {
    28452852                $id = $term_ids[$row->term_taxonomy_id];
    28462853                $term_items[$id][$row->object_id] = isset($term_items[$id][$row->object_id]) ? ++$term_items[$id][$row->object_id] : 1;
    function _update_post_term_count( $terms, $taxonomy ) { 
    29012908        if ( $object_types )
    29022909                $object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) );
    29032910
     2911        $public_stati = apply_filters( 'term_count_stati', get_post_stati( array( 'public' => true, 'object_type' => $taxonomy->object_type ) ) );
     2912        $public_csv = implode( "', '", $public_stati );
     2913       
    29042914        foreach ( (array) $terms as $term ) {
     2915
    29052916                $count = 0;
    29062917
    29072918                // Attachments can be 'inherit' status, we need to base count off the parent's status if so
    29082919                if ( $check_attachments )
    2909                         $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts p1 WHERE p1.ID = $wpdb->term_relationships.object_id AND ( post_status = 'publish' OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM $wpdb->posts WHERE ID = p1.post_parent ) = 'publish' ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term ) );
     2920                        $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts p1 WHERE p1.ID = $wpdb->term_relationships.object_id AND ( post_status IN ('$public_csv') OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM $wpdb->posts WHERE ID = p1.post_parent ) IN ('$public_csv') ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term ) );
    29102921
    29112922                if ( $object_types )
    2912                         $count += (int) $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 ) );
     2923                        $count += (int) $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 ) );
    29132924
    29142925                do_action( 'edit_term_taxonomy', $term, $taxonomy );
    29152926                $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );