map_meta_cap

Map meta capabilities to primitive capabilities.

Description

(array) map_meta_cap( (string) $cap, (int) $user_id ); 

This does not actually compare whether the user ID has the actual capability, just what the capability or capabilities are. Meta capability list value can be delete_user,, edit_user., remove_user, promote_user, delete_post, 'delete_page', edit_post, edit_page, read_post, or read_page.

Returns (array)

Actual capabilities for meta capability.

Parameters (2)

0. $cap (string)
Capability name.
1. $user_id (int)
The user id.

Usage

  1. if ( !function_exists( 'map_meta_cap' ) ) { 
  2. require_once ABSPATH . WPINC . '/capabilities.php'; 
  3.  
  4. // Capability name. 
  5. $cap = ''; 
  6.  
  7. // The user id. 
  8. $user_id = -1; 
  9.  
  10. // NOTICE! Understand what this does before running. 
  11. $result = map_meta_cap($cap, $user_id); 
  12.  

Defined (1)

The function is defined in the following location(s).

/wp-includes/capabilities.php  
  1. function map_meta_cap( $cap, $user_id ) { 
  2. $args = array_slice( func_get_args(), 2 ); 
  3. $caps = array(); 
  4.  
  5. switch ( $cap ) { 
  6. case 'remove_user': 
  7. $caps[] = 'remove_users'; 
  8. break; 
  9. case 'promote_user': 
  10. case 'add_users': 
  11. $caps[] = 'promote_users'; 
  12. break; 
  13. case 'edit_user': 
  14. case 'edit_users': 
  15. // Allow user to edit itself 
  16. if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] ) 
  17. break; 
  18.  
  19. // In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin. 
  20. if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) { 
  21. $caps[] = 'do_not_allow'; 
  22. } else { 
  23. $caps[] = 'edit_users'; // edit_user maps to edit_users. 
  24. break; 
  25. case 'delete_post': 
  26. case 'delete_page': 
  27. $post = get_post( $args[0] ); 
  28. if ( ! $post ) { 
  29. $caps[] = 'do_not_allow'; 
  30. break; 
  31.  
  32. if ( 'revision' == $post->post_type ) { 
  33. $post = get_post( $post->post_parent ); 
  34. if ( ! $post ) { 
  35. $caps[] = 'do_not_allow'; 
  36. break; 
  37.  
  38. if ( ( get_option( 'page_for_posts' ) == $post->ID ) || ( get_option( 'page_on_front' ) == $post->ID ) ) { 
  39. $caps[] = 'manage_options'; 
  40. break; 
  41.  
  42. $post_type = get_post_type_object( $post->post_type ); 
  43. if ( ! $post_type ) { 
  44. /** translators: 1: post type, 2: capability name */ 
  45. _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); 
  46. $caps[] = 'edit_others_posts'; 
  47. break; 
  48.  
  49. if ( ! $post_type->map_meta_cap ) { 
  50. $caps[] = $post_type->cap->$cap; 
  51. // Prior to 3.1 we would re-call map_meta_cap here. 
  52. if ( 'delete_post' == $cap ) 
  53. $cap = $post_type->cap->$cap; 
  54. break; 
  55.  
  56. // If the post author is set and the user is the author... 
  57. if ( $post->post_author && $user_id == $post->post_author ) { 
  58. // If the post is published or scheduled... 
  59. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 
  60. $caps[] = $post_type->cap->delete_published_posts; 
  61. } elseif ( 'trash' == $post->post_status ) { 
  62. $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); 
  63. if ( in_array( $status, array( 'publish', 'future' ), true ) ) { 
  64. $caps[] = $post_type->cap->delete_published_posts; 
  65. } else { 
  66. $caps[] = $post_type->cap->delete_posts; 
  67. } else { 
  68. // If the post is draft... 
  69. $caps[] = $post_type->cap->delete_posts; 
  70. } else { 
  71. // The user is trying to edit someone else's post. 
  72. $caps[] = $post_type->cap->delete_others_posts; 
  73. // The post is published or scheduled, extra cap required. 
  74. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 
  75. $caps[] = $post_type->cap->delete_published_posts; 
  76. } elseif ( 'private' == $post->post_status ) { 
  77. $caps[] = $post_type->cap->delete_private_posts; 
  78. break; 
  79. // edit_post breaks down to edit_posts, edit_published_posts, or 
  80. // edit_others_posts 
  81. case 'edit_post': 
  82. case 'edit_page': 
  83. $post = get_post( $args[0] ); 
  84. if ( ! $post ) { 
  85. $caps[] = 'do_not_allow'; 
  86. break; 
  87.  
  88. if ( 'revision' == $post->post_type ) { 
  89. $post = get_post( $post->post_parent ); 
  90. if ( ! $post ) { 
  91. $caps[] = 'do_not_allow'; 
  92. break; 
  93.  
  94. $post_type = get_post_type_object( $post->post_type ); 
  95. if ( ! $post_type ) { 
  96. /** translators: 1: post type, 2: capability name */ 
  97. _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); 
  98. $caps[] = 'edit_others_posts'; 
  99. break; 
  100.  
  101. if ( ! $post_type->map_meta_cap ) { 
  102. $caps[] = $post_type->cap->$cap; 
  103. // Prior to 3.1 we would re-call map_meta_cap here. 
  104. if ( 'edit_post' == $cap ) 
  105. $cap = $post_type->cap->$cap; 
  106. break; 
  107.  
  108. // If the post author is set and the user is the author... 
  109. if ( $post->post_author && $user_id == $post->post_author ) { 
  110. // If the post is published or scheduled... 
  111. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 
  112. $caps[] = $post_type->cap->edit_published_posts; 
  113. } elseif ( 'trash' == $post->post_status ) { 
  114. $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); 
  115. if ( in_array( $status, array( 'publish', 'future' ), true ) ) { 
  116. $caps[] = $post_type->cap->edit_published_posts; 
  117. } else { 
  118. $caps[] = $post_type->cap->edit_posts; 
  119. } else { 
  120. // If the post is draft... 
  121. $caps[] = $post_type->cap->edit_posts; 
  122. } else { 
  123. // The user is trying to edit someone else's post. 
  124. $caps[] = $post_type->cap->edit_others_posts; 
  125. // The post is published or scheduled, extra cap required. 
  126. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 
  127. $caps[] = $post_type->cap->edit_published_posts; 
  128. } elseif ( 'private' == $post->post_status ) { 
  129. $caps[] = $post_type->cap->edit_private_posts; 
  130. break; 
  131. case 'read_post': 
  132. case 'read_page': 
  133. $post = get_post( $args[0] ); 
  134. if ( ! $post ) { 
  135. $caps[] = 'do_not_allow'; 
  136. break; 
  137.  
  138. if ( 'revision' == $post->post_type ) { 
  139. $post = get_post( $post->post_parent ); 
  140. if ( ! $post ) { 
  141. $caps[] = 'do_not_allow'; 
  142. break; 
  143.  
  144. $post_type = get_post_type_object( $post->post_type ); 
  145. if ( ! $post_type ) { 
  146. /** translators: 1: post type, 2: capability name */ 
  147. _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); 
  148. $caps[] = 'edit_others_posts'; 
  149. break; 
  150.  
  151. if ( ! $post_type->map_meta_cap ) { 
  152. $caps[] = $post_type->cap->$cap; 
  153. // Prior to 3.1 we would re-call map_meta_cap here. 
  154. if ( 'read_post' == $cap ) 
  155. $cap = $post_type->cap->$cap; 
  156. break; 
  157.  
  158. $status_obj = get_post_status_object( $post->post_status ); 
  159. if ( $status_obj->public ) { 
  160. $caps[] = $post_type->cap->read; 
  161. break; 
  162.  
  163. if ( $post->post_author && $user_id == $post->post_author ) { 
  164. $caps[] = $post_type->cap->read; 
  165. } elseif ( $status_obj->private ) { 
  166. $caps[] = $post_type->cap->read_private_posts; 
  167. } else { 
  168. $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); 
  169. break; 
  170. case 'publish_post': 
  171. $post = get_post( $args[0] ); 
  172. if ( ! $post ) { 
  173. $caps[] = 'do_not_allow'; 
  174. break; 
  175.  
  176. $post_type = get_post_type_object( $post->post_type ); 
  177. if ( ! $post_type ) { 
  178. /** translators: 1: post type, 2: capability name */ 
  179. _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); 
  180. $caps[] = 'edit_others_posts'; 
  181. break; 
  182.  
  183. $caps[] = $post_type->cap->publish_posts; 
  184. break; 
  185. case 'edit_post_meta': 
  186. case 'delete_post_meta': 
  187. case 'add_post_meta': 
  188. case 'edit_comment_meta': 
  189. case 'add_comment_meta': 
  190. case 'edit_term_meta': 
  191. case 'delete_term_meta': 
  192. case 'add_term_meta': 
  193. case 'edit_user_meta': 
  194. case 'delete_user_meta': 
  195. case 'add_user_meta': 
  196. list( $_, $object_type, $_ ) = explode( '_', $cap ); 
  197. $object_id = (int) $args[0]; 
  198.  
  199. switch ( $object_type ) { 
  200. case 'post': 
  201. $post = get_post( $object_id ); 
  202. if ( ! $post ) { 
  203. break; 
  204.  
  205. $sub_type = get_post_type( $post ); 
  206. break; 
  207.  
  208. case 'comment': 
  209. $comment = get_comment( $object_id ); 
  210. if ( ! $comment ) { 
  211. break; 
  212.  
  213. $sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type; 
  214. break; 
  215.  
  216. case 'term': 
  217. $term = get_term( $object_id ); 
  218. if ( ! $term ) { 
  219. break; 
  220.  
  221. $sub_type = $term->taxonomy; 
  222. break; 
  223.  
  224. case 'user': 
  225. $user = get_user_by( 'id', $object_id ); 
  226. if ( ! $user ) { 
  227. break; 
  228.  
  229. $sub_type = 'user'; 
  230. break; 
  231.  
  232. if ( empty( $sub_type ) ) { 
  233. $caps[] = 'do_not_allow'; 
  234. break; 
  235.  
  236. $caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id ); 
  237.  
  238. $meta_key = isset( $args[1] ) ? $args[1] : false; 
  239.  
  240. $has_filter = has_filter( "auth_{$object_type}_meta_{$meta_key}" ) || has_filter( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}" ); 
  241. if ( $meta_key && $has_filter ) { 
  242. /** This filter is documented in wp-includes/meta.php */ 
  243. $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", false, $meta_key, $object_id, $user_id, $cap, $caps ); 
  244.  
  245. /** This filter is documented in wp-includes/meta.php */ 
  246. $allowed = apply_filters( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps ); 
  247.  
  248. if ( ! $allowed ) { 
  249. $caps[] = $cap; 
  250. } elseif ( $meta_key && is_protected_meta( $meta_key, $object_type ) ) { 
  251. $caps[] = $cap; 
  252. break; 
  253. case 'edit_comment': 
  254. $comment = get_comment( $args[0] ); 
  255. if ( ! $comment ) { 
  256. $caps[] = 'do_not_allow'; 
  257. break; 
  258.  
  259. $post = get_post( $comment->comment_post_ID ); 
  260.  
  261. /** 
  262. * If the post doesn't exist, we have an orphaned comment. 
  263. * Fall back to the edit_posts capability, instead. 
  264. */ 
  265. if ( $post ) { 
  266. $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); 
  267. } else { 
  268. $caps = map_meta_cap( 'edit_posts', $user_id ); 
  269. break; 
  270. case 'unfiltered_upload': 
  271. if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) ) ) 
  272. $caps[] = $cap; 
  273. else 
  274. $caps[] = 'do_not_allow'; 
  275. break; 
  276. case 'edit_css' : 
  277. case 'unfiltered_html' : 
  278. // Disallow unfiltered_html for all users, even admins and super admins. 
  279. if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) 
  280. $caps[] = 'do_not_allow'; 
  281. elseif ( is_multisite() && ! is_super_admin( $user_id ) ) 
  282. $caps[] = 'do_not_allow'; 
  283. else 
  284. $caps[] = 'unfiltered_html'; 
  285. break; 
  286. case 'edit_files': 
  287. case 'edit_plugins': 
  288. case 'edit_themes': 
  289. // Disallow the file editors. 
  290. if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) 
  291. $caps[] = 'do_not_allow'; 
  292. elseif ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) 
  293. $caps[] = 'do_not_allow'; 
  294. elseif ( is_multisite() && ! is_super_admin( $user_id ) ) 
  295. $caps[] = 'do_not_allow'; 
  296. else 
  297. $caps[] = $cap; 
  298. break; 
  299. case 'update_plugins': 
  300. case 'delete_plugins': 
  301. case 'install_plugins': 
  302. case 'upload_plugins': 
  303. case 'update_themes': 
  304. case 'delete_themes': 
  305. case 'install_themes': 
  306. case 'upload_themes': 
  307. case 'update_core': 
  308. // Disallow anything that creates, deletes, or updates core, plugin, or theme files. 
  309. // Files in uploads are excepted. 
  310. if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) { 
  311. $caps[] = 'do_not_allow'; 
  312. } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { 
  313. $caps[] = 'do_not_allow'; 
  314. } elseif ( 'upload_themes' === $cap ) { 
  315. $caps[] = 'install_themes'; 
  316. } elseif ( 'upload_plugins' === $cap ) { 
  317. $caps[] = 'install_plugins'; 
  318. } else { 
  319. $caps[] = $cap; 
  320. break; 
  321. case 'activate_plugins': 
  322. $caps[] = $cap; 
  323. if ( is_multisite() ) { 
  324. // update_, install_, and delete_ are handled above with is_super_admin(). 
  325. $menu_perms = get_site_option( 'menu_items', array() ); 
  326. if ( empty( $menu_perms['plugins'] ) ) 
  327. $caps[] = 'manage_network_plugins'; 
  328. break; 
  329. case 'delete_user': 
  330. case 'delete_users': 
  331. // If multisite only super admins can delete users. 
  332. if ( is_multisite() && ! is_super_admin( $user_id ) ) 
  333. $caps[] = 'do_not_allow'; 
  334. else 
  335. $caps[] = 'delete_users'; // delete_user maps to delete_users. 
  336. break; 
  337. case 'create_users': 
  338. if ( !is_multisite() ) 
  339. $caps[] = $cap; 
  340. elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) ) 
  341. $caps[] = $cap; 
  342. else 
  343. $caps[] = 'do_not_allow'; 
  344. break; 
  345. case 'manage_links' : 
  346. if ( get_option( 'link_manager_enabled' ) ) 
  347. $caps[] = $cap; 
  348. else 
  349. $caps[] = 'do_not_allow'; 
  350. break; 
  351. case 'customize' : 
  352. $caps[] = 'edit_theme_options'; 
  353. break; 
  354. case 'delete_site': 
  355. $caps[] = 'manage_options'; 
  356. break; 
  357. case 'edit_term': 
  358. case 'delete_term': 
  359. case 'assign_term': 
  360. $term_id = (int) $args[0]; 
  361. $term = get_term( $term_id ); 
  362. if ( ! $term || is_wp_error( $term ) ) { 
  363. $caps[] = 'do_not_allow'; 
  364. break; 
  365.  
  366. $tax = get_taxonomy( $term->taxonomy ); 
  367. if ( ! $tax ) { 
  368. $caps[] = 'do_not_allow'; 
  369. break; 
  370.  
  371. if ( 'delete_term' === $cap && ( $term->term_id == get_option( 'default_' . $term->taxonomy ) ) ) { 
  372. $caps[] = 'do_not_allow'; 
  373. break; 
  374.  
  375. $taxo_cap = $cap . 's'; 
  376.  
  377. $caps = map_meta_cap( $tax->cap->$taxo_cap, $user_id, $term_id ); 
  378.  
  379. break; 
  380. case 'manage_post_tags': 
  381. case 'edit_categories': 
  382. case 'edit_post_tags': 
  383. case 'delete_categories': 
  384. case 'delete_post_tags': 
  385. $caps[] = 'manage_categories'; 
  386. break; 
  387. case 'assign_categories': 
  388. case 'assign_post_tags': 
  389. $caps[] = 'edit_posts'; 
  390. break; 
  391. case 'create_sites': 
  392. case 'delete_sites': 
  393. case 'manage_network': 
  394. case 'manage_sites': 
  395. case 'manage_network_users': 
  396. case 'manage_network_plugins': 
  397. case 'manage_network_themes': 
  398. case 'manage_network_options': 
  399. $caps[] = $cap; 
  400. break; 
  401. default: 
  402. // Handle meta capabilities for custom post types. 
  403. global $post_type_meta_caps; 
  404. if ( isset( $post_type_meta_caps[ $cap ] ) ) { 
  405. $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args ); 
  406. return call_user_func_array( 'map_meta_cap', $args ); 
  407.  
  408. // If no meta caps match, return the original cap. 
  409. $caps[] = $cap; 
  410.  
  411. /** 
  412. * Filters a user's capabilities depending on specific context and/or privilege. 
  413. * @since 2.8.0 
  414. * @param array $caps Returns the user's actual capabilities. 
  415. * @param string $cap Capability name. 
  416. * @param int $user_id The user ID. 
  417. * @param array $args Adds the context to the cap. Typically the object ID. 
  418. */ 
  419. return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );