0

I've tried to make a script that only allows a specific user to edit a specific page but without any success.

The idea behind, is that if a users username contains a specific word, they are allowed to edit a special page.

I've tried to do this, by granting the specific users a special capability, and then checking that capability when opening the special page.

Here's my code:

add_action( 'admin_init', function() {
    $current_user = wp_get_current_user();
    $user_login = $current_user->data->user_login;

    if( strpos($user_login, '@special-domain.com') !== false ) {
        $user = new WP_User($current_user->ID);
        $user->add_cap('edit_special_page');
    }
});

add_filter( 'map_meta_cap', function( $caps, $cap, $user_id, $args ) {
    if ( 'edit_page' == $cap && user_can( $user_id, 'edit_special_page' ) )
    {
        $post_id = $args[0];
        $special_page_id = get_page_by_path('special-page') ? get_page_by_path('special-page')->ID : null;

        if ( special_page_id == $post_id ) {
            $caps = [];
            $caps[] = 'edit_special_page';
        }
    }
    return $caps;
}, 10, 4 );

But all users can still edit to the special page, which should only be possible for users with @special-domain.com in their usernames. I've also tried to use the post-id directly instead of $special_page_id, but with the same result.

Any idea why this is not working and how to do it?

PS: I am NOT interested in any kind of plugins.

0

The issue is that an empty return value from map_meta_cap will grant all users permission to do that thing, because that's essentially the same thing as saying "no capabilities are required to do this". What you really want to do is just add edit_special_page to the existing list of required capabilities:

add_filter( 'map_meta_cap', function( $caps, $cap, $user_id, $args ) {
    if ( 'edit_post' === $cap || 'edit_page' === $cap ) {
        $current_page_id = $args[0];
        $special_page_id = get_page_by_path( 'special-page' ) ? get_page_by_path( 'special-page' )->ID : null;

        // If the page being edited is the special page...
        if ( $special_page_id === $current_page_id ) {
            // ... the user must have the edit_special_page capability.
            $caps[] = 'edit_special_page';
        }
    }

    return $caps;
}, 10, 4 );

An unrelated issue, but something that you'll need to address, is that you shouldn't add capabilities on admin_init or init. Adding capabilities writes to the database, so its only something that should be done once of plugin/theme activation or when the user is registered:

add_action( 'user_register', function( $user_id ) {
    $user = get_userdata( $user_id );

    if ( strpos( $user->user_login, '@special-domain.com' ) !== false ) {
        $user->add_cap( 'edit_special_page' );
    }
} );
  • Thanks for your help. But all users still have access and can make edits to the special page. If I try to print_r($cap), I can a large list of capabilities, but 'edit-page' is not one of them – Jesper Jul 15 at 12:18
  • Where are you printing it? You're only going to see edit_page if that capability is currently being checked. – Jacob Peattie Jul 15 at 12:37
  • I'm printing it on the post-edit page. – Jesper Jul 16 at 6:16
  • I've updated my answer. In some cases WordPress core checks the edit_post meta capability, regardless of the post type, so you'll need to apply the check for that capability too. – Jacob Peattie Jul 16 at 6:25
  • Than you very much. Now it seems to work perfectly :) – Jesper Jul 16 at 7:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.