Skip to content

Instantly share code, notes, and snippets.

@rickalday
Created November 7, 2025 23:01
Show Gist options
  • Select an option

  • Save rickalday/1a9baff2500927784e2c32f1466b0839 to your computer and use it in GitHub Desktop.

Select an option

Save rickalday/1a9baff2500927784e2c32f1466b0839 to your computer and use it in GitHub Desktop.
Restrict Editor role to Give Campaing Pages only
<?php
/**
* Allow editors to edit/delete ONLY pages that have the give_campaign_id meta key.
*/
/**
* Map meta caps so editors may only edit/delete posts that have give_campaign_id.
*
* @param array $caps Mapped capabilities to return.
* @param string $cap Capability being checked.
* @param int $user_id User ID.
* @param array $args Additional args (for edit_post/delete_post, $args[0] is post ID).
* @return array
*/
function allow_editors_only_give_campaign_map_meta_cap( $caps, $cap, $user_id, $args ) {
// Only care about edit/delete capabilities for posts/pages.
$targets = array( 'edit_post', 'delete_post', 'edit_page', 'delete_page' );
if ( ! in_array( $cap, $targets, true ) ) {
return $caps;
}
// Need a post ID to decide.
$post_id = isset( $args[0] ) ? intval( $args[0] ) : 0;
if ( ! $post_id ) {
return $caps;
}
// Allow administrators and other high-cap users to behave normally.
if ( user_can( $user_id, 'manage_options' ) ) {
return $caps;
}
// Load the user and check for the editor role.
$user = get_userdata( $user_id );
if ( ! $user ) {
return $caps;
}
// If the user is an editor, enforce restriction: only allow when meta exists.
if ( in_array( 'editor', (array) $user->roles, true ) ) {
$val = get_post_meta( $post_id, 'give_campaign_id', true );
if ( $val === '' || $val === null ) {
// No campaign meta — deny.
return array( 'do_not_allow' );
}
// Meta exists — allow. Return original $caps (no change).
}
return $caps;
}
add_filter( 'map_meta_cap', 'allow_editors_only_give_campaign_map_meta_cap', 10, 4 );
/**
* Prevent editors from opening the edit screen for pages that do NOT have give_campaign_id.
* (Extra guard for direct URL access.)
*/
function allow_editors_only_give_campaign_block_edit_screen() {
if ( ! is_admin() ) {
return;
}
// Only run for the post edit screen (post.php). We intentionally allow post-new.php.
$pagenow = basename( $_SERVER['PHP_SELF'] );
if ( 'post.php' !== $pagenow ) {
return;
}
if ( ! is_user_logged_in() ) {
return;
}
$current_user = wp_get_current_user();
if ( ! in_array( 'editor', (array) $current_user->roles, true ) ) {
return;
}
$post_id = isset( $_GET['post'] ) ? intval( $_GET['post'] ) : 0;
if ( ! $post_id ) {
return;
}
$val = get_post_meta( $post_id, 'give_campaign_id', true );
if ( $val === '' || $val === null ) {
// Redirect back to the pages list with a notice.
$redirect = add_query_arg(
array(
'post_type' => get_post_type( $post_id ),
'restricted_by' => 'give_campaign_only',
),
admin_url( 'edit.php' )
);
wp_safe_redirect( $redirect );
exit;
}
}
add_action( 'admin_init', 'allow_editors_only_give_campaign_block_edit_screen' );
/**
* Admin notice when redirected due to restriction.
*/
function allow_editors_only_give_campaign_admin_notice() {
if ( ! current_user_can( 'editor' ) ) {
return;
}
if ( isset( $_GET['restricted_by'] ) && 'give_campaign_only' === $_GET['restricted_by'] ) {
echo '<div class="notice notice-error is-dismissible"><p>';
echo esc_html__( 'You can only edit pages that are associated with a campaign.', 'your-textdomain' );
echo '</p></div>';
}
}
add_action( 'admin_notices', 'allow_editors_only_give_campaign_admin_notice' );
/**
* Optional: restrict the Pages list so editors only see pages that have give_campaign_id.
* Remove this function if you prefer editors to still see the full list but be blocked when they attempt edits.
*/
function allow_editors_only_give_campaign_pre_get_posts( $query ) {
if ( ! is_admin() || ! $query->is_main_query() ) {
return;
}
// Only apply on the Pages admin list.
$pagenow = basename( $_SERVER['PHP_SELF'] );
if ( 'edit.php' !== $pagenow || $query->get( 'post_type' ) !== 'page' ) {
return;
}
if ( ! current_user_can( 'editor' ) ) {
return;
}
// Only show pages that have the meta key give_campaign_id.
$meta_query = array(
array(
'key' => 'give_campaign_id',
'compare' => 'EXISTS',
),
);
$query->set( 'meta_query', $meta_query );
}
add_action( 'pre_get_posts', 'allow_editors_only_give_campaign_pre_get_posts' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment