capabilities.php 33 KB

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