Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Advanced WordPress Development: Capabilities (W...

nacin
November 05, 2011

Advanced WordPress Development: Capabilities (WordCamp Philly 2011)

Advanced WordPress Development: Capabilities, and tweaking them through unconventional means. WordCamp Philadelphia 2011.

nacin

November 05, 2011
Tweet

Other Decks in Technology

Transcript

  1. Modifying Roles and Capabilities in the DB get_role( ), add_role(

    ), add_cap( ), remove_cap( ), etc. @nacin
  2. current_user_can( ) : $user = wp_get_current_user( ); return $user->has_cap( $args

    ); (Core functions are often simplified in this talk.) @nacin
  3. WP_User's has_cap( ) method: $required_caps = map_meta_cap( $args ); //

    Multisite super admin has all caps, unless denied. if ( is_multisite( ) && is_super_admin( $user_id ) ) return ! in_array( 'do_not_allow', $required_caps ); $caps_user_has = apply_filters( 'user_has_cap', $caps_user_has, $required_caps, $args ); // Must have all required caps foreach ( $caps_user_has as $cap ) if ( empty( $caps_user_has[ $cap ] ) ) return false; return true;
  4. WP_User's has_cap( ) method: $required_caps = map_meta_cap( $args ); //

    Multisite super admin has all caps, unless denied. if ( is_multisite( ) && is_super_admin( $user_id ) ) return ! in_array( 'do_not_allow', $required_caps );
  5. WP_User's has_cap( ) method: $required_caps = map_meta_cap( $args ); //

    Multisite super admin has all caps, unless denied. if ( is_multisite( ) && is_super_admin( $user_id ) ) return ! in_array( 'do_not_allow', $required_caps ); $caps_user_has = apply_filters( 'user_has_cap', $caps_user_has, $required_caps, $args );
  6. WP_User's has_cap( ) method: $required_caps = map_meta_cap( $caps ); //

    Multisite super admin has all caps, unless denied. if ( is_multisite( ) && is_super_admin( $user_id ) ) return ! in_array( 'do_not_allow', $required_caps ); $caps_user_has = apply_filters( 'user_has_cap' $caps_user_has, $required_caps, $args ); // Must have all required caps foreach ( $caps_user_has as $cap ) if ( empty( $caps_user_has[ $cap ] ) ) return false; return true;
  7. If you can edit pages, you can edit widgets: add_filter(

    'user_has_cap', function( $caps ) { if ( ! empty( $caps[ 'edit_pages' ] ) $caps[ 'edit_theme_options' ] = true; return $caps; } );
  8. Give secondary "administrators" less control: add_filter( 'user_has_cap', function( $caps, $required_caps,

    $args ) { $user_id = $args[1]; $user = new WP_User( $user_id ); if ( $user->user_email != get_option( 'admin_email' ) ) $caps[ 'manage_options' ] = false; return $caps; }, 10, 3 );
  9. edit_posts — Contributors, Authors, Editors have this. edit_published_posts — Is

    the post published? — Authors, Editors have this. @nacin
  10. edit_posts — Contributors, Authors, Editors have this. edit_published_posts — Is

    the post published? — Authors, Editors have this. edit_private_posts — Is the post private? — Editors have this. @nacin
  11. edit_posts — Contributors, Authors, Editors have this. edit_published_posts — Is

    the post published? — Authors, Editors have this. edit_private_posts — Is the post private? — Editors have this. edit_others_posts — Are you not the post author? — Editors have this. @nacin
  12. Meta caps are singular, and roles should never be assigned

    them. — edit_post, delete_post, read_post —delete_user, edit_user @nacin
  13. Meta caps are singular, and roles should never be assigned

    them. — edit_post, delete_post, read_post —delete_user, edit_user Primitive caps are plural, and roles have these. — edit_posts, edit_published_posts —delete_users, edit_users @nacin
  14. If you do: current_user_can( 'edit_post', $post_id ) meta capability ^

    context ^ map_meta_cap() translates this to, e.g.: array( 'edit_posts' ) If the post is published and not by you: array( 'edit_published_posts', 'edit_others_posts' ) @nacin
  15. WP_User's has_cap( ) method: $required_caps = map_meta_cap( $args ); //

    Multisite super admin has all caps, unless denied. if ( is_multisite( ) && is_super_admin( $user_id ) ) return ! in_array( 'do_not_allow', $required_caps ); $caps_user_has = apply_filters( 'user_has_cap', $caps_user_has, $required_caps, $args ); // Must have all required caps foreach ( $caps_user_has as $cap ) if ( empty( $caps_user_has[ $cap ] ) ) return false; return true;
  16. Don't let anyone delete users from the UI: // apply_filters(

    'map_meta_cap', $required_caps, $queried_cap, $user_id, $args ); add_filter( 'map_meta_cap', function( $required_caps, $queried_cap ) { if ( 'delete_user' == $queried_cap || 'delete_users' == $queried_cap ) $required_caps[] = 'do_not_allow'; return $required_caps; }, 10, 2 );
  17. Only administrators can delete published posts: add_filter( 'map_meta_cap', function( $required_caps,

    $queried_cap ) { if ( 'delete_post' == $queried_cap ) $required_caps[] = 'manage_options'; return $required_caps; }, 10, 2 );
  18. Don't allow file changes via the UI: add_filter( 'map_meta_cap', function(

    $required_caps, $queried_cap ) { if ( in_array( $queried_cap, array( 'edit_themes', 'edit_plugins', 'update_themes', 'update_plugins', 'install_themes', 'install_plugins', 'update_core' ) ) $required_caps[] = 'do_not_allow'; return $required_caps; }, 10, 2 );
  19. (That is built into core, by the way...) // deny

    edit_themes, edit_plugins define( 'DISALLOW_FILE_EDIT', true ); // deny all file changes define( 'DISALLOW_FILE_MODS', true );
  20. Require editors to approve posts: add_filter( 'map_meta_cap', function( $required_caps, $queried_cap

    ) { if ( $queried_cap == 'publish_posts' ) $required_caps[] = 'edit_others_posts'; return $required_caps; }, 10, 2 );
  21. // mapping for current_user_can( 'edit_post', $post_id ) case 'edit_post' :

    if ( $user_id == $post_author->ID ) { // Are we the author? if ( 'publish' == $post->post_status ) $caps[] = $post_type->cap->edit_published_posts; else $caps[] = $post_type->cap->edit_posts; } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->edit_others_posts; // If the post is published, extra caps are required. if ( 'publish' == $post->post_status ) $caps[] = $post_type->cap->edit_published_posts; elseif ( 'private' == $post->post_status ) $caps[] = $post_type->cap->edit_private_posts; } . . . return apply_filters( 'map_meta_cap', $caps, ... );
  22. Where you are leveraging the same *_posts capabilities: register_post_type( 'book',

    array( . . . 'capability_type' => 'post', // Implied for 'post' and 'page' : 'map_meta_cap' => true, . . . );
  23. Where you are assigning *_books capabilities to users: register_post_type( 'book',

    array( . . . 'capability_type' => 'book', // Map edit_book (and read, delete) 'map_meta_cap' => true, . . . );
  24. Hey, plural forms too: register_post_type( 'story', array( . . .

    'capability_type' => array( 'story', 'stories' ) // Map edit_story (and read, delete) to edit_stories, etc. 'map_meta_cap' => true, );
  25. Go crazy with full customizations: register_post_type( 'article', array( . .

    . 'capabilities' => array( // primitive capabilities assigned to users 'read' => 'read', 'edit_posts' => 'edit_articles', 'publish_posts' => 'edit_articles', // lock them down once published 'edit_published_posts' => 'do_not_allow', 'delete_posts' => 'do_not_allow', 'delete_others_posts' => 'do_not_allow', 'delete_published_posts' => 'do_not_allow', // meta capabilities 'edit_post' => . . .
  26. Review user_has_cap filter Explicitly granting or denying users a capability.

    map_meta_cap filter Translating a capability into the capabilities required, depending on the context. @nacin
  27. And finally: register_post_type( ) You can customize mapping and capabilities

    when registering a post type. map_meta_cap( ) Read it. It's worth it. get_post_type_capabilities( ) Read the documentation in wp-includes/post.php. @nacin