I've been digging into the map_meta_cap filter since I need to extend the user's capabilities based on context, in certain situations. This is working well but in my traces I noticed something odd about the way $args show up at the callback function. Here's my filter registration (inside a class):

add_filter( 'map_meta_cap', array(&$this, 'post_map_meta_cap'), 10, 4 );

and here's the callback function definition that goes with it:

public function post_map_meta_cap( $caps, $cap, $user_id, $args ) {
    error_log("Filter fired:  ------>  meta_cap args:  " . json_encode($args));

Now, I'm on the admin page that shows all of my custom post types listed, and about to click on "edit" for one of the posts (id number 6). Here's the trace:

on page: edit.php?post_type=my_custom_post_type
click on edit post id 6
Filter fired:  map_meta_cap:  ------>  meta_cap args:  [6]
Filter fired:  admin_enqueue_scripts
Filter fired:  admin_head
Filter fired:  in_admin_header
Filter fired:  admin_bar_menu
Filter fired:  wp_before_admin_bar_render
Filter fired:  wp_after_admin_bar_render
Filter fired:  map_meta_cap:  ------>  meta_cap args:  ["6"]
Filter fired:  in_admin_footer
Filter fired:  admin_footer_text
Filter fired:  admin_footer
Filter fired:  admin_print_footer_scripts
on page:  post.php?post=6&action=edit

I'm writing the value of $args with this:


which is a quick/easy way to get any object to be readable in a trace/log.

So, what I found odd is that as you can see the first time the filter is fired the $args array has one element which is an integer, 6. The second time it fires the array has one element and is a string, "6".

I'm casting the result to integer just to be safe, now that I see this -- but I was wondering why it does this? Do we expect the post id to sometimes be an integer and sometimes be a string?


The map_meta_cap function handles context arguments generically - you can give it anything and it'll happily pass it down the chain. It's only particular capabilities like edit_post that expect the argument to be an integer, but even then it's up to the caller to pass an appropriate value.

Here's where you get your string/integer mashups - usually the caller will pass the ID straight from a WP_Post object, but it could be from anywhere - another database call, another object that has a reference to a post ID, hardcoded etc. In other words, lots of opportunities for a string to slip through.

You can try a debug_backtrace on your tests to find the culprits, but there are more important things in life to get on with - stick to your int type-casting and carry on coding ;)

  • Thanks, this makes sense. This particular filter is not really well documented so I wasn't sure what was going on. – C C Nov 27 '15 at 15:37

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.