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', '', "Default text placed after the title of a private post", 'yes'); } // Left join with the custom fields table so we can filter // based on level in the where clause function postlevels_posts_join($join, $force = false) { return $join; // Don't do this for a page, since it breaks the SQL if (is_page() && !$force) return $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, $force = false) { return $where; // Single page query doesn't check for published vs. private if (is_page() && !$force) return $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); } // Edit the many SQL queries that do not have specific filters // This is almost guaranteed to break some day function postlevels_query($sql) { global $postlevels_current_user_level, $postlevels_post_key, $wpdb; // Hack, for now if (strpos($sql, "post_status = 'publish'") !== false) { if (strpos($sql, "post2cat") !== false) { $sql = str_replace(" post_id", " {$wpdb->post2cat}.post_id", $sql); } $sql = str_replace(" {$wpdb->posts} ", " {$wpdb->posts} LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id ", $sql); $sql = 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 )))", $sql); } return $sql; } // 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 certain // capabilities. Ignore all other calls into here. if (!in_array('read_private_posts', $caps) && !in_array('read_private_pages', $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_post 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 // UPDATE: WP 2.1 has read_private_pages // 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 capabilities $allcaps['read_private_posts'] = $allcaps['read_private_pages'] = ($user_level >= $post_level); return $allcaps; } // 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; } } // 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('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_page_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); 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 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.