451 lines
21 KiB
PHP
Executable File
451 lines
21 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Plugin Name: KGV Rollen Manager
|
|
* Description: Erstellt zusätzliche WordPress-Rollen und vergibt Rechte direkt im Backend.
|
|
* Version: 1.0.3
|
|
* Author: Ronny Grobel
|
|
* Author URI: https://apex-project.de/
|
|
* Text Domain: kgv-role-manager
|
|
* Plugin URI: https://apex-project.de/
|
|
* Update URI: https://git.apex-project.de/Wordpress_Plugins/KGV-Role-Manager
|
|
* Gitea Plugin URI: https://git.apex-project.de/Wordpress_Plugins/KGV-Role-Manager
|
|
* Requires Plugins: KGV-Updater
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
final class KGV_Rollen_Manager {
|
|
private array $protected_roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
|
|
|
|
public function __construct() {
|
|
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
|
add_action( 'admin_post_kgv_rm_save_role', array( $this, 'handle_save_role' ) );
|
|
add_action( 'admin_post_kgv_rm_delete_role', array( $this, 'handle_delete_role' ) );
|
|
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
|
}
|
|
|
|
public function admin_menu(): void {
|
|
add_users_page(
|
|
__( 'Rollen Manager', 'kgv-role-manager' ),
|
|
__( 'Rollen Manager', 'kgv-role-manager' ),
|
|
'promote_users',
|
|
'kgv-role-manager',
|
|
array( $this, 'render_page' )
|
|
);
|
|
}
|
|
|
|
public function admin_notices(): void {
|
|
if ( ! current_user_can( 'promote_users' ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( empty( $_GET['page'] ) || 'kgv-role-manager' !== $_GET['page'] || empty( $_GET['kgv_rm_notice'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$notice = sanitize_key( wp_unslash( $_GET['kgv_rm_notice'] ) );
|
|
$map = array(
|
|
'saved' => 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( '<div class="notice notice-%1$s is-dismissible"><p>%2$s</p></div>', 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();
|
|
?>
|
|
<div class="wrap">
|
|
<h1><?php esc_html_e( 'Rollen Manager', 'kgv-role-manager' ); ?></h1>
|
|
<p><?php esc_html_e( 'Hier legst du eigene Rollen an und weist gezielt Rechte zu. Standardrollen können bearbeitet, aber hier nicht gelöscht werden.', 'kgv-role-manager' ); ?></p>
|
|
|
|
<div style="display:grid;grid-template-columns:minmax(340px,460px) minmax(0,1fr);gap:24px;align-items:start;">
|
|
<div style="background:#fff;border:1px solid #dcdcde;padding:20px;">
|
|
<h2 style="margin-top:0;"><?php echo $edit_data ? esc_html__( 'Rolle bearbeiten', 'kgv-role-manager' ) : esc_html__( 'Neue Rolle anlegen', 'kgv-role-manager' ); ?></h2>
|
|
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
|
<input type="hidden" name="action" value="kgv_rm_save_role">
|
|
<input type="hidden" name="mode" value="<?php echo $edit_data ? 'edit' : 'create'; ?>">
|
|
<?php if ( $edit_data ) : ?>
|
|
<input type="hidden" name="edit_role" value="<?php echo esc_attr( $edit_role ); ?>">
|
|
<?php endif; ?>
|
|
<?php wp_nonce_field( 'kgv_rm_save_role' ); ?>
|
|
|
|
<table class="form-table" role="presentation">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row"><label for="role_name"><?php esc_html_e( 'Rollenname', 'kgv-role-manager' ); ?></label></th>
|
|
<td><input name="role_name" id="role_name" type="text" class="regular-text" required value="<?php echo esc_attr( $edit_data['name'] ?? '' ); ?>"></td>
|
|
</tr>
|
|
<?php if ( ! $edit_data ) : ?>
|
|
<tr>
|
|
<th scope="row"><label for="role_slug"><?php esc_html_e( 'Rollen-Slug', 'kgv-role-manager' ); ?></label></th>
|
|
<td>
|
|
<input name="role_slug" id="role_slug" type="text" class="regular-text" value="">
|
|
<p class="description"><?php esc_html_e( 'Nur Kleinbuchstaben, Zahlen und Unterstriche. Leer lassen = automatisch aus dem Namen erzeugen.', 'kgv-role-manager' ); ?></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><label for="source_role"><?php esc_html_e( 'Vorlage', 'kgv-role-manager' ); ?></label></th>
|
|
<td>
|
|
<select name="source_role" id="source_role">
|
|
<option value=""><?php esc_html_e( 'Keine Vorlage', 'kgv-role-manager' ); ?></option>
|
|
<?php foreach ( $all_roles as $role_key => $role_data ) : ?>
|
|
<option value="<?php echo esc_attr( $role_key ); ?>"><?php echo esc_html( translate_user_role( $role_data['name'] ) . ' (' . $role_key . ')' ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<p class="description"><?php esc_html_e( 'Wird nur verwendet, wenn du unten keine Rechte manuell auswählst.', 'kgv-role-manager' ); ?></p>
|
|
</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h3><?php esc_html_e( 'Rechte', 'kgv-role-manager' ); ?></h3>
|
|
<p><?php esc_html_e( 'Setze nur die Rechte, die wirklich nötig sind. Zu viele Rechte machen die Rolle faktisch zum Administrator.', 'kgv-role-manager' ); ?></p>
|
|
|
|
<div style="max-height:520px;overflow:auto;border:1px solid #dcdcde;padding:16px;background:#f9f9f9;">
|
|
<?php foreach ( $cap_groups as $group_label => $group_caps ) : ?>
|
|
<div style="margin-bottom:18px;">
|
|
<h4 style="margin:0 0 10px;"><?php echo esc_html( $group_label ); ?></h4>
|
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px 16px;">
|
|
<?php foreach ( $group_caps as $cap ) : ?>
|
|
<label style="display:flex;gap:8px;align-items:flex-start;">
|
|
<input type="checkbox" name="caps[]" value="<?php echo esc_attr( $cap ); ?>" <?php checked( in_array( $cap, $selected, true ) ); ?>>
|
|
<span><code><?php echo esc_html( $cap ); ?></code></span>
|
|
</label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<?php submit_button( $edit_data ? __( 'Rolle speichern', 'kgv-role-manager' ) : __( 'Rolle anlegen', 'kgv-role-manager' ) ); ?>
|
|
</form>
|
|
</div>
|
|
|
|
<div style="background:#fff;border:1px solid #dcdcde;padding:20px;">
|
|
<h2 style="margin-top:0;"><?php esc_html_e( 'Vorhandene Rollen', 'kgv-role-manager' ); ?></h2>
|
|
<table class="widefat striped">
|
|
<thead>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Name', 'kgv-role-manager' ); ?></th>
|
|
<th><?php esc_html_e( 'Slug', 'kgv-role-manager' ); ?></th>
|
|
<th><?php esc_html_e( 'Rechte', 'kgv-role-manager' ); ?></th>
|
|
<th><?php esc_html_e( 'Aktionen', 'kgv-role-manager' ); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ( $all_roles as $role_key => $role_data ) : ?>
|
|
<?php $role_caps = ! empty( $role_data['capabilities'] ) ? count( array_filter( $role_data['capabilities'] ) ) : 0; ?>
|
|
<tr>
|
|
<td><?php echo esc_html( translate_user_role( $role_data['name'] ) ); ?></td>
|
|
<td><code><?php echo esc_html( $role_key ); ?></code></td>
|
|
<td><?php echo esc_html( (string) $role_caps ); ?></td>
|
|
<td>
|
|
<?php
|
|
$edit_url = add_query_arg(
|
|
array(
|
|
'page' => 'kgv-role-manager',
|
|
'edit_role' => $role_key,
|
|
),
|
|
admin_url( 'users.php' )
|
|
);
|
|
?>
|
|
<a class="button button-small" href="<?php echo esc_url( $edit_url ); ?>"><?php esc_html_e( 'Bearbeiten', 'kgv-role-manager' ); ?></a>
|
|
<?php if ( ! in_array( $role_key, $this->protected_roles, true ) ) : ?>
|
|
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="display:inline-block;margin-left:6px;" onsubmit="return confirm('<?php echo esc_js( __( 'Rolle wirklich löschen?', 'kgv-role-manager' ) ); ?>');">
|
|
<input type="hidden" name="action" value="kgv_rm_delete_role">
|
|
<input type="hidden" name="role" value="<?php echo esc_attr( $role_key ); ?>">
|
|
<?php wp_nonce_field( 'kgv_rm_delete_role' ); ?>
|
|
<button type="submit" class="button button-small button-link-delete"><?php esc_html_e( 'Löschen', 'kgv-role-manager' ); ?></button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
new KGV_Rollen_Manager();
|