# Lists WordPress users via WP-CLI. # $1 (domain): site domain name. function wordpressUserList() { local domain domain=$(domainPrepare "$1") domainCheck "$domain" || return 1 wordpressExec "$domain" user list } # Sets a WordPress user's password via WP-CLI. # $1 (domain): site domain name. # $2 (user): WordPress username or ID. # $3 (pass): new password. function wordpressPasswordSet() { local domain domain=$(domainPrepare "$1") domainCheck "$domain" || return 1 local user="$2" [[ -n "$user" ]] || { appError "User not specified"; return 1; } local pass="$3" [[ -n "$pass" ]] || { appError "Password not specified"; return 1; } wordpressExec "$domain" user update "$user" --user_pass="$pass" } # Runs WP-CLI inside the OLS pod for the specified domain. # $1 (domain): site domain name. # $2+ (...): WP-CLI arguments. function wordpressExec() { local domain="$1" [[ -n "$domain" ]] || { appError "Domain not specified"; return 1; } domain=$(domainPrepare "$domain") shift || true openlitespeedExec wp --path="$olsPodVhostsPath/$domain/www" --allow-root --skip-plugins --skip-themes --require="$olsPodPrivatePath/$domain/bootstrap.php" --exec='error_reporting(0);define("WP_DEBUG",false);' "$@" } function wordpressSalt() { local domain="$1" [[ -n "$domain" ]] || { appError "Domain not specified"; return 1; } domain=$(domainPrepare "$domain") shift || true wordpressExec "$domain" config shuffle-salts; } # Replaces a string in the WordPress database via WP-CLI search-replace. # $1 (domain): site domain name. # $2 (search): string to search for. # $3 (replace): replacement string. function wordpressSearchReplace() { local domain domain=$(domainPrepare "$1") domainCheck "$domain" || return 1 local search="$2" [[ -n "$search" ]] || { appError "Search string not specified"; return 1; } local replace="$3" [[ -n "$replace" ]] || { appError "Replacement string not specified"; return 1; } [[ "$search" == "$replace" ]] && return 0 wordpressExec "$domain" search-replace "$search" "$replace" --all-tables-with-prefix --precise --skip-columns=guid --report-changed-only } # Writes the bootstrap.php configuration file for a site. # $1 (domain): site domain name. function wordpressConfigUpdate() { local domain="$1" domain=$(domainPrepare "$domain") domainCheck "$domain" || return 1 local ug bootstrapFile tmpFile ug=$(domainToUser "$domain") bootstrapFile="$olsPrivatePath/$domain/bootstrap.php" tmpFile="$bootstrapFile".tmp local databaseName databaseUser databasePass redisUser redisPass postfixUser postfixPass key databaseName="$(siteConfigGet "$domain" "databaseName")" databaseUser="$(siteConfigGet "$domain" "databaseUser")" databasePass="$(siteConfigGet "$domain" "databasePass")" redisUser="$(siteConfigGet "$domain" "redisUser")" redisPass="$(siteConfigGet "$domain" "redisPass")" postfixUser="$(siteConfigGet "$domain" "postfixUser")" postfixPass="$(siteConfigGet "$domain" "postfixPass")" for key in databaseName databaseUser databasePass redisUser redisPass postfixUser postfixPass; do [[ -n "${!key}" ]] || { appError "wordpressConfigUpdate: $key is empty"; return 1; } done # aliases... local aliasList aliasFirst error run aliasList error openlitespeedConfigVhostAliasList "$domain" aliasFirst=$(awk 'NR==1' <<< "$aliasList") cat > "$tmpFile" <> "$tmpFile" chown -R -- "$ug:$ug" "$tmpFile" || { appError "Change owner of vhost data directory failed: $tmpFile"; return 1; } chmod 600 -- "$tmpFile" || { appError "Change permissions of vhost data files failed: $tmpFile"; return 1; } mv -f -- "$tmpFile" "$bootstrapFile" || return 1 } # Wraps WordPress define() calls to be conditional (defined() || define(...)). # $1 (domain): site domain name. function wordpressConfigDefine() { local domain domain=$(domainPrepare "$1") domainCheck "$domain" || return 1 local configFile="$olsVhostsPath/$domain/www/wp-config.php" [[ -f "$configFile" ]] || { appError "File not found: $configFile"; return 1; } local constants=( DB_NAME DB_USER DB_PASSWORD DB_HOST DB_CHARSET DB_COLLATE WP_REDIS_SELECTIVE_FLUSH WP_REDIS_PASSWORD WP_REDIS_PREFIX WP_REDIS_PORT WP_REDIS_HOST WP_REDIS_CLIENT SODEW_SMTP_USER SODEW_SMTP_PASS SODEW_SMTP_HOST SODEW_SMTP_POSTMASTER ) local const for const in "${constants[@]}"; do sed -i -E "s@^([[:space:]]*)(define[[:space:]]*\([[:space:]]*['\"]${const}['\"][[:space:]]*,)@\1defined('${const}') || \2@" "$configFile" done } # Rebuilds WordPress configuration for a site: defines, bootstrap, and mu-plugins. # $1 (domain): site domain name. function wordpressConfigRebuild() { local domain domain=$(domainPrepare "$1") domainCheck "$domain" || return 1 wordpressConfigDefine "$domain" || return 1 wordpressConfigUpdate "$domain" || return 1 local muPluginsPath ug muPluginsPath="$olsVhostsPath/$domain/www/wp-content/mu-plugins" ug=$(domainToUser "$domain") [[ -d "$muPluginsPath" ]] || mkdir -p -- "$muPluginsPath" || { appError "Create directory failed: $muPluginsPath"; return 1; } cp -f -- "$appAssetsPath/wordpress/shared/00-hosting-loader.php" "$muPluginsPath/00-hosting-loader.php" || { appError "Copy file failed: $muPluginsPath/00-hosting-loader.php"; return 1; } chown -R -- "$ug:$ug" "$muPluginsPath" || { appError "Change owner of directory failed: $muPluginsPath"; return 1; } chmod 2750 "$muPluginsPath" || { appError "Change permissions of directories failed: $muPluginsPath"; return 1; } chmod 0640 "$muPluginsPath/00-hosting-loader.php" || { appError "Change permissions of file failed: $muPluginsPath/00-hosting-loader.php"; return 1; } } # Placeholder for extended WordPress config rebuild (not yet implemented). # $1 (domain): site domain name. function wordpressConfigRebuildEx() { echo '*****' } # Updates all WordPress URLs in DB to match the current domain, cleans cache and Redis. # $1 (domain): site domain name. # [$2] (abspathOld): old absolute path to replace. function wordpressDomainUpdate() { local domain="$1" [[ -n "$domain" ]] || { printDanger "$wordpressLabel Domain not specified"; return 1; } local siteNew="https://$domain" local abspathOld="$2" local isMultiSite isMultiSite=$(wordpressExec "$domain" eval 'echo is_multisite() ? 1 : 0;') if [[ "$isMultiSite" == "1" ]]; then printDanger "$wordpressLabel This script is for SINGLE SITE only. Detected multisite. Abort." return 1 fi local siteConst homeConst siteOption homeOption siteConst=$(wordpressExec "$domain" eval 'echo defined("WP_SITEURL")?WP_SITEURL:"";' || true) siteConst=$(strTrimSlash "$siteConst") homeConst=$(wordpressExec "$domain" eval 'echo defined("WP_HOME")?WP_HOME:"";' || true) homeConst=$(strTrimSlash "$homeConst") siteOption=$(wordpressExec "$domain" option get siteurl 2>/dev/null || true) siteOption=$(strTrimSlash "$siteOption") homeOption=$(wordpressExec "$domain" option get home 2>/dev/null || true) homeOption=$(strTrimSlash "$homeOption") printInfo "$wordpressLabel Wordpress siteurl | Const: $siteConst | Option: $siteOption" printInfo "$wordpressLabel Wordpress home | Const: $homeConst | Option: $homeOption" local siteOld="${siteConst:-$siteOption}" if [[ -z "$siteOld" ]]; then siteOld="${homeConst:-$homeOption}" fi if [[ -z "$siteOld" ]]; then appError "Could not detect siteOld (neither constants nor DB options present)." return 2 fi local schemeOld hostOld rootOld schemeOld=$(printf '%s' "$siteOld" | awk -F:// '{print $1}') hostOld=$(printf '%s' "$siteOld" | awk -F[/:] '{print $4}') rootOld="$schemeOld://$hostOld" printInfo "$wordpressLabel Wordpress OLD | Site: $siteOld | Scheme: $schemeOld | Host: $hostOld | Root: $rootOld" local sitePath homePath sitePath=$(wordpressExec "$domain" eval 'echo parse_url(get_option("siteurl"), PHP_URL_PATH)?:"";' || true) [[ "$sitePath" == "/" ]] && sitePath="" homePath=$(wordpressExec "$domain" eval 'echo parse_url(get_option("home"), PHP_URL_PATH)?:"";' || true) [[ "$homePath" == "/" ]] && homePath="" local wpType="unknown" if [[ -z "$homePath" && -z "$sitePath" ]]; then wpType="single_root" elif [[ -n "$homePath" && -n "$sitePath" && "$homePath" == "$sitePath" ]]; then wpType="single_subdir" elif [[ -z "$homePath" && -n "$sitePath" ]]; then wpType="single_mixed" fi printInfo "$wordpressLabel Wordpress OLD | Type: $wpType" local siteConstHas homeConstHas siteConstHas=$(wordpressExec "$domain" eval 'echo defined("WP_SITEURL")?1:0;') if [[ "$siteConstHas" == "1" ]]; then wordpressExec "$domain" config delete WP_SITEURL --type=constant || true fi homeConstHas=$(wordpressExec "$domain" eval 'echo defined("WP_HOME")?1:0;') if [[ "$homeConstHas" == "1" ]]; then wordpressExec "$domain" config delete WP_HOME --type=constant || true fi printInfo "$wordpressLabel Update siteurl: $siteNew" wordpressExec "$domain" option update siteurl "$siteNew" printInfo "$wordpressLabel Update home: $siteNew" wordpressExec "$domain" option update home "$siteNew" printInfo "$wordpressLabel Replace in DB (1): $siteOld --> $siteNew" wordpressSearchReplace "$domain" "$siteOld" "$siteNew" if [[ -n "$homeOption" && "$homeOption" != "$siteOld" ]]; then printInfo "$wordpressLabel Replace in DB (2): $homeOption --> $siteNew" wordpressSearchReplace "$domain" "$homeOption" "$siteNew" fi if [[ -n "$siteOption" && "$siteOption" != "$siteOld" && "$siteOption" != "$homeOption" ]]; then printInfo "$wordpressLabel Replace in DB (3): $siteOption --> $siteNew" wordpressSearchReplace "$domain" "$siteOption" "$siteNew" fi if [[ -n "$hostOld" ]]; then printInfo "$wordpressLabel Replace in DB (4): //$hostOld --> $siteNew" wordpressSearchReplace "$domain" "//$hostOld" "$siteNew" fi if [[ "$wpType" == "single_mixed" ]]; then printInfo "$wordpressLabel Replace in DB (5): $rootOld --> $siteNew" wordpressSearchReplace "$domain" "$rootOld" "$siteNew" fi if [[ -n "$abspathOld" ]]; then printInfo "$wordpressLabel Replace in DB (6): $abspathOld --> $olsPodVhostsPath/$domain/www" wordpressSearchReplace "$domain" "$abspathOld" "$olsPodVhostsPath/$domain/www" fi printInfo "$wordpressLabel Replace in DB (7): $hostOld --> $domain" wordpressSearchReplace "$domain" "$hostOld" "$domain" printInfo "$wordpressLabel Delete options: upload_path/upload_url_path..." wordpressExec "$domain" option delete upload_path || true wordpressExec "$domain" option delete upload_url_path || true printInfo "$wordpressLabel Clean cache..." wordpressExec "$domain" transient delete --all || true printInfo "$wordpressLabel Redis clean..." redisDomainClean "$domain" || true }