From 525ccf25ef7561b1d069c3a4701810a58bf8be6a Mon Sep 17 00:00:00 2001 From: Jason Raveling Date: Fri, 23 Jan 2026 15:46:23 -0600 Subject: [PATCH 1/3] feat(user creation): initial commit of user creation script --- user-create.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 user-create.sh diff --git a/user-create.sh b/user-create.sh new file mode 100644 index 0000000..9088586 --- /dev/null +++ b/user-create.sh @@ -0,0 +1,66 @@ +#!/bin/env bash + +# Creates users from a CSV. On multisite, adds user to every site. +# +# CSV expects to have the following values with no header row as labels: +# username +# email +# role (a valid WP role) +# superadmin (1 or 0) + +source 'source/includes.sh'; + +# Check if this is a multisite/network installation of WordPress. +is_multisite=$(wp config get MULTISITE); + +echo; + +if [ "$is_multisite" == 1 ]; then + echo 'Multisite detected'; + echo ' Users will be added to every network site'; +else + echo 'Multisite NOT detected'; +fi + +echo; + +# Prompt the user for the path to a CSV with username and email. +read -r -p 'Path to CSV file with users [./user-create.csv]: ' csv_path; + +# Set default value if empty string provided. +[[ -z "$csv_path" ]] && csv_path='./user-create.csv'; + +# Ensure the file actually exists. +[[ ! -f "$csv_path" ]]; then + + echo "The file you provided does not exist: ${csv_path}"; + exit 1; + +fi + +###################################################### +# Read the CSV and create the user(s) +###################################################### + +# Init the user counter. +user_count=0; + +# Loop over the entire CSV file. +while IFS="," read -r username email role superadmin; do + + # Create the user. + new_user_id=$(wp_skip_all user create --porcelain "$username" "$email" --role="$role"); + + # Check if the user should be a superadmin. + if [[ "1" == "$superadmin" ]]; then + + wp super-admin add $username; + + fi + + # Update the count for each successful user creation. + [[ new_user_id > 0 ]] && ((user_count++)); + +done < "$csv_path" + +echo "Users added: ${user_count}"; From 91836e39ecf32113afa361a435dd862b978eb3c7 Mon Sep 17 00:00:00 2001 From: Jason Raveling Date: Fri, 23 Jan 2026 16:36:20 -0600 Subject: [PATCH 2/3] feat(user creation): uses correct wp_skip_all() and checks successful add --- user-create.sh | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/user-create.sh b/user-create.sh index 9088586..94fe3a5 100644 --- a/user-create.sh +++ b/user-create.sh @@ -11,7 +11,7 @@ source 'source/includes.sh'; # Check if this is a multisite/network installation of WordPress. -is_multisite=$(wp config get MULTISITE); +is_multisite=$(wp_skip_all config get MULTISITE); echo; @@ -31,7 +31,7 @@ read -r -p 'Path to CSV file with users [./user-create.csv]: ' csv_path; [[ -z "$csv_path" ]] && csv_path='./user-create.csv'; # Ensure the file actually exists. -[[ ! -f "$csv_path" ]]; then +if [[ ! -f "$csv_path" ]]; then echo "The file you provided does not exist: ${csv_path}"; exit 1; @@ -49,17 +49,25 @@ user_count=0; while IFS="," read -r username email role superadmin; do # Create the user. - new_user_id=$(wp_skip_all user create --porcelain "$username" "$email" --role="$role"); + if wp_skip_all user create --porcelain "$username" "$email" --role="$role" > /dev/null; then - # Check if the user should be a superadmin. - if [[ "1" == "$superadmin" ]]; then + # Update the count for each successful user creation. + ((user_count++)); - wp super-admin add $username; + echo "'$username' was successfully created."; - fi + # Check if the user should be a superadmin. + if [[ "1" == "$superadmin" ]]; then + + wp_skip_all super-admin add $username; + + fi - # Update the count for each successful user creation. - [[ new_user_id > 0 ]] && ((user_count++)); + else + + >&2 + + fi done < "$csv_path" From e6dbd11602e022fffea13be6a60429e35b8908b7 Mon Sep 17 00:00:00 2001 From: Jason Raveling Date: Fri, 23 Jan 2026 16:50:59 -0600 Subject: [PATCH 3/3] feat(user creation): adds users to each site --- user-create.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/user-create.sh b/user-create.sh index 94fe3a5..cd6fc60 100644 --- a/user-create.sh +++ b/user-create.sh @@ -48,8 +48,8 @@ user_count=0; # Loop over the entire CSV file. while IFS="," read -r username email role superadmin; do - # Create the user. - if wp_skip_all user create --porcelain "$username" "$email" --role="$role" > /dev/null; then + # Create the user. Only output WPCLI success message on successful creation. + if new_user_id=$(wp_skip_all user create --porcelain "$username" "$email" --role="$role" >&1 ); then # Update the count for each successful user creation. ((user_count++)); @@ -61,10 +61,20 @@ while IFS="," read -r username email role superadmin; do wp_skip_all super-admin add $username; + else + + for site_url in $(wp_skip_all site list --field="url" --archived=0 --deleted=0 --spam=0); do + + # The user is not a superadmin so add them to each site individually. + wp_on_site user set-role "$new_user_id" "$role"; + + done; + fi else + # Output any errors from WPCLI. >&2 fi