Berechtigungen (capabilities) in WordPress beschreiben Aktionen, die ein bestimmter Benutzer durchführen oder nicht durchführen darf.
Rollen (roles) in WordPress sind dafür verantwortlich festzulegen, über welche Berechtigungen ein Benutzer verfügt oder nicht verfügt.
read
edit_posts
upload_files
manage_categories
manage_options
read_ct_tutorials
edit_ct_tutorials
manage_ct_options
options
-TabelleDie verfügbaren Rollen für eine Website sind in der options
-Datenbanktabelle als serialisiertes Array gespeichert.
Die Berechtigungen, die eine Rolle gewährt, sind ebenfalls Teil dieses Arrays.
array(
'administrator' => array(
'name' => 'Administrator',
'capabilities' => array(
'switch_themes' => true,
'edit_themes' => true,
'activate_plugins' => true,
'edit_plugins' => true,
'edit_users' => true,
'edit_files' => true,
'manage_options' => true,
'moderate_comments' => true,
'manage_categories' => true,
'manage_links' => true,
'upload_files' => true,
'import' => true,
'unfiltered_html' => true,
'edit_posts' => true,
'edit_others_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'edit_pages' => true,
'read' => true,
'edit_others_pages' => true,
'edit_published_pages' => true,
'publish_pages' => true,
'delete_pages' => true,
'delete_others_pages' => true,
'delete_published_pages' => true,
'delete_posts' => true,
'delete_others_posts' => true,
'delete_published_posts' => true,
'delete_private_posts' => true,
'edit_private_posts' => true,
'read_private_posts' => true,
'delete_private_pages' => true,
'edit_private_pages' => true,
'read_private_pages' => true,
'delete_users' => true,
'create_users' => true,
'unfiltered_upload' => true,
'edit_dashboard' => true,
'update_plugins' => true,
'delete_plugins' => true,
'install_plugins' => true,
'update_themes' => true,
'install_themes' => true,
'update_core' => true,
'list_users' => true,
'remove_users' => true,
'promote_users' => true,
'edit_theme_options' => true,
'delete_themes' => true,
'export' => true,
),
),
'editor' => array(
'name' => 'Editor',
'capabilities' => array(
'moderate_comments' => true,
'manage_categories' => true,
'manage_links' => true,
'upload_files' => true,
'unfiltered_html' => true,
'edit_posts' => true,
'edit_others_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'edit_pages' => true,
'read' => true,
'edit_others_pages' => true,
'edit_published_pages' => true,
'publish_pages' => true,
'delete_pages' => true,
'delete_others_pages' => true,
'delete_published_pages' => true,
'delete_posts' => true,
'delete_others_posts' => true,
'delete_published_posts' => true,
'delete_private_posts' => true,
'edit_private_posts' => true,
'read_private_posts' => true,
'delete_private_pages' => true,
'edit_private_pages' => true,
'read_private_pages' => true,
),
),
'author' => array(
'name' => 'Author',
'capabilities' => array(
'upload_files' => true,
'edit_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'read' => true,
'delete_posts' => true,
'delete_published_posts' => true,
),
),
'contributor' => array(
'name' => 'Contributor',
'capabilities' => array(
'edit_posts' => true,
'read' => true,
'delete_posts' => true,
),
),
'subscriber' => array(
'name' => 'Subscriber',
'capabilities' => array(
'read' => true,
),
),
);
usermeta
-TabelleDie Rollen, die ein Benutzer hat, sind in der usermeta
-Datenbanktabelle unter der jeweiligen Benutzer-ID als serialisiertes Array gespeichert.
Zusätzliche Berechtigungen können theoretisch ebenfalls Teil dieses Arrays sein, unabhängig von Rollen.
array(
'editor' => true,
);
current_user_can( string $capability )
oder
user_can( int|WP_User $user, string $capability )
user_has_cap
-Filtercurrent_user_can( 'edit_posts' )
current_user_can( 'activate_plugins' )
map_meta_cap
-Filters in ein oder mehrere primitive Berechtigungen gemappt/aufgelöstcurrent_user_can( 'edit_post', $post_id )
current_user_can( 'activate_plugin', $plugin_basename )
Die folgenden Berechtigungen werden gesondert behandelt:
exist
: Jeder verfügt über diese Berechtigung, sogar ausgeloggte Benutzer.do_not_allow
: Niemand verfügt über diese Berechtigung, nicht einmal Netzwerk-Administratoren.{action}_{items}
für primitive Berechtigungen
{action}_{item}
für Meta-Berechtigungen
current_user_can()
map_meta_cap()
→ apply_filters( 'map_meta_cap' )
apply_filters( 'user_has_cap' )
github.com/felixarntz/capability-tutorials
current_user_can( string $capability )
developer.wordpress.org/reference/functions/current_user_can/
function ct_add_settings_page() {
$hook_suffix = add_submenu_page(
'edit.php?post_type=' . CT_POST_TYPE_SINGULAR,
__( 'Tutorial Settings', 'capability-tutorials' ),
__( 'Settings', 'capability-tutorials' ),
'manage_ct_options',
'ct_settings_page',
'ct_render_settings_page'
);
add_action( "load-{$hook_suffix}", 'ct_initialize_settings_page' );
}
add_action( 'admin_menu', 'ct_add_settings_page' );
add_menu_page()
und add_submenu_page()
sind Beispiele, wo eine Berechtigung angegeben werden muss. WordPress verwendet intern current_user_can()
für die entsprechende Überprüfung.
function ct_initialize_settings_page() {
add_settings_field( 'rewrite_slug', __( 'Rewrite Slug', 'capability-tutorials' ), 'ct_render_settings_page_rewrite_slug_field', CT_OPTION_GROUP, 'default', array(
'label_for' => 'ct-rewrite-slug',
) );
add_settings_field( 'supports', __( 'Supported Features', 'capability-tutorials' ), 'ct_render_settings_page_supports_field', CT_OPTION_GROUP, 'default' );
add_settings_field( 'has_archive', __( 'Archive', 'capability-tutorials' ), 'ct_render_settings_page_has_archive_field', CT_OPTION_GROUP, 'default' );
}
function ct_initialize_settings_page() {
if ( current_user_can( 'manage_ct_option', 'ct_rewrite_slug' ) ) {
add_settings_field( 'rewrite_slug', __( 'Rewrite Slug', 'capability-tutorials' ), 'ct_render_settings_page_rewrite_slug_field', CT_OPTION_GROUP, 'default', array(
'label_for' => 'ct-rewrite-slug',
) );
}
if ( current_user_can( 'manage_ct_option', 'ct_supports' ) ) {
add_settings_field( 'supports', __( 'Supported Features', 'capability-tutorials' ), 'ct_render_settings_page_supports_field', CT_OPTION_GROUP, 'default' );
}
if ( current_user_can( 'manage_ct_option', 'ct_has_archive' ) ) {
add_settings_field( 'has_archive', __( 'Archive', 'capability-tutorials' ), 'ct_render_settings_page_has_archive_field', CT_OPTION_GROUP, 'default' );
}
}
→ Die Berechtigungen müssen noch passend gewährt werden!
apply_filters( 'user_has_cap', array $allcaps, array $caps, array $args, WP_User $user )
function ct_maybe_grant_capabilities( $allcaps ) {
// Allow managing plugin options depending on the user having the 'manage_options' capability.
if ( isset( $allcaps['manage_options'] ) ) {
$allcaps['manage_ct_options'] = $allcaps['manage_options'];
}
return $allcaps;
}
add_filter( 'user_has_cap', 'ct_maybe_grant_capabilities' );
→ Die Meta-Berechtigungen müssen in primitive Berechtigungen aufgelöst werden!
apply_filters( 'map_meta_cap', array $caps, string $cap, int $user_id, array $args )
function ct_map_meta_capabilities( $caps, $cap, $user_id, $args ) {
switch ( $cap ) {
// Maps the meta capability for a single option to the primitive capability for options.
case 'manage_ct_option':
$caps = array( 'manage_ct_options' );
break;
}
return $caps;
}
add_filter( 'map_meta_cap', 'ct_map_meta_capabilities', 10, 4 );
Während das Standardverhalten sich durch die granulare Nutzung von Berechtigungen nicht verändert, erlaubt dies anderen Entwicklern folgende projektspezifische Verbesserungen:
Anstatt den user_has_cap
-Filter zur Gewährung der Berechtigungen zu verwenden, könnte eine eigene "Tutorial Manager"-Rolle eingeführt werden und diese dann die Berechtigungen allen Benutzern mit dieser Rolle gewähren.
function mysetup_add_tutorial_manager_role() {
add_role( 'tutorial_manager', __( 'Tutorial Manager', 'my-setup' ), array(
'edit_ct_tutorials' => true,
'edit_others_ct_tutorials' => true,
'publish_ct_tutorials' => true,
'read_private_ct_tutorials' => true,
'create_ct_tutorials' => true,
'edit_private_ct_tutorials' => true,
'edit_published_ct_tutorials' => true,
'delete_ct_tutorials' => true,
'delete_others_ct_tutorials' => true,
'delete_private_ct_tutorials' => true,
'delete_published_ct_tutorials' => true,
'read_ct_tutorials' => true,
'manage_ct_options' => true,
) );
}
register_activation_hook( __FILE__, 'mysetup_add_tutorial_manager_role' );
remove_filter( 'user_has_cap', 'ct_maybe_grant_capabilities' );
In einer Multisite könnte man beispielsweise wollen, dass die Rewrite Slug-Option nur vom Netzwerk-Administrator (oder jemand anderem, der über die manage_network_options
-Berechtigung verfügt) verändert werden kann.
function mysetup_tweak_rewrite_slug_capability( $caps, $cap, $user_id, $args ) {
if ( 'manage_ct_option' === $cap ) {
$caps = array( 'manage_ct_options' );
if ( ! empty( $args ) && 'ct_rewrite_slug' === $args[0] && is_multisite() ) {
$caps[] = 'manage_network_options';
}
}
return $caps;
}
add_filter( 'map_meta_cap', 'mysetup_tweak_rewrite_slug_capability', 11, 4 );
Der Netzwerk-Administrator (manchmal auch "Super Admin" genannt) scheint erstmal eine zusätzliche Rolle zu sein. Eigentlich ist es jedoch nur eine einfache Flag, die einem Benutzer erlaubt, auf alle Berechtigungen außer do_not_allow
zugreifen zu können.
Nichtsdestotrotz sollte immer auf Berechtigungen geprüft werden, mithilfe eigener multisite-spezifischer Berechtigungen. Niemals is_super_admin()
verwenden!
manage_sites
create_sites
delete_sites
manage_network
manage_network_themes
manage_network_plugins
manage_network_users
manage_network_options
upgrade_network
Oftmals möchte man in Multisite eine Berechtigung ausschließlich Netzwerk-Administratoren gewähren, während ansonsten auch reguläre Administratoren darauf Zugriff haben sollten.
function map_install_plugin_cap( $caps, $cap, $user_id, $args ) {
if ( 'install_plugin' === $cap ) {
$caps = array( 'install_plugins' );
if ( is_multisite() && ! is_super_admin( $user_id ) ) {
$caps[] = 'do_not_allow';
}
}
return $caps;
}
function map_install_plugin_cap( $caps, $cap, $user_id, $args ) {
if ( 'install_plugin' === $cap ) {
$caps = array( 'install_plugins' );
if ( is_multisite() ) {
$caps[] = 'manage_network_plugins';
}
}
return $caps;
}
Plugin Developer / Core Committer / Freelancer