user_level; $user_ID = $userdata->ID; $user_email = $userdata->user_email; $user_url = $userdata->user_url; $user_pass_md5 = md5($userdata->user_pass); $user_identity = $userdata->display_name; // Should never happen, but just in case if ( empty($current_user) ) $current_user = new WP_User($user_ID); } } } // Defer setup function until pluggable functions have been loaded // (required since we need to call get_currentuserinfo) add_action('init', 'postlevels_setup'); // Initialize plugin variables and functions, called during the // 'init' action by WordPress function postlevels_setup() { // Setup options stored in database postlevels_setup_options(); // Defer admin menu setup to only run if we're in admin section add_action('admin_menu', 'postlevels_admin_hook'); // Don't bother with anything more unless someone is logged in if (is_user_logged_in()) { // Make sure private pages aren't cached publicly header('Cache-Control: private'); header('Pragma: no-cache'); // Setup filters add_filter('posts_join', 'postlevels_posts_join'); add_filter('posts_where', 'postlevels_posts_where'); add_filter('user_has_cap', 'postlevels_has_cap', 10, 3); add_filter('the_title', 'postlevels_the_title', 10, 2); // Initialize global variables global $postlevels_post_key, $postlevels_user_key, $postlevels_current_user_level; $postlevels_post_key = get_option('postlevels_post_key'); $postlevels_user_key = get_option('postlevels_user_key'); $postlevels_current_user_level = postlevels_get_user_level(); // Only filter RSS content if we're using HTTP auth global $postlevels_http_auth; if ($postlevels_http_auth) { global $rss_content; $rss_content = get_option('postlevels_http_auth_rss'); // Don't bother setting up filters if we're not gonna // change the content if ($rss_content != 'full_content') { add_filter('the_content_rss', 'postlevels_the_content_rss'); // WP 2.0 bug? the_content_rss never gets called add_filter('the_content', 'postlevels_the_content_rss'); add_filter('the_excerpt_rss', 'postlevels_the_excerpt_rss'); } } // In case WP ever defines this function for us, check // if it exists first if (!function_exists('is_private')) { // Whether the current post is private (i.e. not level 0) function is_private() { global $post; return ($post->post_status == 'private'); } } // Whether the current posts is of the given level function is_post_level($level = 0) { global $postlevels_post_key; $val = get_post_custom_values($postlevels_post_key); if (!empty($val)) return ($val == $level); else return ($level == 0); } } else { // Not logged in, define fast functions that don't use the DB // in case they're used in the templates function is_post_level($level = 0) { return ($level == 0); } if (!function_exists('is_private')) { function is_private() { return false; } } } } // Creates the database-stored options for the plugins that customize // the plugin's behavior function postlevels_setup_options() { add_option('postlevels_post_key', 'post_level', "The name of the custom field used for specifiying a post's level", 'yes'); add_option('postlevels_user_key', 'wp_user_level', "The name of the custom field used for specifiying a user's privacy level", 'yes'); add_option('postlevels_default_post_level', '0', "Default post level for private posts", 'yes'); add_option('postlevels_default_user_level', '0', "Default user privacy level for users", 'yes'); add_option('postlevels_private_before_title', '', "Default text placed before the title of a private post", 'yes'); add_option('postlevels_private_after_title', ' (private)', "Default text placed after the title of a private post", 'yes'); add_option('postlevels_http_auth_rss', 'title_only', "What content should be displayed in rss feeds when using HTTP authentication", 'yes'); } // Left join with the custom fields table so we can filter // based on level in the where clause function postlevels_posts_join($join) { // We add a left join here on the postmeta table -- // this could conceivably break if another plugin // manipulates the join global $wpdb; return " LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id " . $join; } // Change where clause to accept published posts and private posts // with a post level less than or equal to the user's level function postlevels_posts_where($where) { // This could break if another plugin manipulates the where // clause, specifically the post_status part global $postlevels_current_user_level, $postlevels_post_key, $wpdb; return str_replace('post_status = "publish"', '(post_status = "publish" OR (post_status = "private" ' . "AND ({$wpdb->postmeta}.meta_key = '$postlevels_post_key' " . "AND {$wpdb->postmeta}.meta_value <= $postlevels_current_user_level )))", $where); } // Enable users with the right level to read a private post // This is required because single post viewing has special logic // $allcaps = Capabilities the user currently has // $caps = Primitive capabilities being tested / requested // $args = array with: // $args[0] = original meta capability requested // $args[1] = user being tested // $args[2] = post id to view // See code for assumptions function postlevels_has_cap($allcaps, $caps, $args) { // This handler is only set up to deal with the read_private_posts // capability. Ignore all other calls into here. if (!in_array('read_private_posts', $caps)) { // These aren't the droids you're looking for return $allcaps; } global $postlevels_post_key, $userlevels_key; // As of WP 2.0, read_private_posts is only requested when viewing // a single post. When this happens, the args[] array has three values, // as shown above. If WP changes the args[], this plugin will break // The level of the post being tested $post_level = get_post_meta($args[2], $postlevels_post_key, true); if ($post_level == '') { $post_level = get_option('postlevels_default_post_level'); } // The level of the user being tested $user_level = get_usermeta($args[1], $userlevels_key); if ($user_level == '') { $user_level = get_option('postlevels_default_user_level'); } // Add the capability $capabilities['read_private_posts'] = ($user_level >= $post_level); return $capabilities; } // Modifies the text of a private post function postlevels_the_title($title, $incomingpost = null) { // It's really annoying that WP will call this function sometimes // with a string for the second paramter, and sometimes with // an object ... this checks for that. if (!is_object($incomingpost)) { global $post; $incomingpost = $post; } if ($incomingpost->post_status == 'private') { return get_option('postlevels_private_before_title') . $title . get_option('postlevels_private_after_title'); } else { return $title; } } // Called when using HTTP auth -- changes the post content function postlevels_the_content_rss($content) { global $post, $rss_content; if ($post->post_status != 'private') return $content; switch ($rss_content) { case 'excerpt_only': return apply_filters('the_excerpt_rss', get_the_excerpt(true)); break; case 'title_only': default: $permalink = get_permalink($post->ID); return "View the content of this awesome private post (probably about you!)"; break; } } // Called when using HTTP auth -- changes the post excerpt function postlevels_the_excerpt_rss($excerpt) { global $post, $rss_content; if ($post->post_status != 'private') return $excerpt; switch ($rss_content) { case 'excerpt_only': return $excerpt; break; case 'title_only': default: $permalink = get_permalink($post->ID); return "View the content of this awesome private post (probably about you!)"; break; } } // Gets the user level of the current user // If the user isn't logged in, returns null function postlevels_get_user_level() { if (!is_user_logged_in()) { return null; } global $user_ID, $postlevels_user_key; get_currentuserinfo(); $postlevels_current_user_level = get_usermeta($user_ID, $postlevels_user_key, true); // Only want numbers here if (($postlevels_current_user_level == '') || !is_numeric($postlevels_current_user_level)) { return get_option('postlevels_default_user_level'); } return intval($postlevels_current_user_level); } // Sets up the post levels admin menu function postlevels_admin_hook() { global $postlevels_post_key, $postlevels_user_key; if (function_exists('add_submenu_page')) { add_submenu_page('plugins.php', 'Post Levels Configuration', 'Post Levels Configuration', 8, __FILE__, 'postlevels_conf'); add_submenu_page('profile.php', 'User Levels', 'User Levels', 8, __FILE__, 'postlevels_users'); add_submenu_page('users.php', 'User Levels', 'User Levels', 8, __FILE__, 'postlevels_users'); } add_filter('manage_posts_columns', 'postlevels_add_column'); add_action('manage_posts_custom_column', 'postlevels_do_column'); add_action('simple_edit_form', 'postlevels_do_form'); add_action('edit_form_advanced', 'postlevels_do_form'); add_filter('status_save_pre', 'postlevels_status_save'); add_action('save_post', 'postlevels_post_save'); } // Called when a post is saved, updates the post level function postlevels_post_save($post_ID) { global $postlevels_post_key; $post = get_post($post_ID); $post_level = 4; if (($_POST['post_level'] != '') || ($post->post_status == 'private')) { // Private post with no post level gets default if ($_POST['post_level'] == '') { $post_level = get_option('postlevels_default_post_level'); } else { $post_level = $_POST['post_level']; } // Check if old value exists so we know whether to update or add $old_value = get_post_meta($post_ID, $postlevels_post_key, true); if ($old_value != '') { update_post_meta($post_ID, $postlevels_post_key, $post_level); } else { add_post_meta($post_ID, $postlevels_post_key, $post_level); } } } // Called before post status is updated on save. Marks // post as private if the post level is set function postlevels_status_save($post_status) { if (($_POST['post_level'] != '') && ($post_status == 'publish')) return 'private'; else return $post_status; } // Adds a post level column to manage post list function postlevels_add_column($posts_columns) { $posts_columns['post_level'] = 'Post Level'; return $posts_columns; } // Outputs the post level value for each post in the manage post list function postlevels_do_column($column_name) { global $postlevels_post_key; if ($column_name != 'post_level') return false; global $post; if ($post->post_status != 'private') { echo 'Public'; return true; } echo get_post_meta($post->ID, $postlevels_post_key, true); return true; } // Called during the edit form, outputs the post level drop down function postlevels_do_form() { global $post, $postlevels_post_key; echo '
'; echo '

Post Level

'; echo '
'; echo ''; echo '
'; } // Post Levels configuration page function postlevels_conf() { global $postlevels_user_key, $postlevels_post_key; ?>

Post Levels is a plugin that allows you to restrict access to your posts based upon the user's access level.

' . __('Options saved.') . '

'; } global $postlevels_post_key, $postlevels_user_key; $postlevels_post_key = get_option('postlevels_post_key'); $postlevels_user_key = get_option('postlevels_user_key'); if (isset($_POST['migrate'])) { if (($_POST['postlevels_migrate_user_levels'] == 1) && ($postlevels_user_key != 'wp_user_level')) { global $wpdb; $wpdb->query("DELETE FROM $wpdb->usermeta WHERE meta_key='$postlevels_user_key'"); $wpdb->query("INSERT INTO $wpdb->usermeta (user_id, meta_key, meta_value) SELECT user_id, '$postlevels_user_key', meta_value FROM $wpdb->usermeta WHERE meta_key = 'wp_user_level'"); echo '

' . __('User levels migrated to') . ' ' . $postlevels_user_key . '

'; } } ?>
Private Post Title Prefix:
What text gets prepended to the post title
Private Post Title Postfix:
What text gets appended to the post title
Default Post Level:
Posts marked Private have this level by default
Default User Level:
Users have this level by default
RSS Privacy:
For users reading RSS via HTTP authentication, this decides how much content should be shown
Advanced Options
Post Levels Meta Key:
Custom field used for tracking a post's level (for almost all users, the default is fine)
User Level Meta Key:
Custom field used for tracking a user's level (note: wp_user_level is also used internally by WordPress for permissions, use it with caution)

