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; 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'); // 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(); // 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); $rewrite_rss = get_option('postlevels_rewrite_rss_link'); if ($rewrite_rss == 1) { add_filter('feed_link', 'postlevels_feed_link'); } // 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', 'postlevels_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'); add_option('postlevels_rewrite_rss_link', '1', "Whether links to RSS feeds should be rewritten to use HTTP authentication for logged in users", '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, $postlevels_user_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], $postlevels_user_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; } } // Rewrites RSS feed links to support http authentication // if the user is logged in function postlevels_feed_link($output) { $delim = (strpos('?', $output) === false) ? '?' : '&'; return $output . $delim . 'http_auth=yes'; } // 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 '
'; } // Post Levels configuration page function postlevels_conf() { global $postlevels_user_key, $postlevels_post_key; global $table_prefix; $default_user_key = $table_prefix . 'user_level'; ?>Post Levels is a plugin that allows you to restrict access to your posts based upon the user's access level.
' . __('Options saved.') . '
' . __('User levels migrated to') . ' ' . $postlevels_user_key . '
' . __('User levels changed for ') . count($userids) . ' ' . __('user(s)') . '
'; } else { echo '' . __('No users updated (none checked)') . '
' . __('No users updated (you must click the button below "Update User Levels")') . '
This page controls the level of each user, which determines what posts can and cannot be seen by that user.