capabilities.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. <?php
  2. /**
  3. * Core User Role & Capabilities API
  4. *
  5. * @package WordPress
  6. * @subpackage Users
  7. */
  8. /**
  9. * Map meta capabilities to primitive capabilities.
  10. *
  11. * This does not actually compare whether the user ID has the actual capability,
  12. * just what the capability or capabilities are. Meta capability list value can
  13. * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post',
  14. * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'.
  15. *
  16. * @since 2.0.0
  17. *
  18. * @global array $post_type_meta_caps Used to get post type meta capabilities.
  19. *
  20. * @param string $cap Capability name.
  21. * @param int $user_id User ID.
  22. * @param int $object_id Optional. ID of the specific object to check against if `$cap` is a "meta" cap.
  23. * "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
  24. * by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
  25. * 'edit_others_posts', etc. The parameter is accessed via func_get_args().
  26. * @return array Actual capabilities for meta capability.
  27. */
  28. function map_meta_cap( $cap, $user_id ) {
  29. $args = array_slice( func_get_args(), 2 );
  30. $caps = array();
  31. switch ( $cap ) {
  32. case 'remove_user':
  33. // In multisite the user must be a super admin to remove themselves.
  34. if ( isset( $args[0] ) && $user_id == $args[0] && ! is_super_admin( $user_id ) ) {
  35. $caps[] = 'do_not_allow';
  36. } else {
  37. $caps[] = 'remove_users';
  38. }
  39. break;
  40. case 'promote_user':
  41. case 'add_users':
  42. $caps[] = 'promote_users';
  43. break;
  44. case 'edit_user':
  45. case 'edit_users':
  46. // Allow user to edit itself
  47. if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] )
  48. break;
  49. // In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin.
  50. if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) {
  51. $caps[] = 'do_not_allow';
  52. } else {
  53. $caps[] = 'edit_users'; // edit_user maps to edit_users.
  54. }
  55. break;
  56. case 'delete_post':
  57. case 'delete_page':
  58. $post = get_post( $args[0] );
  59. if ( ! $post ) {
  60. $caps[] = 'do_not_allow';
  61. break;
  62. }
  63. if ( 'revision' == $post->post_type ) {
  64. $post = get_post( $post->post_parent );
  65. if ( ! $post ) {
  66. $caps[] = 'do_not_allow';
  67. break;
  68. }
  69. }
  70. if ( ( get_option( 'page_for_posts' ) == $post->ID ) || ( get_option( 'page_on_front' ) == $post->ID ) ) {
  71. $caps[] = 'manage_options';
  72. break;
  73. }
  74. $post_type = get_post_type_object( $post->post_type );
  75. if ( ! $post_type ) {
  76. /* translators: 1: post type, 2: capability name */
  77. _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' );
  78. $caps[] = 'edit_others_posts';
  79. break;
  80. }
  81. if ( ! $post_type->map_meta_cap ) {
  82. $caps[] = $post_type->cap->$cap;
  83. // Prior to 3.1 we would re-call map_meta_cap here.
  84. if ( 'delete_post' == $cap )
  85. $cap = $post_type->cap->$cap;
  86. break;
  87. }
  88. // If the post author is set and the user is the author...
  89. if ( $post->post_author && $user_id == $post->post_author ) {
  90. // If the post is published or scheduled...
  91. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  92. $caps[] = $post_type->cap->delete_published_posts;
  93. } elseif ( 'trash' == $post->post_status ) {
  94. $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
  95. if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
  96. $caps[] = $post_type->cap->delete_published_posts;
  97. } else {
  98. $caps[] = $post_type->cap->delete_posts;
  99. }
  100. } else {
  101. // If the post is draft...
  102. $caps[] = $post_type->cap->delete_posts;
  103. }
  104. } else {
  105. // The user is trying to edit someone else's post.
  106. $caps[] = $post_type->cap->delete_others_posts;
  107. // The post is published or scheduled, extra cap required.
  108. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  109. $caps[] = $post_type->cap->delete_published_posts;
  110. } elseif ( 'private' == $post->post_status ) {
  111. $caps[] = $post_type->cap->delete_private_posts;
  112. }
  113. }
  114. /*
  115. * Setting the privacy policy page requires `manage_privacy_options`,
  116. * so deleting it should require that too.
  117. */
  118. if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
  119. $caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
  120. }
  121. break;
  122. // edit_post breaks down to edit_posts, edit_published_posts, or
  123. // edit_others_posts
  124. case 'edit_post':
  125. case 'edit_page':
  126. $post = get_post( $args[0] );
  127. if ( ! $post ) {
  128. $caps[] = 'do_not_allow';
  129. break;
  130. }
  131. if ( 'revision' == $post->post_type ) {
  132. $post = get_post( $post->post_parent );
  133. if ( ! $post ) {
  134. $caps[] = 'do_not_allow';
  135. break;
  136. }
  137. }
  138. $post_type = get_post_type_object( $post->post_type );
  139. if ( ! $post_type ) {
  140. /* translators: 1: post type, 2: capability name */
  141. _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' );
  142. $caps[] = 'edit_others_posts';
  143. break;
  144. }
  145. if ( ! $post_type->map_meta_cap ) {
  146. $caps[] = $post_type->cap->$cap;
  147. // Prior to 3.1 we would re-call map_meta_cap here.
  148. if ( 'edit_post' == $cap )
  149. $cap = $post_type->cap->$cap;
  150. break;
  151. }
  152. // If the post author is set and the user is the author...
  153. if ( $post->post_author && $user_id == $post->post_author ) {
  154. // If the post is published or scheduled...
  155. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  156. $caps[] = $post_type->cap->edit_published_posts;
  157. } elseif ( 'trash' == $post->post_status ) {
  158. $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
  159. if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
  160. $caps[] = $post_type->cap->edit_published_posts;
  161. } else {
  162. $caps[] = $post_type->cap->edit_posts;
  163. }
  164. } else {
  165. // If the post is draft...
  166. $caps[] = $post_type->cap->edit_posts;
  167. }
  168. } else {
  169. // The user is trying to edit someone else's post.
  170. $caps[] = $post_type->cap->edit_others_posts;
  171. // The post is published or scheduled, extra cap required.
  172. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  173. $caps[] = $post_type->cap->edit_published_posts;
  174. } elseif ( 'private' == $post->post_status ) {
  175. $caps[] = $post_type->cap->edit_private_posts;
  176. }
  177. }
  178. /*
  179. * Setting the privacy policy page requires `manage_privacy_options`,
  180. * so editing it should require that too.
  181. */
  182. if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
  183. $caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
  184. }
  185. break;
  186. case 'read_post':
  187. case 'read_page':
  188. $post = get_post( $args[0] );
  189. if ( ! $post ) {
  190. $caps[] = 'do_not_allow';
  191. break;
  192. }
  193. if ( 'revision' == $post->post_type ) {
  194. $post = get_post( $post->post_parent );
  195. if ( ! $post ) {
  196. $caps[] = 'do_not_allow';
  197. break;
  198. }
  199. }
  200. $post_type = get_post_type_object( $post->post_type );
  201. if ( ! $post_type ) {
  202. /* translators: 1: post type, 2: capability name */
  203. _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' );
  204. $caps[] = 'edit_others_posts';
  205. break;
  206. }
  207. if ( ! $post_type->map_meta_cap ) {
  208. $caps[] = $post_type->cap->$cap;
  209. // Prior to 3.1 we would re-call map_meta_cap here.
  210. if ( 'read_post' == $cap )
  211. $cap = $post_type->cap->$cap;
  212. break;
  213. }
  214. $status_obj = get_post_status_object( $post->post_status );
  215. if ( $status_obj->public ) {
  216. $caps[] = $post_type->cap->read;
  217. break;
  218. }
  219. if ( $post->post_author && $user_id == $post->post_author ) {
  220. $caps[] = $post_type->cap->read;
  221. } elseif ( $status_obj->private ) {
  222. $caps[] = $post_type->cap->read_private_posts;
  223. } else {
  224. $caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
  225. }
  226. break;
  227. case 'publish_post':
  228. $post = get_post( $args[0] );
  229. if ( ! $post ) {
  230. $caps[] = 'do_not_allow';
  231. break;
  232. }
  233. $post_type = get_post_type_object( $post->post_type );
  234. if ( ! $post_type ) {
  235. /* translators: 1: post type, 2: capability name */
  236. _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' );
  237. $caps[] = 'edit_others_posts';
  238. break;
  239. }
  240. $caps[] = $post_type->cap->publish_posts;
  241. break;
  242. case 'edit_post_meta':
  243. case 'delete_post_meta':
  244. case 'add_post_meta':
  245. case 'edit_comment_meta':
  246. case 'delete_comment_meta':
  247. case 'add_comment_meta':
  248. case 'edit_term_meta':
  249. case 'delete_term_meta':
  250. case 'add_term_meta':
  251. case 'edit_user_meta':
  252. case 'delete_user_meta':
  253. case 'add_user_meta':
  254. list( $_, $object_type, $_ ) = explode( '_', $cap );
  255. $object_id = (int) $args[0];
  256. $object_subtype = get_object_subtype( $object_type, $object_id );
  257. if ( empty( $object_subtype ) ) {
  258. $caps[] = 'do_not_allow';
  259. break;
  260. }
  261. $caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id );
  262. $meta_key = isset( $args[1] ) ? $args[1] : false;
  263. if ( $meta_key ) {
  264. $allowed = ! is_protected_meta( $meta_key, $object_type );
  265. if ( ! empty( $object_subtype ) && has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
  266. /**
  267. * Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype.
  268. *
  269. * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
  270. * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
  271. * the meta key value, and the object subtype respectively.
  272. *
  273. * @since 4.9.8
  274. *
  275. * @param bool $allowed Whether the user can add the object meta. Default false.
  276. * @param string $meta_key The meta key.
  277. * @param int $object_id Object ID.
  278. * @param int $user_id User ID.
  279. * @param string $cap Capability name.
  280. * @param string[] $caps Array of the user's capabilities.
  281. */
  282. $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
  283. } else {
  284. /**
  285. * Filters whether the user is allowed to edit a specific meta key of a specific object type.
  286. *
  287. * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
  288. *
  289. * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
  290. * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
  291. *
  292. * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
  293. * @since 4.6.0
  294. *
  295. * @param bool $allowed Whether the user can add the object meta. Default false.
  296. * @param string $meta_key The meta key.
  297. * @param int $object_id Object ID.
  298. * @param int $user_id User ID.
  299. * @param string $cap Capability name.
  300. * @param string[] $caps Array of the user's capabilities.
  301. */
  302. $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
  303. }
  304. if ( ! empty( $object_subtype ) ) {
  305. /**
  306. * Filters whether the user is allowed to edit meta for specific object types/subtypes.
  307. *
  308. * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
  309. *
  310. * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
  311. * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
  312. * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
  313. *
  314. * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
  315. * @since 4.7.0
  316. * @deprecated 4.9.8 Use `auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}`
  317. *
  318. * @param bool $allowed Whether the user can add the object meta. Default false.
  319. * @param string $meta_key The meta key.
  320. * @param int $object_id Object ID.
  321. * @param int $user_id User ID.
  322. * @param string $cap Capability name.
  323. * @param string[] $caps Array of the user's capabilities.
  324. */
  325. $allowed = apply_filters_deprecated( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ), '4.9.8', "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" );
  326. }
  327. if ( ! $allowed ) {
  328. $caps[] = $cap;
  329. }
  330. }
  331. break;
  332. case 'edit_comment':
  333. $comment = get_comment( $args[0] );
  334. if ( ! $comment ) {
  335. $caps[] = 'do_not_allow';
  336. break;
  337. }
  338. $post = get_post( $comment->comment_post_ID );
  339. /*
  340. * If the post doesn't exist, we have an orphaned comment.
  341. * Fall back to the edit_posts capability, instead.
  342. */
  343. if ( $post ) {
  344. $caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
  345. } else {
  346. $caps = map_meta_cap( 'edit_posts', $user_id );
  347. }
  348. break;
  349. case 'unfiltered_upload':
  350. if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) ) )
  351. $caps[] = $cap;
  352. else
  353. $caps[] = 'do_not_allow';
  354. break;
  355. case 'edit_css' :
  356. case 'unfiltered_html' :
  357. // Disallow unfiltered_html for all users, even admins and super admins.
  358. if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML )
  359. $caps[] = 'do_not_allow';
  360. elseif ( is_multisite() && ! is_super_admin( $user_id ) )
  361. $caps[] = 'do_not_allow';
  362. else
  363. $caps[] = 'unfiltered_html';
  364. break;
  365. case 'edit_files':
  366. case 'edit_plugins':
  367. case 'edit_themes':
  368. // Disallow the file editors.
  369. if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT )
  370. $caps[] = 'do_not_allow';
  371. elseif ( ! wp_is_file_mod_allowed( 'capability_edit_themes' ) )
  372. $caps[] = 'do_not_allow';
  373. elseif ( is_multisite() && ! is_super_admin( $user_id ) )
  374. $caps[] = 'do_not_allow';
  375. else
  376. $caps[] = $cap;
  377. break;
  378. case 'update_plugins':
  379. case 'delete_plugins':
  380. case 'install_plugins':
  381. case 'upload_plugins':
  382. case 'update_themes':
  383. case 'delete_themes':
  384. case 'install_themes':
  385. case 'upload_themes':
  386. case 'update_core':
  387. // Disallow anything that creates, deletes, or updates core, plugin, or theme files.
  388. // Files in uploads are excepted.
  389. if ( ! wp_is_file_mod_allowed( 'capability_update_core' ) ) {
  390. $caps[] = 'do_not_allow';
  391. } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
  392. $caps[] = 'do_not_allow';
  393. } elseif ( 'upload_themes' === $cap ) {
  394. $caps[] = 'install_themes';
  395. } elseif ( 'upload_plugins' === $cap ) {
  396. $caps[] = 'install_plugins';
  397. } else {
  398. $caps[] = $cap;
  399. }
  400. break;
  401. case 'install_languages':
  402. case 'update_languages':
  403. if ( ! wp_is_file_mod_allowed( 'can_install_language_pack' ) ) {
  404. $caps[] = 'do_not_allow';
  405. } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
  406. $caps[] = 'do_not_allow';
  407. } else {
  408. $caps[] = 'install_languages';
  409. }
  410. break;
  411. case 'activate_plugins':
  412. case 'deactivate_plugins':
  413. case 'activate_plugin':
  414. case 'deactivate_plugin':
  415. $caps[] = 'activate_plugins';
  416. if ( is_multisite() ) {
  417. // update_, install_, and delete_ are handled above with is_super_admin().
  418. $menu_perms = get_site_option( 'menu_items', array() );
  419. if ( empty( $menu_perms['plugins'] ) )
  420. $caps[] = 'manage_network_plugins';
  421. }
  422. break;
  423. case 'delete_user':
  424. case 'delete_users':
  425. // If multisite only super admins can delete users.
  426. if ( is_multisite() && ! is_super_admin( $user_id ) )
  427. $caps[] = 'do_not_allow';
  428. else
  429. $caps[] = 'delete_users'; // delete_user maps to delete_users.
  430. break;
  431. case 'create_users':
  432. if ( !is_multisite() )
  433. $caps[] = $cap;
  434. elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) )
  435. $caps[] = $cap;
  436. else
  437. $caps[] = 'do_not_allow';
  438. break;
  439. case 'manage_links' :
  440. if ( get_option( 'link_manager_enabled' ) )
  441. $caps[] = $cap;
  442. else
  443. $caps[] = 'do_not_allow';
  444. break;
  445. case 'customize' :
  446. $caps[] = 'edit_theme_options';
  447. break;
  448. case 'delete_site':
  449. if ( is_multisite() ) {
  450. $caps[] = 'manage_options';
  451. } else {
  452. $caps[] = 'do_not_allow';
  453. }
  454. break;
  455. case 'edit_term':
  456. case 'delete_term':
  457. case 'assign_term':
  458. $term_id = (int) $args[0];
  459. $term = get_term( $term_id );
  460. if ( ! $term || is_wp_error( $term ) ) {
  461. $caps[] = 'do_not_allow';
  462. break;
  463. }
  464. $tax = get_taxonomy( $term->taxonomy );
  465. if ( ! $tax ) {
  466. $caps[] = 'do_not_allow';
  467. break;
  468. }
  469. if ( 'delete_term' === $cap && ( $term->term_id == get_option( 'default_' . $term->taxonomy ) ) ) {
  470. $caps[] = 'do_not_allow';
  471. break;
  472. }
  473. $taxo_cap = $cap . 's';
  474. $caps = map_meta_cap( $tax->cap->$taxo_cap, $user_id, $term_id );
  475. break;
  476. case 'manage_post_tags':
  477. case 'edit_categories':
  478. case 'edit_post_tags':
  479. case 'delete_categories':
  480. case 'delete_post_tags':
  481. $caps[] = 'manage_categories';
  482. break;
  483. case 'assign_categories':
  484. case 'assign_post_tags':
  485. $caps[] = 'edit_posts';
  486. break;
  487. case 'create_sites':
  488. case 'delete_sites':
  489. case 'manage_network':
  490. case 'manage_sites':
  491. case 'manage_network_users':
  492. case 'manage_network_plugins':
  493. case 'manage_network_themes':
  494. case 'manage_network_options':
  495. case 'upgrade_network':
  496. $caps[] = $cap;
  497. break;
  498. case 'setup_network':
  499. if ( is_multisite() ) {
  500. $caps[] = 'manage_network_options';
  501. } else {
  502. $caps[] = 'manage_options';
  503. }
  504. break;
  505. case 'export_others_personal_data':
  506. case 'erase_others_personal_data':
  507. case 'manage_privacy_options':
  508. $caps[] = is_multisite() ? 'manage_network' : 'manage_options';
  509. break;
  510. default:
  511. // Handle meta capabilities for custom post types.
  512. global $post_type_meta_caps;
  513. if ( isset( $post_type_meta_caps[ $cap ] ) ) {
  514. $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args );
  515. return call_user_func_array( 'map_meta_cap', $args );
  516. }
  517. // If no meta caps match, return the original cap.
  518. $caps[] = $cap;
  519. }
  520. /**
  521. * Filters a user's capabilities depending on specific context and/or privilege.
  522. *
  523. * @since 2.8.0
  524. *
  525. * @param array $caps Returns the user's actual capabilities.
  526. * @param string $cap Capability name.
  527. * @param int $user_id The user ID.
  528. * @param array $args Adds the context to the cap. Typically the object ID.
  529. */
  530. return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
  531. }
  532. /**
  533. * Whether the current user has a specific capability.
  534. *
  535. * While checking against particular roles in place of a capability is supported
  536. * in part, this practice is discouraged as it may produce unreliable results.
  537. *
  538. * Note: Will always return true if the current user is a super admin, unless specifically denied.
  539. *
  540. * @since 2.0.0
  541. *
  542. * @see WP_User::has_cap()
  543. * @see map_meta_cap()
  544. *
  545. * @param string $capability Capability name.
  546. * @param int $object_id Optional. ID of the specific object to check against if `$capability` is a "meta" cap.
  547. * "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
  548. * by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
  549. * 'edit_others_posts', etc. Accessed via func_get_args() and passed to WP_User::has_cap(),
  550. * then map_meta_cap().
  551. * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is
  552. * passed, whether the current user has the given meta capability for the given object.
  553. */
  554. function current_user_can( $capability ) {
  555. $current_user = wp_get_current_user();
  556. if ( empty( $current_user ) )
  557. return false;
  558. $args = array_slice( func_get_args(), 1 );
  559. $args = array_merge( array( $capability ), $args );
  560. return call_user_func_array( array( $current_user, 'has_cap' ), $args );
  561. }
  562. /**
  563. * Whether the current user has a specific capability for a given site.
  564. *
  565. * @since 3.0.0
  566. *
  567. * @param int $blog_id Site ID.
  568. * @param string $capability Capability name.
  569. * @return bool Whether the user has the given capability.
  570. */
  571. function current_user_can_for_blog( $blog_id, $capability ) {
  572. $switched = is_multisite() ? switch_to_blog( $blog_id ) : false;
  573. $current_user = wp_get_current_user();
  574. if ( empty( $current_user ) ) {
  575. if ( $switched ) {
  576. restore_current_blog();
  577. }
  578. return false;
  579. }
  580. $args = array_slice( func_get_args(), 2 );
  581. $args = array_merge( array( $capability ), $args );
  582. $can = call_user_func_array( array( $current_user, 'has_cap' ), $args );
  583. if ( $switched ) {
  584. restore_current_blog();
  585. }
  586. return $can;
  587. }
  588. /**
  589. * Whether the author of the supplied post has a specific capability.
  590. *
  591. * @since 2.9.0
  592. *
  593. * @param int|WP_Post $post Post ID or post object.
  594. * @param string $capability Capability name.
  595. * @return bool Whether the post author has the given capability.
  596. */
  597. function author_can( $post, $capability ) {
  598. if ( !$post = get_post($post) )
  599. return false;
  600. $author = get_userdata( $post->post_author );
  601. if ( ! $author )
  602. return false;
  603. $args = array_slice( func_get_args(), 2 );
  604. $args = array_merge( array( $capability ), $args );
  605. return call_user_func_array( array( $author, 'has_cap' ), $args );
  606. }
  607. /**
  608. * Whether a particular user has a specific capability.
  609. *
  610. * @since 3.1.0
  611. *
  612. * @param int|WP_User $user User ID or object.
  613. * @param string $capability Capability name.
  614. * @return bool Whether the user has the given capability.
  615. */
  616. function user_can( $user, $capability ) {
  617. if ( ! is_object( $user ) )
  618. $user = get_userdata( $user );
  619. if ( ! $user || ! $user->exists() )
  620. return false;
  621. $args = array_slice( func_get_args(), 2 );
  622. $args = array_merge( array( $capability ), $args );
  623. return call_user_func_array( array( $user, 'has_cap' ), $args );
  624. }
  625. /**
  626. * Retrieves the global WP_Roles instance and instantiates it if necessary.
  627. *
  628. * @since 4.3.0
  629. *
  630. * @global WP_Roles $wp_roles WP_Roles global instance.
  631. *
  632. * @return WP_Roles WP_Roles global instance if not already instantiated.
  633. */
  634. function wp_roles() {
  635. global $wp_roles;
  636. if ( ! isset( $wp_roles ) ) {
  637. $wp_roles = new WP_Roles();
  638. }
  639. return $wp_roles;
  640. }
  641. /**
  642. * Retrieve role object.
  643. *
  644. * @since 2.0.0
  645. *
  646. * @param string $role Role name.
  647. * @return WP_Role|null WP_Role object if found, null if the role does not exist.
  648. */
  649. function get_role( $role ) {
  650. return wp_roles()->get_role( $role );
  651. }
  652. /**
  653. * Add role, if it does not exist.
  654. *
  655. * @since 2.0.0
  656. *
  657. * @param string $role Role name.
  658. * @param string $display_name Display name for role.
  659. * @param array $capabilities List of capabilities, e.g. array( 'edit_posts' => true, 'delete_posts' => false );
  660. * @return WP_Role|null WP_Role object if role is added, null if already exists.
  661. */
  662. function add_role( $role, $display_name, $capabilities = array() ) {
  663. if ( empty( $role ) ) {
  664. return;
  665. }
  666. return wp_roles()->add_role( $role, $display_name, $capabilities );
  667. }
  668. /**
  669. * Remove role, if it exists.
  670. *
  671. * @since 2.0.0
  672. *
  673. * @param string $role Role name.
  674. */
  675. function remove_role( $role ) {
  676. wp_roles()->remove_role( $role );
  677. }
  678. /**
  679. * Retrieve a list of super admins.
  680. *
  681. * @since 3.0.0
  682. *
  683. * @global array $super_admins
  684. *
  685. * @return array List of super admin logins
  686. */
  687. function get_super_admins() {
  688. global $super_admins;
  689. if ( isset($super_admins) )
  690. return $super_admins;
  691. else
  692. return get_site_option( 'site_admins', array('admin') );
  693. }
  694. /**
  695. * Determine if user is a site admin.
  696. *
  697. * @since 3.0.0
  698. *
  699. * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
  700. * @return bool True if the user is a site admin.
  701. */
  702. function is_super_admin( $user_id = false ) {
  703. if ( ! $user_id || $user_id == get_current_user_id() )
  704. $user = wp_get_current_user();
  705. else
  706. $user = get_userdata( $user_id );
  707. if ( ! $user || ! $user->exists() )
  708. return false;
  709. if ( is_multisite() ) {
  710. $super_admins = get_super_admins();
  711. if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) )
  712. return true;
  713. } else {
  714. if ( $user->has_cap('delete_users') )
  715. return true;
  716. }
  717. return false;
  718. }
  719. /**
  720. * Grants Super Admin privileges.
  721. *
  722. * @since 3.0.0
  723. *
  724. * @global array $super_admins
  725. *
  726. * @param int $user_id ID of the user to be granted Super Admin privileges.
  727. * @return bool True on success, false on failure. This can fail when the user is
  728. * already a super admin or when the `$super_admins` global is defined.
  729. */
  730. function grant_super_admin( $user_id ) {
  731. // If global super_admins override is defined, there is nothing to do here.
  732. if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) {
  733. return false;
  734. }
  735. /**
  736. * Fires before the user is granted Super Admin privileges.
  737. *
  738. * @since 3.0.0
  739. *
  740. * @param int $user_id ID of the user that is about to be granted Super Admin privileges.
  741. */
  742. do_action( 'grant_super_admin', $user_id );
  743. // Directly fetch site_admins instead of using get_super_admins()
  744. $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
  745. $user = get_userdata( $user_id );
  746. if ( $user && ! in_array( $user->user_login, $super_admins ) ) {
  747. $super_admins[] = $user->user_login;
  748. update_site_option( 'site_admins' , $super_admins );
  749. /**
  750. * Fires after the user is granted Super Admin privileges.
  751. *
  752. * @since 3.0.0
  753. *
  754. * @param int $user_id ID of the user that was granted Super Admin privileges.
  755. */
  756. do_action( 'granted_super_admin', $user_id );
  757. return true;
  758. }
  759. return false;
  760. }
  761. /**
  762. * Revokes Super Admin privileges.
  763. *
  764. * @since 3.0.0
  765. *
  766. * @global array $super_admins
  767. *
  768. * @param int $user_id ID of the user Super Admin privileges to be revoked from.
  769. * @return bool True on success, false on failure. This can fail when the user's email
  770. * is the network admin email or when the `$super_admins` global is defined.
  771. */
  772. function revoke_super_admin( $user_id ) {
  773. // If global super_admins override is defined, there is nothing to do here.
  774. if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) {
  775. return false;
  776. }
  777. /**
  778. * Fires before the user's Super Admin privileges are revoked.
  779. *
  780. * @since 3.0.0
  781. *
  782. * @param int $user_id ID of the user Super Admin privileges are being revoked from.
  783. */
  784. do_action( 'revoke_super_admin', $user_id );
  785. // Directly fetch site_admins instead of using get_super_admins()
  786. $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
  787. $user = get_userdata( $user_id );
  788. if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) {
  789. if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
  790. unset( $super_admins[$key] );
  791. update_site_option( 'site_admins', $super_admins );
  792. /**
  793. * Fires after the user's Super Admin privileges are revoked.
  794. *
  795. * @since 3.0.0
  796. *
  797. * @param int $user_id ID of the user Super Admin privileges were revoked from.
  798. */
  799. do_action( 'revoked_super_admin', $user_id );
  800. return true;
  801. }
  802. }
  803. return false;
  804. }
  805. /**
  806. * Filters the user capabilities to grant the 'install_languages' capability as necessary.
  807. *
  808. * A user must have at least one out of the 'update_core', 'install_plugins', and
  809. * 'install_themes' capabilities to qualify for 'install_languages'.
  810. *
  811. * @since 4.9.0
  812. *
  813. * @param array $allcaps An array of all the user's capabilities.
  814. * @return array Filtered array of the user's capabilities.
  815. */
  816. function wp_maybe_grant_install_languages_cap( $allcaps ) {
  817. if ( ! empty( $allcaps['update_core'] ) || ! empty( $allcaps['install_plugins'] ) || ! empty( $allcaps['install_themes'] ) ) {
  818. $allcaps['install_languages'] = true;
  819. }
  820. return $allcaps;
  821. }