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

Advanced WordPress Development: Capabilities (W...

Avatar for nacin nacin
November 05, 2011

Advanced WordPress Development: Capabilities (WordCamp Philly 2011)

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

Avatar for nacin

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