From 780c17b3fddb15084e860e77a6a00117c1085080 Mon Sep 17 00:00:00 2001 From: Ronny Grobel Date: Mon, 13 Apr 2026 21:57:54 +0200 Subject: [PATCH] Initial plugin commit --- .gitignore | 3 + kgv-role-manager.php | 448 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 451 insertions(+) create mode 100644 .gitignore create mode 100755 kgv-role-manager.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b6e650 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +Thumbs.db +*.zip diff --git a/kgv-role-manager.php b/kgv-role-manager.php new file mode 100755 index 0000000..f8e908d --- /dev/null +++ b/kgv-role-manager.php @@ -0,0 +1,448 @@ + array( 'updated', __( 'Rolle gespeichert.', 'kgv-role-manager' ) ), + 'deleted' => array( 'updated', __( 'Rolle gelöscht.', 'kgv-role-manager' ) ), + 'invalid' => array( 'error', __( 'Ungültige Eingabe.', 'kgv-role-manager' ) ), + 'exists' => array( 'error', __( 'Der Rollen-Slug existiert bereits.', 'kgv-role-manager' ) ), + 'failed' => array( 'error', __( 'Aktion konnte nicht ausgeführt werden.', 'kgv-role-manager' ) ), + 'core' => array( 'error', __( 'Standardrollen können hier nicht gelöscht werden.', 'kgv-role-manager' ) ), + ); + + if ( empty( $map[ $notice ] ) ) { + return; + } + + list( $class, $message ) = $map[ $notice ]; + printf( '

%2$s

', esc_attr( $class ), esc_html( $message ) ); + } + + private function redirect_with_notice( string $notice ): void { + $url = add_query_arg( + array( + 'page' => 'kgv-role-manager', + 'kgv_rm_notice' => $notice, + ), + admin_url( 'users.php' ) + ); + + wp_safe_redirect( $url ); + exit; + } + + private function get_all_capabilities(): array { + global $wp_post_types, $wp_taxonomies; + + $caps = array( + 'read', + 'level_0', + 'level_1', + 'level_2', + 'level_3', + 'level_4', + 'level_5', + 'level_6', + 'level_7', + 'level_8', + 'level_9', + 'level_10', + 'edit_posts', + 'edit_others_posts', + 'edit_published_posts', + 'publish_posts', + 'delete_posts', + 'delete_others_posts', + 'delete_published_posts', + 'delete_private_posts', + 'edit_private_posts', + 'read_private_posts', + 'upload_files', + 'manage_categories', + 'moderate_comments', + 'edit_pages', + 'edit_others_pages', + 'edit_published_pages', + 'publish_pages', + 'delete_pages', + 'delete_others_pages', + 'delete_published_pages', + 'delete_private_pages', + 'edit_private_pages', + 'read_private_pages', + 'read_private_posts', + 'list_users', + 'create_users', + 'edit_users', + 'delete_users', + 'promote_users', + 'remove_users', + 'manage_options', + 'switch_themes', + 'edit_theme_options', + 'activate_plugins', + 'edit_plugins', + 'install_plugins', + 'update_plugins', + 'delete_plugins', + 'install_themes', + 'update_themes', + 'delete_themes', + 'customize', + 'unfiltered_html', + 'unfiltered_upload', + 'edit_dashboard', + 'import', + 'export', + 'manage_links', + 'manage_privacy_options', + 'edit_files', + 'update_core', + 'manage_network', + 'setup_network', + 'create_sites', + 'delete_sites', + 'manage_network_users', + 'manage_network_plugins', + 'manage_network_themes', + 'manage_network_options', + ); + + $roles = wp_roles(); + if ( $roles instanceof WP_Roles ) { + foreach ( $roles->roles as $role_data ) { + if ( empty( $role_data['capabilities'] ) || ! is_array( $role_data['capabilities'] ) ) { + continue; + } + $caps = array_merge( $caps, array_keys( $role_data['capabilities'] ) ); + } + } + + if ( is_array( $wp_post_types ) ) { + foreach ( $wp_post_types as $post_type ) { + if ( empty( $post_type->cap ) ) { + continue; + } + foreach ( (array) $post_type->cap as $cap_name ) { + if ( is_string( $cap_name ) ) { + $caps[] = $cap_name; + } + } + } + } + + if ( is_array( $wp_taxonomies ) ) { + foreach ( $wp_taxonomies as $taxonomy ) { + if ( empty( $taxonomy->cap ) ) { + continue; + } + foreach ( (array) $taxonomy->cap as $cap_name ) { + if ( is_string( $cap_name ) ) { + $caps[] = $cap_name; + } + } + } + } + + $caps = array_values( array_unique( array_filter( $caps, 'is_string' ) ) ); + natcasesort( $caps ); + + return array_values( $caps ); + } + + private function group_capabilities( array $caps ): array { + $groups = array( + 'Inhalt' => array(), + 'Medien' => array(), + 'Kommentare' => array(), + 'Benutzer' => array(), + 'Design' => array(), + 'Plugins' => array(), + 'Einstellungen' => array(), + 'Netzwerk / Sonstiges' => array(), + 'Weitere' => array(), + ); + + foreach ( $caps as $cap ) { + if ( preg_match( '/^(edit_|publish_|delete_|read_private_|manage_categories)/', $cap ) ) { + $groups['Inhalt'][] = $cap; + } elseif ( preg_match( '/^(upload_files|unfiltered_upload)/', $cap ) ) { + $groups['Medien'][] = $cap; + } elseif ( preg_match( '/^(moderate_comments)/', $cap ) ) { + $groups['Kommentare'][] = $cap; + } elseif ( preg_match( '/^(list_users|create_users|edit_users|delete_users|promote_users|remove_users)/', $cap ) ) { + $groups['Benutzer'][] = $cap; + } elseif ( preg_match( '/^(switch_themes|edit_theme_options|customize|edit_files)/', $cap ) ) { + $groups['Design'][] = $cap; + } elseif ( preg_match( '/^(activate_plugins|edit_plugins|install_plugins|update_plugins|delete_plugins)/', $cap ) ) { + $groups['Plugins'][] = $cap; + } elseif ( preg_match( '/^(manage_options|manage_privacy_options|import|export|update_core)/', $cap ) ) { + $groups['Einstellungen'][] = $cap; + } elseif ( preg_match( '/^(manage_network|setup_network|create_sites|delete_sites|manage_network_users|manage_network_plugins|manage_network_themes|manage_network_options)/', $cap ) ) { + $groups['Netzwerk / Sonstiges'][] = $cap; + } else { + $groups['Weitere'][] = $cap; + } + } + + return array_filter( $groups ); + } + + public function handle_save_role(): void { + if ( ! current_user_can( 'promote_users' ) ) { + wp_die( esc_html__( 'Keine Berechtigung.', 'kgv-role-manager' ) ); + } + + check_admin_referer( 'kgv_rm_save_role' ); + + $mode = isset( $_POST['mode'] ) ? sanitize_key( wp_unslash( $_POST['mode'] ) ) : 'create'; + $role_name = isset( $_POST['role_name'] ) ? sanitize_text_field( wp_unslash( $_POST['role_name'] ) ) : ''; + $role_slug = isset( $_POST['role_slug'] ) ? sanitize_key( wp_unslash( $_POST['role_slug'] ) ) : ''; + $source_role = isset( $_POST['source_role'] ) ? sanitize_key( wp_unslash( $_POST['source_role'] ) ) : ''; + $caps_input = isset( $_POST['caps'] ) && is_array( $_POST['caps'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['caps'] ) ) : array(); + + if ( '' === $role_name ) { + $this->redirect_with_notice( 'invalid' ); + } + + $roles = wp_roles(); + if ( ! ( $roles instanceof WP_Roles ) ) { + $this->redirect_with_notice( 'failed' ); + } + + $all_caps = $this->get_all_capabilities(); + $caps = array_fill_keys( array_intersect( $all_caps, $caps_input ), true ); + + if ( 'edit' === $mode ) { + $edit_role = isset( $_POST['edit_role'] ) ? sanitize_key( wp_unslash( $_POST['edit_role'] ) ) : ''; + if ( '' === $edit_role || empty( $roles->roles[ $edit_role ] ) ) { + $this->redirect_with_notice( 'invalid' ); + } + + remove_role( $edit_role ); + $result = add_role( $edit_role, $role_name, $caps ); + if ( ! $result ) { + $this->redirect_with_notice( 'failed' ); + } + + $this->redirect_with_notice( 'saved' ); + } + + if ( '' === $role_slug ) { + $role_slug = sanitize_key( str_replace( ' ', '_', strtolower( $role_name ) ) ); + } + + if ( '' === $role_slug ) { + $this->redirect_with_notice( 'invalid' ); + } + + if ( ! empty( $roles->roles[ $role_slug ] ) ) { + $this->redirect_with_notice( 'exists' ); + } + + if ( $source_role && ! empty( $roles->roles[ $source_role ]['capabilities'] ) && empty( $caps ) ) { + $caps = array_map( '__return_true', $roles->roles[ $source_role ]['capabilities'] ); + } + + $result = add_role( $role_slug, $role_name, $caps ); + if ( ! $result ) { + $this->redirect_with_notice( 'failed' ); + } + + $this->redirect_with_notice( 'saved' ); + } + + public function handle_delete_role(): void { + if ( ! current_user_can( 'promote_users' ) ) { + wp_die( esc_html__( 'Keine Berechtigung.', 'kgv-role-manager' ) ); + } + + check_admin_referer( 'kgv_rm_delete_role' ); + + $role = isset( $_POST['role'] ) ? sanitize_key( wp_unslash( $_POST['role'] ) ) : ''; + if ( '' === $role ) { + $this->redirect_with_notice( 'invalid' ); + } + + if ( in_array( $role, $this->protected_roles, true ) ) { + $this->redirect_with_notice( 'core' ); + } + + remove_role( $role ); + $this->redirect_with_notice( 'deleted' ); + } + + public function render_page(): void { + if ( ! current_user_can( 'promote_users' ) ) { + wp_die( esc_html__( 'Keine Berechtigung.', 'kgv-role-manager' ) ); + } + + $roles = wp_roles(); + $all_roles = $roles instanceof WP_Roles ? $roles->roles : array(); + $edit_role = isset( $_GET['edit_role'] ) ? sanitize_key( wp_unslash( $_GET['edit_role'] ) ) : ''; + $edit_data = ( $edit_role && ! empty( $all_roles[ $edit_role ] ) ) ? $all_roles[ $edit_role ] : null; + $all_caps = $this->get_all_capabilities(); + $cap_groups = $this->group_capabilities( $all_caps ); + $selected = $edit_data && ! empty( $edit_data['capabilities'] ) ? array_keys( array_filter( $edit_data['capabilities'] ) ) : array(); + ?> +
+

+

+ +
+
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+

+ +
+ $group_caps ) : ?> +
+

+
+ + + +
+
+ +
+ + +
+
+ +
+

+ + + + + + + + + + + $role_data ) : ?> + + + + + + + + + +
+ 'kgv-role-manager', + 'edit_role' => $role_key, + ), + admin_url( 'users.php' ) + ); + ?> + + protected_roles, true ) ) : ?> +
+ + + + +
+ +
+
+
+
+