Temporary capability for current_user_can()

Is it possible to intercept calls to current_user_can() ?

Example:

Read More

current_user_can('rate', $post_id)

There’s no “rate” capability registered, but could I somehow hook into that function and do my own checks, without having to register a role capability?

Related posts

Leave a Reply

1 comment

  1. Yes, just filter 'user_has_cap'. You get an array with the current capabilities that you can change without touching the database.

    Sample Code

    add_filter( 'user_has_cap', 'wpse_53230_catch_cap', 10, 3 );
    
    /**
     * See WP_User::has_cap() in wp-includes/capabilities.php
     *
     * @param  array  $allcaps Existing capabilities for the user
     * @param  string $caps    Capabilities provided by map_meta_cap()
     * @param  array  $args    Arguments for current_user_can()
     * @return array
     */
    function wpse_53230_catch_cap( $allcaps, $caps, $args )
    {
    
      // $args[2] is the post ID
      if($args[0] !== 'beat_chuck_norris' || !isset($args[2]) || !my_checks($args[2]))
        return $allcaps;
    
      $allcaps['beat_chuck_norris'] = 1;
    
      return $allcaps;
    }
    
    
    function my_checks($post_id){
      // here check if the current user can rate this post
      return true;
    } 
    

    Test

    current_user_can( 'beat_chuck_norris', get_the_ID() )
        and print 'The current user can beat Chuck Norris. Be nice to her!';
    

    Handle super-admins

    add_filter('map_meta_cap', 'wpse_53230_catch_cap_for_sa', 10, 4);
    
    function wpse_53230_catch_cap_for_sa($caps, $req_cap, $user_id, $args){
    
      if(is_multisite() 
          && is_super_admin($user_id)
          && ($req_cap === 'beat_chuck_norris')
          && !empty($args[0]) // here post ID is $args[0]
          && !my_checks($args[0])
        ){
             $caps[] = 'do_not_allow';
         }      
    
      return $caps;    
    }