WordPress plugin that allow user to “edit_others_posts” to save only, not publish
<?php | |
/** | |
* Plugin Name: WPSE 161061 | |
* Description: Allow user to “edit_others_posts” to save only, not publish | |
* Plugin URI: http://wordpress.stackexchange.com/questions/161061/ | |
* Author: Giuseppe Mazzapica | |
* Author URI: http://gm.zoomlab.it | |
* License: GPLv3 | |
* Version: 1.0.0 | |
* | |
*/ | |
/* | |
Copyright (C) 2014 Giuseppe Mazzapica | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
class CustomEditorRole { | |
private static $role = 'authorplus'; | |
private $role_label; | |
function __construct() { | |
// here we need a real, loaded, text domain | |
$this->role_label = __( 'Author +', 'yout-txt-dmn' ); | |
} | |
function addRole() { | |
global $wp_roles; | |
if ( ! $wp_roles instanceof WP_Roles ) { | |
$wp_roles = new WP_Roles; | |
} | |
$author = get_role( 'author' ); | |
$caps = $author->capabilities; // start with author capabilities | |
$caps['publish_posts'] = FALSE; | |
$caps['edit_published_posts'] = FALSE; | |
$caps['delete_published_posts'] = FALSE; | |
$caps['edit_others_pending_posts'] = TRUE; // custom cap | |
// create new role with custom caps | |
add_role( self::$role, $this->role_label, $caps ); | |
} | |
function removeRole() { | |
global $wp_roles; | |
if ( ! $wp_roles instanceof WP_Roles ) { | |
$wp_roles = new WP_Roles; | |
} | |
remove_role(self::$role); | |
} | |
} | |
class CustomEditorCaps { | |
function manageCaps( $allcaps, $caps, $args, $user ) { | |
if ( ! $this->shouldManage( $args[0], $user ) ) { | |
return $allcaps; | |
} | |
// Are we saving? | |
$action = filter_input( INPUT_POST, 'action', FILTER_SANITIZE_STRING ); | |
$method = strtoupper(filter_var($_SERVER['REQUEST_METHOD'], FILTER_SANITIZE_STRING )); | |
if ( $method !== 'POST' ) { // not saving | |
global $pagenow; | |
// we are interested only on post list and post edit screens | |
if ( | |
is_admin() | |
&& in_array( $pagenow, array( 'post.php', 'post-new.php', 'edit.php' ), TRUE | |
) ) { | |
$screen_id = $pagenow === 'edit.php' ? 'edit-post' : 'post'; | |
$allcaps = $this->maybeAllow( $args, $allcaps, $user, $screen_id ); | |
} | |
} elseif ( $action === 'editpost' ) { // saving and right action | |
$allcaps = $this->maybeAllowOnSave( $args, $allcaps, $user ); | |
} | |
return $allcaps; // always return: it's a filter | |
} | |
function allowPreview( $posts, $query ) { | |
if ( is_admin() | |
|| ! $query->is_main_query() | |
|| empty( $posts ) | |
|| ! $query->is_single | |
|| $posts[0]->post_type !== 'post' | |
) { | |
return $posts; // return first argument: it's a filter | |
} | |
$status = get_post_status( $posts[0] ); | |
$post_status_obj = get_post_status_object( $status ); | |
if ( | |
! $post_status_obj->public | |
&& $status === 'pending' | |
&& current_user_can('edit_others_pending_posts') | |
) { | |
// post is pending and our user has our special role | |
// allow preview | |
global $wp_post_statuses; | |
$wp_post_statuses[$status]->public = TRUE; | |
} | |
return $posts; // return first argument: it's a filter | |
} | |
private function maybeAllow( $args, $allcaps, $user, $screen ) { | |
if ( $args[0] === 'edit_others_posts' ) { | |
// if filtering 'edit_others_posts' we have no access to single post data | |
// allow cap only on post list screen and before querying posts | |
$allcaps['edit_others_posts'] = ! did_action('pre_get_posts') | |
&& $screen === 'edit-post'; | |
return $allcaps; | |
} | |
$post = get_post( $args[2] ); | |
if ( $post->post_status === 'pending' ) { | |
$allcaps['edit_others_posts'] = TRUE; | |
} | |
return $allcaps; // always return: it's a filter | |
} | |
private function maybeAllowOnSave( $args, $allcaps, $user ) { | |
$data = $this->getPostedData(); | |
if ( $data['post_type'] !== 'post' || (int) $data['post_ID'] <= 0 ) { | |
return $allcaps; | |
} | |
$post = get_post( $data['post_ID'] ); | |
if ( | |
$post->post_status === 'pending' | |
&& $data['original_post_status'] === 'pending' | |
&& ( empty( $data['post_status'] ) || $data['post_status'] === 'pending' ) | |
) { | |
// if post is pending and will stay pending allow editing | |
$allcaps['edit_others_posts'] = true; | |
} | |
return $allcaps; | |
} | |
private function shouldManage( $cap, $user ) { | |
return is_admin() // not affect frontend | |
&& in_array( $cap, array( 'edit_others_posts', 'edit_post' ), TRUE ) | |
&& ! $user->has_cap( 'delete_others_posts' ) // real editor or more | |
&& $user->has_cap( 'edit_others_pending_posts' ) // our role | |
&& ! defined( 'DOING_AJAX' ); // does not affect ajax | |
} | |
private function getPostedData() { | |
return filter_input_array( INPUT_POST, array( | |
'post_type' => FILTER_SANITIZE_STRING, | |
'post_ID' => FILTER_SANITIZE_NUMBER_INT, | |
'original_post_status' => FILTER_SANITIZE_STRING, | |
'post_status' => FILTER_SANITIZE_STRING, | |
) ); | |
} | |
} | |
register_activation_hook( __FILE__, array( new CustomEditorRole, 'addRole' ) ); | |
register_deactivation_hook( __FILE__, array( new CustomEditorRole, 'removeRole' ) ); | |
$cap_manager = new CustomEditorCaps; | |
add_filter( 'user_has_cap', array( $cap_manager, 'manageCaps' ), PHP_INT_MAX, 4 ); | |
add_filter( 'posts_results', array( $cap_manager, 'allowPreview' ), 10, 2 ); | |
add_filter( 'wp_insert_post_data', array( $cap_manager, 'lockPendingStatus' ), 10, 2 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Hi Giuseppe,
I downloaded this plugin because I'm trying to achieve exactly the same thing as the OP here - for which I think you developed this.
However, when I assign a user to the "Author+" category, that user doesn't have the ability to edit other members' posts. Am I missing something? Is this due to a recent update of WP?