#!/bin/bash
# php-versions.sh - list every vhost on a cPanel/CloudLinux server with its
# effective PHP version, grouped by version.
#
# Sources, in order of preference:
#   1. Apache handler lines in httpd.conf (ea-phpNN / alt-phpNN)
#   2. PHP-FPM pool files (/opt/cpanel/ea-php*/root/etc/php-fpm.d/<domain>.conf)
#   3. WHM MultiPHP setting (whmapi1 php_get_vhost_versions)
# Where (1) or (2) disagrees with (3), the line is flagged "WHM says ...".
#
# Usage (as root):   bash php-versions.sh [output-file]

set -u

if [[ $EUID -ne 0 ]]; then
    echo "Run as root." >&2
    exit 1
fi

command -v whmapi1 >/dev/null || { echo "whmapi1 not found - is this a WHM server?" >&2; exit 1; }
command -v python3 >/dev/null || { echo "python3 not found." >&2; exit 1; }

OUTFILE="${1:-}"
HTTPD_CONF=/etc/apache2/conf/httpd.conf

declare -A WHM   # domain -> version according to WHM MultiPHP
declare -A EFF   # domain -> version according to Apache / FPM
declare -A SRC   # domain -> where EFF came from

# 1. WHM MultiPHP
while read -r dom ver; do
    [[ -n "$dom" ]] && WHM["$dom"]="$ver"
done < <(whmapi1 php_get_vhost_versions --output=json 2>/dev/null | python3 -c '
import sys, json
try:
    for v in json.load(sys.stdin)["data"]["versions"]:
        print(v["vhost"], v["version"])
except Exception as e:
    sys.stderr.write("Could not parse whmapi1 output: %s\n" % e)
')

# 2. Apache handler lines inside each VirtualHost
if [[ -r "$HTTPD_CONF" ]]; then
    while read -r ver dom; do
        [[ -n "$dom" ]] && { EFF["$dom"]="$ver"; SRC["$dom"]="apache handler"; }
    done < <(awk '
        /<VirtualHost/            { name="" }
        /^[[:space:]]*ServerName[[:space:]]/ { name=$2 }
        /x-httpd-(ea|alt)-php[0-9]+/ {
            if (match($0, /(ea|alt)-php[0-9]+/) && name != "")
                print substr($0, RSTART, RLENGTH), name
        }' "$HTTPD_CONF")
fi

# 3. PHP-FPM pools (file name is the domain, folder is the PHP version)
for f in /opt/cpanel/ea-php*/root/etc/php-fpm.d/*.conf; do
    [[ -e "$f" ]] || continue
    [[ "$f" == *www.conf ]] && continue
    ver=$(echo "$f" | grep -o 'ea-php[0-9]*' | head -1)
    dom=$(basename "$f" .conf)
    EFF["$dom"]="$ver"
    SRC["$dom"]="php-fpm pool"
done

# Merge: every domain seen anywhere
declare -A ALL
for d in "${!WHM[@]}" "${!EFF[@]}"; do ALL["$d"]=1; done

report() {
    echo "PHP versions on $(hostname) - $(date '+%Y-%m-%d %H:%M')"
    for d in "${!ALL[@]}"; do
        eff="${EFF[$d]:-}"
        whm="${WHM[$d]:-}"
        if [[ -n "$eff" ]]; then
            note="${SRC[$d]}"
            [[ -n "$whm" && "$whm" != "$eff" ]] && note="$note; WHM says $whm"
            printf '%s\t%s\t%s\n' "$eff" "$d" "$note"
        else
            printf '%s\t%s\t%s\n' "$whm" "$d" "WHM only"
        fi
    done | sort -t$'\t' -k1,1 -k2,2 | awk -F'\t' '
        {
            if ($1 != last) {
                if (last != "") printf "\n"
                printf "\n== %s ==\n", $1
                last = $1
            }
            n[$1]++
            if ($3 == "WHM only" || $3 == "apache handler" || $3 == "php-fpm pool")
                printf "  %s\n", $2
            else
                printf "  %s   [%s]\n", $2, $3
        }
        END {
            printf "\n\nSummary\n"
            for (v in n) printf "  %-14s %d\n", v, n[v]
        }'
}

if [[ -n "$OUTFILE" ]]; then
    report | tee "$OUTFILE"
    echo "Saved to $OUTFILE" >&2
else
    report
fi