Migrating Levels

Old versions of PostLevels (0.2.1 and below) relied on the same user level values used for WordPress administration. This works fine, but can be awkward if you don't want your readers to be able to post, etc.

You are currently using wp_user_level as your user key, which is shared with WordPress for administration purposes. You should probably choose another value (such as postlevels_user_key) to avoid that conflict. Once you do so, you can have your level values ported over.

You can use the button below to port WordPress' user levels (stored in wp_user_level) to the meta key you've chosen (stored in ). This will clear any values you currently have in that key. This won't affect WordPress' administrative values though.

Migrate user levels

' . __('User levels changed for ') . count($userids) . ' ' . __('user(s)') . '

'; } else { echo '

' . __('No users updated (none checked)') . '

'; } } else { if(isset($_POST['update-user-levels'])) { echo '

' . __('No users updated (you must click the button below "Update User Levels")') . '

'; } } ?>

Manage User Levels

This page controls the level of each user, which determines what posts can and cannot be seen by that user.

get_col("SELECT ID FROM $wpdb->users;"); $users = array(); foreach($userids as $userid) { $users[$userid] = new WP_User($userid); } $style = ''; foreach ($users as $user_object) { $email = $user_object->user_email; $style = ('class="alternate"' == $style) ? '' : 'class="alternate"'; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } ?>
$email" . get_usermeta($user_object->ID, $postlevels_user_key) . "

Update User Levels

You are currently using wp_user_level as your user key, which is shared with WordPress for administration purposes. This means that changing a users' level will affect their Administrative powers. If you change your own level, you could lock yourself out of the system! You have been warned.