/** * Conditional tag to check if a user can view a specific post. A user cannot view a post if their * user role has not been selected in the 'Content Permissions' meta box on the edit post screen in * the admin. Non-logged in site visitors cannot view posts if roles were selected. If no roles * were selected, all users and site visitors can view the content. * * There are exceptions to this rule though. The post author, any user with the `restrict_content` * capability, and users that have the ability to edit the post can always view the post, even if * their role was not granted permission to view it. * * @since 0.2.0 * @access public * @param int $user_id * @param int $post_id * @return bool */ function members_can_user_view_post($user_id, $post_id = '') { // If no post ID is given, assume we're in The Loop and get the current post's ID. if (!$post_id) { $post_id = get_the_ID(); } // Assume the user can view the post at this point. */ $can_view = true; // The plugin is only going to handle permissions if the 'content permissions' feature // is active. If not active, the user can always view the post. However, developers // can roll their own handling of this and filter `members_can_user_view_post`. if (members_content_permissions_enabled()) { // Get the roles selected by the user. $roles = members_get_post_roles($post_id); // Check if there are any old roles with the '_role' meta key. if (empty($roles)) { $roles = members_convert_old_post_meta($post_id); } // If we have an array of roles, let's get to work. if (!empty($roles) && is_array($roles)) { // Since specific roles were given, let's assume the user can't view // the post at this point. The rest of this functionality should try // to disprove this. $can_view = false; // Get the post object. $post = get_post($post_id); // Get the post type object. $post_type = get_post_type_object($post->post_type); // If viewing a feed or if the user's not logged in, assume it's blocked at this point. if (is_feed() || !is_user_logged_in()) { $can_view = false; } elseif ($post->post_author == $user_id || user_can($user_id, 'restrict_content') || user_can($user_id, $post_type->cap->edit_post, $post_id)) { $can_view = true; } else { // Loop through each role and set $can_view to true if the user has one of the roles. foreach ($roles as $role) { if (members_user_has_role($user_id, $role)) { $can_view = true; break; } } } } } // Set the check for the parent post based on whether we have permissions for this post. $check_parent = empty($roles) && $can_view; // Set to `FALSE` to avoid hierarchical checking. if (apply_filters('members_check_parent_post_permission', $check_parent, $post_id, $user_id)) { $parent_id = get_post($post_id)->post_parent; // If the post has a parent, check if the user has permission to view it. if (0 < $parent_id) { $can_view = members_can_user_view_post($user_id, $parent_id); } } // Allow developers to overwrite the final return value. return apply_filters('members_can_user_view_post', $can_view, $user_id, $post_id); }
/** * Conditional tag to check if a user can view a specific post. A user cannot view a post if their user role has * not been selected in the 'Content Permissions' meta box on the edit post screen in the admin. Non-logged in * site visitors cannot view posts if roles were seletected. If no roles were selected, all users and site visitors * can view the content. * * There are exceptions to this rule though. The post author, any user with the 'restrict_content' capability, * and users that have the ability to edit the post can always view the post, even if their role was not granted * permission to view it. * * @todo See how feasible it is to just use the normal user_can() NXTClass function to check against a meta * capability such as 'members_view_post' while hooking into 'map_meta_cap' or 'user_has_cap' to roll custom * plugin handling for this. This would just be a wrapper tag. * * @since 0.2.0 * @param int $user_id The ID of the user to check. * @param int $post_id The ID of the post to check. * @return bool True if the user can view the post. False if the user cannot view the post. */ function members_can_user_view_post($user_id, $post_id = '') { /* If no post ID is given, assume we're in The Loop and get the current post's ID. */ if (empty($post_id)) { $post_id = get_the_ID(); } /* Assume the user can view the post at this point. */ $can_view = true; /** * The plugin is only going to handle permissions if the 'content permissions' feature is active. If * not active, the user can always view the post. However, developers can roll their own handling of * this and filter 'members_can_user_view_post'. */ if (members_get_setting('content_permissions')) { /* Get the roles selected by the user. */ $roles = get_post_meta($post_id, '_members_access_role', false); /* Check if there are any old roles with the '_role' meta key. */ if (empty($roles)) { $roles = members_convert_old_post_meta($post_id); } /* If we have an array of roles, let's get to work. */ if (!empty($roles) && is_array($roles)) { /** * Since specific roles were given, let's assume the user can't view the post at * this point. The rest of this functionality should try to disprove this. */ $can_view = false; /* Get the post object. */ $post = get_post($post_id); /* Get the post type object. */ $post_type = get_post_type_object($post->post_type); /* If viewing a feed or if the user's not logged in, assume it's blocked at this point. */ if (is_feed() || !is_user_logged_in()) { $can_view = false; } elseif ($post->post_author == $user_id || user_can($user_id, 'restrict_content') || user_can($user_id, $post_type->cap->edit_post, $post_id)) { $can_view = true; } else { /* Loop through each role and set $can_view to true if the user has one of the roles. */ foreach ($roles as $role) { if (user_can($user_id, $role)) { $can_view = true; } } } } } /* Allow developers to overwrite the final return value. */ return apply_filters('members_can_user_view_post', $can_view, $user_id, $post_id); }
/** * Outputs the meta box HTML. * * @since 1.0.0 * @access public * @param object $post * @global object $wp_roles * @return void */ public function meta_box($post) { global $wp_roles; // Get roles and sort. $_wp_roles = $wp_roles->role_names; asort($_wp_roles); // Get the roles saved for the post. $roles = get_post_meta($post->ID, '_members_access_role', false); // Convert old post meta to the new system if no roles were found. if (empty($roles)) { $roles = members_convert_old_post_meta($post->ID); } wp_nonce_field('members_cp_meta_nonce', 'members_cp_meta'); ?> <p> <?php esc_html_e("Limit access to this post's content to users of the selected roles.", 'members'); ?> </p> <div class="members-cp-role-list-wrap"> <ul class="members-cp-role-list"> <?php foreach ($_wp_roles as $role => $name) { ?> <li> <label> <input type="checkbox" name="members_access_role[]" <?php checked(is_array($roles) && in_array($role, $roles)); ?> value="<?php echo esc_attr($role); ?> " /> <?php echo esc_html(translate_user_role($name)); ?> </label> </li> <?php } ?> </ul> </div> <p class="howto"> <?php printf(esc_html__('If no roles are selected, everyone can view the content. The post author, any users who can edit this post, and users with the %s capability can view the content regardless of role.', 'members'), '<code>restrict_content</code>'); ?> </p> <p> <label for="members_access_error"><?php esc_html_e('Custom error messsage:', 'members'); ?> </label> <textarea class="widefat" id="members_access_error" name="members_access_error" rows="6"><?php echo esc_textarea(get_post_meta($post->ID, '_members_access_error', true)); ?> </textarea> <span class="howto"><?php _e('Message shown to users that do no have permission to view the post.', 'members'); ?> </span> </p> <?php }
/** * @since 0.1.0 */ function members_content_permissions_meta_box($object, $box) { global $wp_roles; /* Get the roles saved for the post. */ $roles = get_post_meta($object->ID, '_members_access_role', false); /* Convert old post meta to the new system if no roles were found. */ if (empty($roles)) { $roles = members_convert_old_post_meta($object->ID); } ?> <input type="hidden" name="content_permissions_meta_nonce" value="<?php echo wp_create_nonce(plugin_basename(__FILE__)); ?> " /> <div style="overflow: hidden; margin-left: 5px;"> <p> <?php _e("Limit access to this post's content to users of the selected roles.", 'members'); ?> </p> <?php /* Loop through each of the available roles. */ foreach ($wp_roles->role_names as $role => $name) { $checked = false; /* If the role has been selected, make sure it's checked. */ if (is_array($roles) && in_array($role, $roles)) { $checked = ' checked="checked" '; } ?> <div style="width: 32%; float: left; margin: 0 0 5px 0;"> <label for="members_access_role-<?php echo $role; ?> "> <input type="checkbox" name="members_access_role[<?php echo $role; ?> ]" id="members_access_role-<?php echo $role; ?> " <?php echo $checked; ?> value="<?php echo $role; ?> " /> <?php echo esc_html($name); ?> </label> </div> <?php } ?> </div> <p style="clear: left;"> <span class="howto"><?php printf(__('If no roles are selected, everyone can view the content. The post author, any users who can edit this post, and users with the %s capability can view the content regardless of role.', 'members'), '<code>restrict_content</code>'); ?> </span> </p> <p> <label for="members_access_error"><?php _e('Custom error messsage:', 'members'); ?> </label> <textarea id="members_access_error" name="members_access_error" cols="60" rows="2" tabindex="30" style="width: 99%;"><?php echo esc_html(get_post_meta($object->ID, '_members_access_error', true)); ?> </textarea> <br /> <span class="howto"><?php _e('Message shown to users that do no have permission to view the post.', 'members'); ?> </span> </p> <?php }