array(), 'total' => 0 ); } $args = array( 'number' => self::PER_PAGE, 'paged' => max( 1, (int) $paged ), 'orderby' => 'display_name', 'order' => 'ASC', 'count_total' => true, ); if ( '' !== $q ) { $args['search'] = '*' . $q . '*'; $args['search_columns'] = array( 'user_login', 'user_email', 'display_name', 'user_nicename' ); } if ( '' !== $role ) { $args['role'] = $role; } $query = new WP_User_Query( $args ); return array( 'users' => (array) $query->get_results(), 'total' => (int) $query->get_total(), ); } public static function grid_staff() { $out = array(); $delegated = AIEO_User_Roles::delegations(); foreach ( AIEO_User_Roles::staff_roles() as $slug => $name ) { $obj = get_role( $slug ); if ( ! $obj || $obj->has_cap( 'promote_users' ) ) { continue; } $reaches = $obj->has_cap( defined( 'AIEO_CAPABILITY' ) ? AIEO_CAPABILITY : 'aieo_access' ) || $obj->has_cap( 'manage_woocommerce' ) || $obj->has_cap( 'edit_pages' ); if ( $reaches || isset( $delegated[ $slug ] ) ) { $out[ $slug ] = $name; } } return $out; } public static function grid_roles() { return array_intersect_key( AIEO_Safe_Roles::roles(), AIEO_User_Roles::assignable() ); } public static function describe_change( array $r ) { $names = static function ( array $slugs ) { return implode( ', ', array_map( array( __CLASS__, 'role_name' ), $slugs ) ); }; $parts = array(); if ( $r['added'] ) { $parts[] = sprintf( __( 'Added: %s.', 'ai-eshop-optimizer' ), $names( $r['added'] ) ); } if ( $r['removed'] ) { $parts[] = sprintf( __( 'Removed: %s.', 'ai-eshop-optimizer' ), $names( $r['removed'] ) ); } if ( '' !== $r['kept'] ) { $parts[] = sprintf( __( 'An account keeps one role, so it has %s.', 'ai-eshop-optimizer' ), self::role_name( $r['kept'] ) ); } return $parts ? implode( ' ', $parts ) : __( 'Nothing changed.', 'ai-eshop-optimizer' ); } public function ajax_save_account() { AIEO_DMM::verify_ajax_request(); $user_id = isset( $_POST['user_id'] ) ? absint( wp_unslash( $_POST['user_id'] ) ) : 0; $roles = isset( $_POST['roles'] ) && is_array( $_POST['roles'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['roles'] ) ) : array(); if ( ! AIEO_User_Roles::may_manage( $user_id ) ) { wp_send_json_error( array( 'message' => __( 'Not saved: you do not manage this account’s roles.', 'ai-eshop-optimizer' ) ) ); } $r = AIEO_User_Roles::set( $user_id, $roles, 'manual' ); if ( is_wp_error( $r ) ) { wp_send_json_error( array( 'message' => sprintf( __( 'Not saved: %s', 'ai-eshop-optimizer' ), $r->get_error_message() ) ) ); } wp_send_json_success( array( 'message' => self::describe_change( $r ) ) ); } public function ajax_save_delegations() { AIEO_DMM::verify_ajax_request(); if ( ! AIEO_User_Roles::is_role_admin() ) { wp_send_json_error( array( 'message' => __( 'Not saved: only an administrator decides who may give roles.', 'ai-eshop-optimizer' ) ) ); } $posted = isset( $_POST['delegate'] ) && is_array( $_POST['delegate'] ) ? wp_unslash( $_POST['delegate'] ) : array(); $errors = array(); foreach ( array_keys( self::grid_staff() ) as $staff ) { $want = isset( $posted[ $staff ] ) ? array_map( 'sanitize_key', (array) $posted[ $staff ] ) : array(); $obj = get_role( $staff ); foreach ( array_keys( self::grid_roles() ) as $role ) { $on = in_array( $role, $want, true ); if ( $obj && $obj->has_cap( AIEO_User_Roles::cap( $role ) ) === $on ) { continue; } $r = AIEO_User_Roles::set_delegation( $staff, $role, $on ); if ( is_wp_error( $r ) ) { $errors[] = $r->get_error_message(); } } } if ( $errors ) { wp_send_json_error( array( 'message' => sprintf( __( 'Not saved: %s', 'ai-eshop-optimizer' ), implode( ' ', array_unique( $errors ) ) ) ) ); } wp_send_json_success( array( 'message' => __( 'Saved.', 'ai-eshop-optimizer' ) ) ); } public function handle_role_form() { check_admin_referer( self::POST_ACTION ); if ( ! current_user_can( defined( 'AIEO_CAPABILITY' ) ? AIEO_CAPABILITY : 'manage_options' ) || ! AIEO_User_Roles::is_role_admin() ) { wp_die( esc_html__( 'Sorry, only an administrator changes the shop’s roles.', 'ai-eshop-optimizer' ), 403 ); } $op = isset( $_POST['op'] ) ? sanitize_key( wp_unslash( $_POST['op'] ) ) : ''; $role = isset( $_POST['role'] ) ? sanitize_key( wp_unslash( $_POST['role'] ) ) : ''; $name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; if ( 'create' === $op ) { $slug = isset( $_POST['slug'] ) ? sanitize_key( wp_unslash( $_POST['slug'] ) ) : ''; $r = AIEO_User_Roles::create_role( $name, $slug ); $done = is_wp_error( $r ) ? '' : sprintf( __( 'Made the customer role %s. Give it to staff to manage below, if they should.', 'ai-eshop-optimizer' ), $name ); } elseif ( 'rename' === $op ) { $old = self::role_name( $role ); $r = AIEO_User_Roles::rename_role( $role, $name ); $done = is_wp_error( $r ) ? '' : sprintf( __( 'Renamed %1$s to %2$s.', 'ai-eshop-optimizer' ), $old, $name ); } elseif ( 'delete' === $op ) { $old = self::role_name( $role ); $r = AIEO_User_Roles::delete_role( $role ); $done = is_wp_error( $r ) ? '' : sprintf( __( 'Deleted the role %s.', 'ai-eshop-optimizer' ), $old ); } else { $r = new WP_Error( 'aieo_roles_op', __( 'Nothing was asked.', 'ai-eshop-optimizer' ) ); } set_transient( self::NOTICE . get_current_user_id(), is_wp_error( $r ) ? array( 'destructive', $r->get_error_message() ) : array( 'success', $done ), MINUTE_IN_SECONDS ); wp_safe_redirect( $this->get_url() . '#aieo-card-user-roles-customer-roles' ); exit; } public function render_subtab() { if ( ! AIEO_User_Roles::can_use() ) { echo \Rooster\Admin\Ui::notice( esc_html__( 'Roles are managed by an administrator, and by staff an administrator lets give customer roles.', 'ai-eshop-optimizer' ), 'info' ); return; } $q = isset( $_GET['q'] ) ? sanitize_text_field( wp_unslash( $_GET['q'] ) ) : ''; $role = isset( $_GET['role'] ) ? sanitize_key( wp_unslash( $_GET['role'] ) ) : ''; $paged = isset( $_GET['paged'] ) ? max( 1, absint( wp_unslash( $_GET['paged'] ) ) ) : 1; $user = isset( $_GET['user'] ) ? get_userdata( absint( wp_unslash( $_GET['user'] ) ) ) : false; $notice = get_transient( self::NOTICE . get_current_user_id() ); if ( is_array( $notice ) ) { delete_transient( self::NOTICE . get_current_user_id() ); echo \Rooster\Admin\Ui::notice( esc_html( (string) $notice[1] ), (string) $notice[0] ); } $counts = AIEO_User_Roles::counts(); if ( function_exists( 'rooster_admin_band_open' ) ) { rooster_admin_band_open( array( 'cols' => 1 ) ); } $this->render_find( $q, $role, $paged, $counts ); if ( $user instanceof WP_User ) { $this->render_account( $user ); } if ( function_exists( 'rooster_admin_band_close' ) ) { rooster_admin_band_close(); } if ( AIEO_User_Roles::is_role_admin() ) { if ( function_exists( 'rooster_admin_band_open' ) ) { rooster_admin_band_open( array( 'cols' => 1 ) ); } $this->render_delegations(); $this->render_catalogue( $counts ); if ( function_exists( 'rooster_admin_band_close' ) ) { rooster_admin_band_close(); } } } private function render_find( $q, $role, $paged, array $counts ) { list( $open, $close ) = AIEO_DMM_UI::card( array( 'anchor' => 'user-roles-find', 'icon' => 'users', 'title' => __( 'Find an account', 'ai-eshop-optimizer' ), 'description' => __( 'Search by name, e-mail or username, or list the accounts that hold a role; open one to see every role it holds and change the ones you may.', 'ai-eshop-optimizer' ), ) ); echo $open; $roles = array( '' => __( 'Any role', 'ai-eshop-optimizer' ) ); foreach ( array_keys( wp_roles()->roles ) as $slug ) { $roles[ (string) $slug ] = self::role_name( (string) $slug ); } echo '
'; echo ''; echo ''; echo \Rooster\Admin\Ui::filter( __( 'Name, e-mail or username', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::input( 'q', $q, array( 'id' => 'aieo-ur-q', 'type' => 'search', 'medium' => true ) ), 'aieo-ur-q' ); echo \Rooster\Admin\Ui::filter( __( 'Holding the role', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::select( 'role', $roles, $role, array( 'id' => 'aieo-ur-role', 'counts' => $counts ) ), 'aieo-ur-role' ); echo '
' . \Rooster\Admin\Ui::button( __( 'Search', 'ai-eshop-optimizer' ), array( 'variant' => 'primary', 'type' => 'submit' ) ) . '
'; echo '
'; if ( '' !== $q || '' !== $role ) { $found = self::search( $q, $role, $paged ); $base = add_query_arg( array( 'q' => $q, 'role' => $role ), $this->get_url() ); $rows = array(); foreach ( $found['users'] as $u ) { $badges = ''; foreach ( (array) $u->roles as $slug ) { $badges .= \Rooster\Admin\Ui::badge( self::role_name( (string) $slug ), AIEO_Safe_Roles::is_safe( (string) $slug ) ? 'info' : 'mono', array( 'sm' => true ) ) . ' '; } $open_url = add_query_arg( 'user', (int) $u->ID, $base ) . '#aieo-card-user-roles-account'; $rows[] = array( '_name' => (string) $u->display_name, 'name' => '' . esc_html( (string) $u->display_name ) . '', 'email' => (string) $u->user_email, 'login' => (string) $u->user_login, 'roles' => '' !== $badges ? $badges : \Rooster\Admin\Ui::badge( __( 'No role', 'ai-eshop-optimizer' ), 'warning', array( 'sm' => true ) ), '_actions' => \Rooster\Admin\Ui::row_actions( array( array( 'label' => AIEO_User_Roles::may_manage( (int) $u->ID ) ? __( 'Change roles', 'ai-eshop-optimizer' ) : __( 'See roles', 'ai-eshop-optimizer' ), 'url' => $open_url, ), ) ), ); } echo \Rooster\Admin\Ui::table( array( array( 'key' => 'name', 'label' => __( 'Name', 'ai-eshop-optimizer' ), 'type' => 'html' ), array( 'key' => 'email', 'label' => __( 'E-mail', 'ai-eshop-optimizer' ) ), array( 'key' => 'login', 'label' => __( 'Username', 'ai-eshop-optimizer' ), 'type' => 'code', 'priority' => 'low' ), array( 'key' => 'roles', 'label' => __( 'Roles', 'ai-eshop-optimizer' ), 'type' => 'html' ), ), $rows, array( 'id' => 'aieo-ur-found', 'empty' => \Rooster\Admin\States::state( 'no-results', array( 'compact' => true, 'title' => __( 'No account matches.', 'ai-eshop-optimizer' ), 'text' => __( 'Check the spelling, or search with part of the e-mail address.', 'ai-eshop-optimizer' ) ) ), 'footer' => $found['total'] > self::PER_PAGE ? \Rooster\Admin\Ui::pager( $paged, (int) ceil( $found['total'] / self::PER_PAGE ), static fn( int $p ): string => add_query_arg( 'paged', $p, $base ), array( 'total' => $found['total'], 'per_page' => self::PER_PAGE ) ) : '', ) ); } echo $close; } private function render_account( WP_User $user ) { $form = 'aieo-card-user-roles-account-form'; $manage = AIEO_User_Roles::may_manage( (int) $user->ID ); list( $open, $close ) = AIEO_DMM_UI::card( array( 'anchor' => 'user-roles-account', 'icon' => 'user-cog', 'title' => __( 'Account roles', 'ai-eshop-optimizer' ), 'footer' => $manage ? \Rooster\Admin\States::save_button( $form, array( 'label' => __( 'Save roles', 'ai-eshop-optimizer' ) ) ) : '', ) ); echo $open; $facts = array( array( 'label' => __( 'Name', 'ai-eshop-optimizer' ), 'value' => (string) $user->display_name ), array( 'label' => __( 'E-mail', 'ai-eshop-optimizer' ), 'value' => (string) $user->user_email ), array( 'label' => __( 'Username', 'ai-eshop-optimizer' ), 'code' => (string) $user->user_login ), ); if ( current_user_can( 'edit_user', (int) $user->ID ) ) { $facts[] = array( 'label' => __( 'Profile', 'ai-eshop-optimizer' ), 'html' => '' . esc_html__( 'Edit in WordPress', 'ai-eshop-optimizer' ) . '' ); } echo \Rooster\Admin\Ui::facts( $facts ); $notes = AIEO_User_Roles::notes(); $changeable = array( 'customer' => array(), 'staff' => array() ); $described = array(); $locked = array(); foreach ( array_keys( wp_roles()->roles ) as $slug ) { $slug = (string) $slug; $ok = AIEO_User_Roles::check( (int) $user->ID, $slug ); if ( true === $ok ) { $changeable[ AIEO_Safe_Roles::is_safe( $slug ) ? 'customer' : 'staff' ][ $slug ] = self::role_name( $slug ); if ( ! empty( $notes[ $slug ] ) ) { $described[ $slug ] = implode( ' · ', (array) $notes[ $slug ] ); } } elseif ( in_array( $slug, (array) $user->roles, true ) ) { $locked[ $slug ] = $ok->get_error_message(); } } $held = array_values( (array) $user->roles ); $fields = ''; foreach ( array( 'customer' => __( 'Customer roles', 'ai-eshop-optimizer' ), 'staff' => __( 'Staff roles', 'ai-eshop-optimizer' ), ) as $kind => $label ) { if ( $changeable[ $kind ] ) { $fields .= \Rooster\Admin\Ui::field_row( array( 'group' => true, 'label' => $label, 'control' => \Rooster\Admin\Ui::checks( 'roles', $changeable[ $kind ], $held, array( 'grid' => true, 'descriptions' => array_intersect_key( $described, $changeable[ $kind ] ) ) ), 'help' => 'customer' === $kind ? __( 'Several roles at once are fine: an account has the prices and access of each, and keeps at least one role.', 'ai-eshop-optimizer' ) : __( 'A staff role gives access to the shop’s administration.', 'ai-eshop-optimizer' ), ) ); } } if ( '' !== $fields ) { echo AIEO_DMM_UI::card_form( 'aieo_dmm_user_roles_save', 'user_roles_account', $form, '
' . $fields . '
', array( 'hidden' => array( 'user_id' => (int) $user->ID ) ) ); } else { $why = AIEO_User_Roles::check( (int) $user->ID, (string) key( AIEO_User_Roles::assignable() ) ); echo \Rooster\Admin\Ui::notice( esc_html( is_wp_error( $why ) ? $why->get_error_message() : __( 'An administrator manages this account’s roles.', 'ai-eshop-optimizer' ) ), 'info', array( 'inline' => true ) ); } if ( $locked ) { $items = ''; foreach ( $locked as $slug => $why ) { $items .= '
  • ' . \Rooster\Admin\Ui::badge( self::role_name( $slug ), 'mono', array( 'sm' => true ) ) . ' ' . esc_html( $why ) . '
  • '; } echo \Rooster\Admin\Ui::field_row( array( 'group' => true, 'label' => __( 'Its other roles', 'ai-eshop-optimizer' ), 'control' => '' ) ); } $history = class_exists( 'AIEO_Role_Log' ) ? AIEO_Role_Log::history( (int) $user->ID, self::HISTORY ) : array(); $rows = array(); foreach ( $history as $h ) { $by = $h['actor_id'] > 0 ? get_userdata( $h['actor_id'] ) : false; $rows[] = array( 'when' => wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), (int) strtotime( $h['created_at'] . ' UTC' ) ), 'change' => sprintf( 'add' === $h['action'] ? __( 'Gained %s', 'ai-eshop-optimizer' ) : __( 'Lost %s', 'ai-eshop-optimizer' ), self::role_name( (string) $h['role'] ) ), 'by' => $by ? (string) $by->display_name : __( 'Nobody signed in', 'ai-eshop-optimizer' ), 'through' => AIEO_Role_Log::source_label( (string) $h['source'] ), ); } echo '

    ' . esc_html__( 'History', 'ai-eshop-optimizer' ) . '

    '; echo \Rooster\Admin\Ui::table( array( array( 'key' => 'when', 'label' => __( 'Date', 'ai-eshop-optimizer' ) ), array( 'key' => 'change', 'label' => __( 'Change', 'ai-eshop-optimizer' ) ), array( 'key' => 'by', 'label' => __( 'By', 'ai-eshop-optimizer' ) ), array( 'key' => 'through', 'label' => __( 'Through', 'ai-eshop-optimizer' ) ), ), $rows, array( 'id' => 'aieo-ur-history', 'dense' => true, 'empty' => \Rooster\Admin\States::state( 'first-use', array( 'compact' => true, 'title' => __( 'No role change recorded yet.', 'ai-eshop-optimizer' ), 'text' => __( 'Changes are recorded from Rooster One 11.3.6 on, whoever makes them.', 'ai-eshop-optimizer' ) ) ), ) ); echo $close; } private function render_delegations() { $form = 'aieo-card-user-roles-delegations-form'; $staff = self::grid_staff(); $roles = self::grid_roles(); list( $open, $close ) = AIEO_DMM_UI::card( array( 'anchor' => 'user-roles-delegations', 'icon' => 'shield-check', 'title' => __( 'Who may give which role', 'ai-eshop-optimizer' ), 'description' => __( 'Staff give and take the customer roles ticked for their role, on customer accounts only and never on their own; administrators give any role. Only a customer role, one that gives no power over the shop, can be ticked.', 'ai-eshop-optimizer' ), 'footer' => $staff && $roles ? \Rooster\Admin\States::save_button( $form ) : '', ) ); echo $open; if ( ! $staff || ! $roles ) { echo \Rooster\Admin\Ui::notice( esc_html__( 'There is no staff role or no customer role to pair yet.', 'ai-eshop-optimizer' ), 'info', array( 'inline' => true ) ); } else { $delegated = AIEO_User_Roles::delegations(); $rows = ''; foreach ( $staff as $slug => $name ) { $rows .= \Rooster\Admin\Ui::field_row( array( 'group' => true, 'label' => $name, 'control' => \Rooster\Admin\Ui::checks( 'delegate[' . $slug . ']', $roles, (array) ( $delegated[ $slug ] ?? array() ), array( 'inline' => true ) ), ) ); } echo AIEO_DMM_UI::card_form( 'aieo_dmm_user_roles_delegate', 'user_roles_delegations', $form, '
    ' . $rows . '
    ' ); } echo $close; } private function render_catalogue( array $counts ) { list( $open, $close ) = AIEO_DMM_UI::card( array( 'anchor' => 'user-roles-customer-roles', 'icon' => 'tags', 'title' => __( 'The shop’s roles', 'ai-eshop-optimizer' ), 'flush' => true, 'description' => __( 'A customer role gives no power over the shop: it marks a group of customers, for Role Pricing, the Bonus card or a workflow. Staff roles are WordPress’s and the plugins’ own, and are not changed here.', 'ai-eshop-optimizer' ), ) ); echo $open; $notes = AIEO_User_Roles::notes(); $rows = array(); $renamable = array(); $deletable = array(); foreach ( wp_roles()->roles as $slug => $data ) { $slug = (string) $slug; $safe = AIEO_Safe_Roles::is_safe( $slug ); $count = (int) ( $counts[ $slug ] ?? 0 ); if ( $safe ) { $renamable[ $slug ] = self::role_name( $slug ); if ( array() === AIEO_User_Roles::why_keep( $slug ) ) { $deletable[ $slug ] = self::role_name( $slug ); } } $rows[] = array( '_name' => self::role_name( $slug ), 'name' => self::role_name( $slug ), 'slug' => $slug, 'kind' => array( 'label' => $safe ? __( 'Customer role', 'ai-eshop-optimizer' ) : __( 'Staff role', 'ai-eshop-optimizer' ), 'tone' => $safe ? 'info' : 'mono', ), 'accounts' => $count > 0 ? '' . esc_html( number_format_i18n( $count ) ) . '' : '0', 'notes' => implode( ' · ', (array) ( $notes[ $slug ] ?? array() ) ), ); } echo \Rooster\Admin\Ui::table( array( array( 'key' => 'name', 'label' => __( 'Role', 'ai-eshop-optimizer' ) ), array( 'key' => 'slug', 'label' => __( 'Slug', 'ai-eshop-optimizer' ), 'type' => 'code', 'priority' => 'low' ), array( 'key' => 'kind', 'label' => __( 'Kind', 'ai-eshop-optimizer' ), 'type' => 'status' ), array( 'key' => 'accounts', 'label' => __( 'Accounts', 'ai-eshop-optimizer' ), 'type' => 'html', 'align' => 'end' ), array( 'key' => 'notes', 'label' => __( 'Used by', 'ai-eshop-optimizer' ) ), ), $rows, array( 'id' => 'aieo-ur-roles' ) ); $post = esc_url( admin_url( 'admin-post.php' ) ); $hidden = static function ( $op ) { return '' . wp_nonce_field( self::POST_ACTION, '_wpnonce', true, false ); }; echo '

    ' . esc_html__( 'New customer role', 'ai-eshop-optimizer' ) . '

    '; echo '
    ' . $hidden( 'create' ) . \Rooster\Admin\Ui::filter( __( 'Name', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::input( 'name', '', array( 'id' => 'aieo-ur-new-name', 'medium' => true, 'required' => true ) ), 'aieo-ur-new-name' ) . \Rooster\Admin\Ui::filter( __( 'Slug (optional)', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::input( 'slug', '', array( 'id' => 'aieo-ur-new-slug', 'short' => true, 'code' => true, 'placeholder' => 'professional' ) ), 'aieo-ur-new-slug' ) . '
    ' . \Rooster\Admin\Ui::button( __( 'Make the role', 'ai-eshop-optimizer' ), array( 'variant' => 'primary', 'type' => 'submit' ) ) . '
    '; echo \Rooster\Admin\Guidance::text( __( 'The slug is how prices and settings name the role, and never changes: Latin letters, digits and underscores. A name in Latin letters makes one; a Greek name needs one typed.', 'ai-eshop-optimizer' ), 'guidance', array( 'question' => __( 'What is the slug?', 'ai-eshop-optimizer' ) ) ); if ( $renamable ) { echo '

    ' . esc_html__( 'Rename a customer role', 'ai-eshop-optimizer' ) . '

    '; echo '
    ' . $hidden( 'rename' ) . \Rooster\Admin\Ui::filter( __( 'Role', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::select( 'role', $renamable, '', array( 'id' => 'aieo-ur-rename-role' ) ), 'aieo-ur-rename-role' ) . \Rooster\Admin\Ui::filter( __( 'New name', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::input( 'name', '', array( 'id' => 'aieo-ur-rename-name', 'medium' => true, 'required' => true ) ), 'aieo-ur-rename-name' ) . '
    ' . \Rooster\Admin\Ui::button( __( 'Rename', 'ai-eshop-optimizer' ), array( 'type' => 'submit' ) ) . '
    '; } echo '

    ' . esc_html__( 'Delete a customer role', 'ai-eshop-optimizer' ) . '

    '; if ( $deletable ) { echo '
    ' . $hidden( 'delete' ) . \Rooster\Admin\Ui::filter( __( 'Role', 'ai-eshop-optimizer' ), \Rooster\Admin\Ui::select( 'role', $deletable, '', array( 'id' => 'aieo-ur-delete-role' ) ), 'aieo-ur-delete-role' ) . '
    ' . \Rooster\Admin\Ui::button( __( 'Delete the role', 'ai-eshop-optimizer' ), array( 'variant' => 'destructive', 'type' => 'submit' ) ) . '
    '; } echo \Rooster\Admin\Guidance::text( __( 'Only a customer role that no account holds and nothing uses (Role Pricing, the Bonus card, the signup, Gravity Forms, login security, another product) can be deleted.', 'ai-eshop-optimizer' ), 'guidance', array( 'question' => __( 'Which roles can be deleted?', 'ai-eshop-optimizer' ) ) ); echo $close; } }