get_names(); if ( '' === $role || ! isset( $roles[ $role ] ) ) { return new WP_Error( 'openstation_agent_invalid_role', __( 'Pick a valid WordPress role for the agent.', 'desktop-mode' ) ); } if ( '' === $slug ) { $slug = sanitize_title( $name ); } if ( '' === $slug ) { return new WP_Error( 'openstation_agent_invalid_slug', __( 'Agent slug could not be derived from the name.', 'desktop-mode' ) ); } $user_id = wp_insert_user( array( 'user_login' => openstation_agent_resolve_unique_login( $slug ), 'user_email' => openstation_agent_synthetic_email( $slug ), 'user_pass' => wp_generate_password( 64, true, true ), 'display_name' => $name, 'nickname' => $name, 'role' => $role, 'show_admin_bar_front' => false, ) ); if ( is_wp_error( $user_id ) ) { return $user_id; } update_user_meta( $user_id, OPENSTATION_AGENT_USER_MARKER_META, '1' ); return new WP_User( $user_id ); } /** * Delete an agent user. Definition meta rows die with the user * (`wp_delete_user()` removes all usermeta). Content the agent * authored is NOT reassigned — pass a reassign id when the caller * wants to keep it. * * @param int $user_id Agent user id. * @param int|null $reassign Optional user id to reassign authored content to. * @return true|WP_Error */ function openstation_agent_delete( $user_id, $reassign = null ) { if ( ! openstation_agent_is_agent( $user_id ) ) { return new WP_Error( 'openstation_agent_not_an_agent', __( 'User is not a OpenStation agent.', 'desktop-mode' ) ); } if ( ! function_exists( 'wp_delete_user' ) ) { require_once ABSPATH . 'wp-admin/includes/user.php'; } // On multisite `wp_delete_user()` only removes the user from the // CURRENT site — the network account (and the agent's meta with // it) lives on. The agent's whole identity is its wp user, so // deleting the agent means the network-wide delete. if ( is_multisite() ) { if ( ! function_exists( 'wpmu_delete_user' ) ) { require_once ABSPATH . 'wp-admin/includes/ms.php'; } if ( null !== $reassign ) { // `wpmu_delete_user()` has no reassign parameter; hand the // current site's content over before the user goes. wp_delete_user( (int) $user_id, $reassign ); } $deleted = wpmu_delete_user( (int) $user_id ); } else { $deleted = wp_delete_user( (int) $user_id, $reassign ); } if ( ! $deleted ) { return new WP_Error( 'openstation_agent_delete_failed', __( 'Could not delete the agent user.', 'desktop-mode' ) ); } /** * Fires after an agent is deleted. * * @param int $user_id Agent user id (row no longer exists when this fires). * @param int $actor_id User who deleted the agent. */ do_action( 'openstation_agent_deleted', (int) $user_id, get_current_user_id() ); return true; } // --------------------------------------------------------------------------- // Identity surface // // `openstation_agent_avatar_url()` lives in bootstrap.php: the WP // Explorer integration needs it for the entity icon and loads while the // feature flag is off, when this file does not. // --------------------------------------------------------------------------- /** * Substitute the bot glyph for agent avatars across the WP admin. * * @param array $args Args being assembled by `get_avatar_data()`. * @param int|string|WP_User|WP_Comment $id_or_email Identifier the caller passed. * @return array */ function openstation_agent_avatar( $args, $id_or_email ) { $user_id = 0; if ( is_numeric( $id_or_email ) ) { $user_id = (int) $id_or_email; } elseif ( $id_or_email instanceof WP_User ) { $user_id = (int) $id_or_email->ID; } elseif ( $id_or_email instanceof WP_Comment ) { $user_id = (int) $id_or_email->user_id; } elseif ( is_string( $id_or_email ) && is_email( $id_or_email ) ) { $user = get_user_by( 'email', $id_or_email ); if ( $user ) { $user_id = (int) $user->ID; } } if ( $user_id > 0 && openstation_agent_is_agent( $user_id ) ) { $args['url'] = openstation_agent_avatar_url( $user_id ); $args['found_avatar'] = true; } return $args; } add_filter( 'pre_get_avatar_data', 'openstation_agent_avatar', 10, 2 ); /** * Add a "Type" column to the wp-admin Users list that labels agents. * * @param string[] $columns Existing column id => label map. * @return string[] */ function openstation_agent_users_columns( $columns ) { $columns['openstation_agent_type'] = __( 'Type', 'desktop-mode' ); return $columns; } add_filter( 'manage_users_columns', 'openstation_agent_users_columns' ); /** * Render the cell for the "Type" column. * * @param string $output Existing rendered HTML. * @param string $column_name Column id. * @param int $user_id User id being rendered. * @return string */ function openstation_agent_users_custom_column( $output, $column_name, $user_id ) { if ( 'openstation_agent_type' !== $column_name ) { return $output; } if ( openstation_agent_is_agent( $user_id ) ) { return '' . ' ' . esc_html__( 'Agent', 'desktop-mode' ) . ''; } return '' . esc_html__( 'Person', 'desktop-mode' ) . ''; } add_filter( 'manage_users_custom_column', 'openstation_agent_users_custom_column', 10, 3 );