From f18f34ead8f6448b773b1896a2460d50954fb84a Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 16 Feb 2010 21:13:44 +0000 Subject: [PATCH] Flag post statuses as public, private, protected, or internal. Add flags for showing the type in the admin all query and the admin status list. see #9674 git-svn-id: http://svn.automattic.com/wordpress/trunk@13172 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/edit.php | 2 +- wp-includes/post.php | 65 ++++++++++++++++++++++++++++---------- wp-includes/query.php | 72 ++++++++++++++++++++++++++++++------------- 3 files changed, 100 insertions(+), 39 deletions(-) diff --git a/wp-admin/edit.php b/wp-admin/edit.php index b3ac11e1d..283cced41 100644 --- a/wp-admin/edit.php +++ b/wp-admin/edit.php @@ -232,7 +232,7 @@ $total_posts = array_sum( (array) $num_posts ) - $num_posts->trash; $class = empty($class) && empty($_GET['post_status']) ? ' class="current"' : ''; $status_links[] = "
  • " . sprintf( _nx( 'All (%s)', 'All (%s)', $total_posts, 'posts' ), number_format_i18n( $total_posts ) ) . ''; -foreach ( get_post_stati(array('show_in_admin_edit' => true), 'objects') as $status ) { +foreach ( get_post_stati(array('show_in_admin_status_list' => true), 'objects') as $status ) { $class = ''; $status_name = $status->name; diff --git a/wp-includes/post.php b/wp-includes/post.php index 1001cbf5d..94fbdfdb6 100644 --- a/wp-includes/post.php +++ b/wp-includes/post.php @@ -70,33 +70,38 @@ function create_initial_post_types() { ) ); register_post_status( 'future', array( 'label' => _x('Scheduled', 'post'), - 'public' => true, + 'protected' => true, '_builtin' => true, 'label_count' => _n_noop('Scheduled (%s)', 'Scheduled (%s)') ) ); register_post_status( 'draft', array( 'label' => _x('Draft', 'post'), - 'public' => true, + 'protected' => true, '_builtin' => true, 'label_count' => _n_noop('Draft (%s)', 'Drafts (%s)') ) ); + register_post_status( 'pending', array( 'label' => _x('Pending', 'post'), + 'protected' => true, + '_builtin' => true, + 'label_count' => _n_noop('Pending (%s)', 'Pending (%s)') + ) ); + register_post_status( 'private', array( 'label' => _x('Private', 'post'), - 'public' => true, + 'private' => true, '_builtin' => true, 'label_count' => _n_noop('Private (%s)', 'Private (%s)') ) ); register_post_status( 'trash', array( 'label' => _x('Trash', 'post'), - 'public' => true, - 'exclude_from_search' => true, + 'internal' => true, + 'show_in_admin_status_list' => true, '_builtin' => true, 'label_count' => _n_noop('Trash (%s)', 'Trash (%s)') ) ); register_post_status( 'auto-draft', array( 'label' => _x('Auto-Draft', 'post'), - 'public' => false, - 'exclude_from_search' => true, + 'internal' => true, '_builtin' => true, 'label_count' => _n_noop('Auto-Draft (%s)', 'Auto-Drafts (%s)') ) ); @@ -526,24 +531,42 @@ function register_post_status($post_status, $args = array()) { $wp_post_statuses = array(); // Args prefixed with an underscore are reserved for internal use. - $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' => false, 'publicly_queryable' => null, 'show_in_admin_edit' => null); + $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); $args = wp_parse_args($args, $defaults); $args = (object) $args; $post_status = sanitize_user($post_status, true); $args->name = $post_status; - // If not set, default to the setting for public. + if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private ) + $args->internal = true; + + if ( null === $args->public ) + $args->public = false; + + if ( null === $args->private ) + $args->private = false; + + if ( null === $args->protected ) + $args->protected = false; + + if ( null === $args->internal ) + $args->internal = false; + if ( null === $args->publicly_queryable ) $args->publicly_queryable = $args->public; - // If not set, default to true if not public, false if public. if ( null === $args->exclude_from_search ) - $args->exclude_from_search = !$args->public; + $args->exclude_from_search = $args->internal; - // If not set, default to the setting for public. - if ( null === $args->show_in_admin_edit ) - $args->show_in_admin_edit = $args->public; + if ( null === $args->show_in_admin_all_list ) + $args->show_in_admin_all_list = !$args->internal; + + if ( null === $args->show_in_admin_status_list ) + $args->show_in_admin_status_list = !$args->internal; + + if ( null === $args->single_view_cap ) + $args->single_view_cap = $args->public ? '' : 'edit'; if ( false === $args->label ) $args->label = $post_status; @@ -591,15 +614,21 @@ function get_post_status_object( $post_status ) { * @param array|string $args An array of key => value arguments to match against the post statuses. * Only post statuses having attributes that match all arguments are returned. * @param string $output The type of output to return, either post status 'names' or 'objects'. 'names' is the default. + * @param string $operator Whether the elements in $args should be logicallly 'or'ed or 'and'ed together. 'or' means only one element from the array needs to match. 'and' means all elements must match. The default is 'or'. * @return array A list of post type names or objects */ -function get_post_stati( $args = array(), $output = 'names' ) { +function get_post_stati( $args = array(), $output = 'names', $operator = 'or' ) { global $wp_post_statuses; $do_names = false; if ( 'names' == $output ) $do_names = true; + if ( 'and' == $operator ) + $arg_count = count($args); + else + $arg_count = 0; + $post_statuses = array(); foreach ( (array) $wp_post_statuses as $post_status ) { if ( empty($args) ) { @@ -607,7 +636,9 @@ function get_post_stati( $args = array(), $output = 'names' ) { $post_statuses[] = $post_status->name; else $post_statuses[] = $post_status; - } elseif ( array_intersect_assoc((array) $post_status, $args) ) { + } elseif ( $intersect = array_intersect_assoc((array) $post_status, $args) ) { + if ( $arg_count && ( $arg_count != count($intersect) ) ) + continue; if ( $do_names ) $post_statuses[] = $post_status->name; else @@ -787,6 +818,8 @@ function register_post_type($post_type, $args = array()) { $args->publish_cap = 'publish_' . $args->capability_type . 's'; if ( empty($args->read_cap) ) $args->read_cap = 'read_' . $args->capability_type; + if ( empty($args->read_private_cap) ) + $args->read_private_cap = 'read_private_' . $args->capability_type . 's'; if ( empty($args->delete_cap) ) $args->delete_cap = 'delete_' . $args->capability_type; diff --git a/wp-includes/query.php b/wp-includes/query.php index 2628e3c86..ec730daef 100644 --- a/wp-includes/query.php +++ b/wp-includes/query.php @@ -2061,9 +2061,9 @@ class WP_Query { $q['orderby'] = "$wpdb->posts.post_date ".$q['order']; } - if ( is_array($post_type) ) + if ( is_array($post_type) ) { $post_type_cap = 'multiple_post_type'; - else { + } else { $post_type_object = get_post_type_object ( $post_type ); if ( !empty($post_type_object) ) $post_type_cap = $post_type_object->capability_type; @@ -2081,15 +2081,29 @@ class WP_Query { $where .= " AND $wpdb->posts.post_type IN ('" . join("', '", $post_type) . "')"; } elseif ( ! empty( $post_type ) ) { $where .= " AND $wpdb->posts.post_type = '$post_type'"; + $post_type_object = get_post_type_object ( $post_type ); } elseif ( $this->is_attachment ) { $where .= " AND $wpdb->posts.post_type = 'attachment'"; - $post_type_cap = 'post'; + $post_type_object = get_post_type_object ( 'attachment' ); } elseif ($this->is_page) { $where .= " AND $wpdb->posts.post_type = 'page'"; - $post_type_cap = 'page'; + $post_type_object = get_post_type_object ( 'page' ); } else { $where .= " AND $wpdb->posts.post_type = 'post'"; - $post_type_cap = 'post'; + $post_type_object = get_post_type_object ( 'post' ); + } + + if ( !empty($post_type_object) ) { + $post_type_cap = $post_type_object->capability_type; + $edit_cap = $post_type_object->edit_cap; + $read_cap = $post_type_object->read_cap; + $edit_others_cap = $post_type_object->edit_others_cap; + $read_private_cap = $post_type_object->read_private_cap; + } else { + $edit_cap = 'edit_' . $post_type_cap; + $read_cap = 'read_' . $post_type_cap; + $edit_others_cap = 'edit_others_' . $post_type_cap . 's'; + $read_private_cap = 'read_private_' . $post_type_cap . 's'; } if ( isset($q['post_status']) && '' != $q['post_status'] ) { @@ -2121,13 +2135,13 @@ class WP_Query { $statuswheres[] = "(" . join( ' AND ', $e_status ) . ")"; } if ( !empty($r_status) ) { - if ( !empty($q['perm'] ) && 'editable' == $q['perm'] && !current_user_can("edit_others_{$post_type_cap}s") ) + if ( !empty($q['perm'] ) && 'editable' == $q['perm'] && !current_user_can($edit_others_cap) ) $statuswheres[] = "($wpdb->posts.post_author = $user_ID " . "AND (" . join( ' OR ', $r_status ) . "))"; else $statuswheres[] = "(" . join( ' OR ', $r_status ) . ")"; } if ( !empty($p_status) ) { - if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can("read_private_{$post_type_cap}s") ) + if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) ) $statuswheres[] = "($wpdb->posts.post_author = $user_ID " . "AND (" . join( ' OR ', $p_status ) . "))"; else $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")"; @@ -2142,11 +2156,26 @@ class WP_Query { } elseif ( !$this->is_singular ) { $where .= " AND ($wpdb->posts.post_status = 'publish'"; - if ( is_admin() ) - $where .= " OR $wpdb->posts.post_status = 'future' OR $wpdb->posts.post_status = 'draft' OR $wpdb->posts.post_status = 'pending'"; + // Add public states. + $public_states = get_post_stati( array('public' => true) ); + foreach ( (array) $public_states as $state ) { + if ( 'publish' == $state ) // Publish is hard-coded above. + continue; + $where .= " OR $wpdb->posts.post_status = '$state'"; + } + + if ( is_admin() ) { + // Add protected states that should show in the admin all list. + $admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true), 'names', 'and' ); + foreach ( (array) $admin_all_states as $state ) + $where .= " OR $wpdb->posts.post_status = '$state'"; + } if ( is_user_logged_in() ) { - $where .= current_user_can( "read_private_{$post_type_cap}s" ) ? " OR $wpdb->posts.post_status = 'private'" : " OR $wpdb->posts.post_author = $user_ID AND $wpdb->posts.post_status = 'private'"; + // Add private states that are limited to viewing by the author of a post or someone who has caps to read private states. + $private_states = get_post_stati( array('private' => true) ); + foreach ( (array) $private_states as $state ) + $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'"; } $where .= ')'; @@ -2296,33 +2325,32 @@ class WP_Query { // Check post status to determine if post should be displayed. if ( !empty($this->posts) && ($this->is_single || $this->is_page) ) { $status = get_post_status($this->posts[0]); + $post_status_obj = get_post_status_object($status); //$type = get_post_type($this->posts[0]); - if ( ('publish' != $status) ) { + if ( !$post_status_obj->public ) { if ( ! is_user_logged_in() ) { // User must be logged in to view unpublished posts. $this->posts = array(); } else { - if (in_array($status, array('draft', 'pending', 'trash')) ) { + if ( $post_status_obj->protected ) { // User must have edit permissions on the draft to preview. - if (! current_user_can("edit_$post_type_cap", $this->posts[0]->ID)) { + if (! current_user_can($edit_cap, $this->posts[0]->ID)) { $this->posts = array(); } else { $this->is_preview = true; - $this->posts[0]->post_date = current_time('mysql'); + if ('future' != $status) + $this->posts[0]->post_date = current_time('mysql'); } - } else if ('future' == $status) { - $this->is_preview = true; - if (!current_user_can("edit_$post_type_cap", $this->posts[0]->ID)) { - $this->posts = array ( ); - } - } else { - if (! current_user_can("read_$post_type_cap", $this->posts[0]->ID)) + } elseif ( $post_status_obj->private ) { + if ( ! current_user_can($read_cap, $this->posts[0]->ID) ) $this->posts = array(); + } else { + $this->posts = array(); } } } - if ( $this->is_preview && current_user_can( "edit_{$post_type_cap}", $this->posts[0]->ID ) ) + if ( $this->is_preview && current_user_can( $edit_cap, $this->posts[0]->ID ) ) $this->posts[0] = apply_filters('the_preview', $this->posts[0]); }